@pheem49/mint 1.15.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (644) hide show
  1. package/Cargo.lock +1012 -69
  2. package/Cargo.toml +5 -2
  3. package/LICENSE +21 -654
  4. package/README.md +92 -817
  5. package/Release_Note.md +53 -560
  6. package/apps/mint-companion/src-tauri/Cargo.toml +20 -0
  7. package/apps/mint-companion/src-tauri/build.rs +3 -0
  8. package/apps/mint-companion/src-tauri/src/main.rs +468 -0
  9. package/apps/mint-companion/tsconfig.json +20 -0
  10. package/apps/mint-companion/vite.config.ts +3 -0
  11. package/components.json +19 -0
  12. package/crates/mint-cli/Cargo.toml +6 -0
  13. package/crates/mint-cli/src/agent/live_status.rs +187 -39
  14. package/crates/mint-cli/src/agent.rs +323 -95
  15. package/crates/mint-cli/src/commands/agent.rs +69 -55
  16. package/crates/mint-cli/src/commands/integrations.rs +7 -0
  17. package/crates/mint-cli/src/commands/knowledge.rs +12 -32
  18. package/crates/mint-cli/src/commands/mod.rs +44 -0
  19. package/crates/mint-cli/src/image.rs +31 -33
  20. package/crates/mint-cli/src/interactive/chat_tui.rs +3594 -483
  21. package/crates/mint-cli/src/interactive/input_box.rs +56 -6
  22. package/crates/mint-cli/src/interactive/slash_commands.rs +208 -56
  23. package/crates/mint-cli/src/interactive/tool_activity.rs +328 -0
  24. package/crates/mint-cli/src/interactive.rs +64 -40
  25. package/crates/mint-cli/src/main.rs +13 -7
  26. package/crates/mint-cli/src/mcp.rs +5 -0
  27. package/crates/mint-cli/src/mod_host.rs +6 -0
  28. package/crates/mint-cli/src/mods_cli.rs +62 -0
  29. package/crates/mint-cli/src/mods_ui.rs +187 -0
  30. package/crates/mint-cli/src/onboard.rs +5 -31
  31. package/crates/mint-cli/src/terminal_theme.rs +3 -1
  32. package/crates/mint-cli/src/updater.rs +56 -2
  33. package/crates/mint-cli/tests/library_intake.rs +77 -0
  34. package/crates/mint-cli/tests/mods_testing.rs +133 -0
  35. package/crates/mint-companion-protocol/Cargo.toml +10 -0
  36. package/crates/mint-companion-protocol/src/lib.rs +163 -0
  37. package/crates/mint-core/Cargo.toml +6 -3
  38. package/crates/mint-core/build.rs +26 -0
  39. package/crates/mint-core/src/agent/chat.rs +167 -39
  40. package/crates/mint-core/src/agent/code_tools.rs +15 -0
  41. package/crates/mint-core/src/agent/memory/sources.rs +240 -0
  42. package/crates/mint-core/src/agent/memory.rs +147 -13
  43. package/crates/mint-core/src/agent/skill_inventory.rs +325 -0
  44. package/crates/mint-core/src/agent/skills.rs +437 -90
  45. package/crates/mint-core/src/agent.rs +1 -0
  46. package/crates/mint-core/src/api_server/routes/background_jobs.rs +310 -0
  47. package/crates/mint-core/src/api_server/routes/chat.rs +216 -199
  48. package/crates/mint-core/src/api_server/routes/html_preview.rs +77 -0
  49. package/crates/mint-core/src/api_server/routes/library.rs +97 -0
  50. package/crates/mint-core/src/api_server/routes/media_gen.rs +10 -57
  51. package/crates/mint-core/src/api_server/routes/misc.rs +104 -107
  52. package/crates/mint-core/src/api_server/routes/mod.rs +6 -0
  53. package/crates/mint-core/src/api_server/routes/mods.rs +31 -0
  54. package/crates/mint-core/src/api_server/routes/sessions.rs +41 -0
  55. package/crates/mint-core/src/api_server/routes/skills_subagents.rs +12 -42
  56. package/crates/mint-core/src/api_server/routes/slash.rs +50 -1
  57. package/crates/mint-core/src/api_server/routes/sources.rs +101 -0
  58. package/crates/mint-core/src/api_server.rs +118 -9
  59. package/crates/mint-core/src/avatar_bridge.rs +11 -2
  60. package/crates/mint-core/src/browser/session.rs +52 -0
  61. package/crates/mint-core/src/companion.rs +716 -0
  62. package/crates/mint-core/src/cron/scheduler.rs +34 -2
  63. package/crates/mint-core/src/integrations/channels.rs +87 -345
  64. package/crates/mint-core/src/integrations/mcp.rs +397 -50
  65. package/crates/mint-core/src/integrations/mcp_calls.rs +823 -0
  66. package/crates/mint-core/src/integrations/mcp_catalog.rs +267 -0
  67. package/crates/mint-core/src/integrations/mcp_device.rs +319 -0
  68. package/crates/mint-core/src/integrations/mcp_result.rs +356 -0
  69. package/crates/mint-core/src/integrations/webhooks.rs +539 -0
  70. package/crates/mint-core/src/integrations.rs +2 -0
  71. package/crates/mint-core/src/lib.rs +85 -26
  72. package/crates/mint-core/src/media/gemini_live.rs +134 -14
  73. package/crates/mint-core/src/media/image_models.rs +3 -27
  74. package/crates/mint-core/src/media/image_workflow.rs +216 -0
  75. package/crates/mint-core/src/media/library/intake.rs +144 -0
  76. package/crates/mint-core/src/media/library/migration.rs +56 -0
  77. package/crates/mint-core/src/media/library/removal.rs +55 -0
  78. package/crates/mint-core/src/media/library/tests.rs +730 -0
  79. package/crates/mint-core/src/media/library/thumbnails.rs +72 -0
  80. package/crates/mint-core/src/media/library.rs +545 -0
  81. package/crates/mint-core/src/media/model_catalog.rs +375 -0
  82. package/crates/mint-core/src/media/pictures.rs +79 -222
  83. package/crates/mint-core/src/media/video_models.rs +3 -22
  84. package/crates/mint-core/src/media.rs +3 -0
  85. package/crates/mint-core/src/mods/manager.rs +1124 -0
  86. package/crates/mint-core/src/mods/mod.rs +569 -0
  87. package/crates/mint-core/src/mods/operations.rs +204 -0
  88. package/crates/mint-core/src/mods/session.rs +146 -0
  89. package/crates/mint-core/src/mods/slash.rs +59 -0
  90. package/crates/mint-core/src/mods/telemetry.rs +306 -0
  91. package/crates/mint-core/src/orchestration/approvals.rs +344 -0
  92. package/crates/mint-core/src/orchestration/context_render.rs +104 -0
  93. package/crates/mint-core/src/orchestration/mcp_review.rs +153 -0
  94. package/crates/mint-core/src/orchestration/memory_skill.rs +104 -32
  95. package/crates/mint-core/src/orchestration/mod.rs +2139 -244
  96. package/crates/mint-core/src/orchestration/mod_authoring_regressions.rs +209 -0
  97. package/crates/mint-core/src/orchestration/progress_clock.rs +80 -0
  98. package/crates/mint-core/src/orchestration/repeated_failures.rs +116 -0
  99. package/crates/mint-core/src/orchestration/review_regressions.rs +449 -0
  100. package/crates/mint-core/src/orchestration/run_control.rs +196 -0
  101. package/crates/mint-core/src/orchestration/tools/files.rs +161 -14
  102. package/crates/mint-core/src/orchestration/tools/media.rs +37 -41
  103. package/crates/mint-core/src/orchestration/tools/misc.rs +3 -2
  104. package/crates/mint-core/src/orchestration/tools/mod.rs +2 -0
  105. package/crates/mint-core/src/orchestration/tools/mods.rs +161 -0
  106. package/crates/mint-core/src/orchestration/tools/plugins_mcp.rs +303 -71
  107. package/crates/mint-core/src/orchestration/tools/shell.rs +95 -2
  108. package/crates/mint-core/src/orchestration/workspace_helpers.rs +4 -1
  109. package/crates/mint-core/src/prompts/agent.rs +17 -2
  110. package/crates/mint-core/src/prompts/tool_catalog.rs +28 -2
  111. package/crates/mint-core/src/search/knowledge.rs +7 -1
  112. package/crates/mint-core/src/search/linked_folders/index.rs +177 -13
  113. package/crates/mint-core/src/search/linked_folders.rs +83 -2
  114. package/crates/mint-core/src/slash/catalog.rs +1 -1
  115. package/crates/mint-core/src/slash/mod.rs +174 -11
  116. package/crates/mint-core/src/slash/mods.rs +155 -0
  117. package/crates/mint-core/src/system/bg_shell.rs +1129 -95
  118. package/crates/mint-core/src/system/config.rs +5 -10
  119. package/crates/mint-core/src/system/html_preview.rs +398 -0
  120. package/crates/mint-core/src/system/mint_web.rs +164 -0
  121. package/crates/mint-core/src/system/release_notes.rs +18 -0
  122. package/crates/mint-core/src/system/shell.rs +21 -6
  123. package/crates/mint-core/src/system/workspace.rs +72 -8
  124. package/crates/mint-core/src/system/workspace_history.rs +604 -0
  125. package/crates/mint-core/src/system.rs +4 -0
  126. package/crates/mint-core/tests/background_retention.rs +34 -0
  127. package/crates/mint-core/tests/background_shutdown.rs +24 -0
  128. package/crates/mint-core/tests/library_http.rs +209 -0
  129. package/crates/mint-core/tests/mcp_contract.rs +283 -0
  130. package/crates/mint-core/tests/mcp_stdio.rs +11 -10
  131. package/crates/mint-core/tests/media_model_catalog_http.rs +403 -0
  132. package/crates/mint-core/tests/mods_http.rs +215 -0
  133. package/crates/mint-core/tests/terminal_shutdown.rs +109 -0
  134. package/crates/mint-mod-runtime/Cargo.toml +18 -0
  135. package/crates/mint-mod-runtime/src/lib.rs +507 -0
  136. package/crates/mint-mod-runtime/src/sdk.js +56 -0
  137. package/crates/mint-mod-runtime/src/test_sdk.js +32 -0
  138. package/crates/mint-mod-runtime/src/testing.rs +94 -0
  139. package/crates/mint-mod-runtime/tests/runtime.rs +156 -0
  140. package/docs/mods/AUTHORING.md +61 -0
  141. package/docs/mods/README.md +139 -0
  142. package/docs/mods/TESTING.md +56 -0
  143. package/docs/mods/mint-mods.d.ts +66 -0
  144. package/examples/device-mcp/README.md +22 -0
  145. package/examples/device-mcp/contract.md +49 -0
  146. package/examples/device-mcp/mock-device.mjs +66 -0
  147. package/examples/device-mcp/server.mjs +48 -0
  148. package/examples/device-mcp/server.test.mjs +78 -0
  149. package/examples/mods/task-checklist/README.md +1 -0
  150. package/examples/mods/task-checklist/main.ts +17 -0
  151. package/examples/mods/task-checklist/manifest.json +1 -0
  152. package/examples/mods/task-checklist/tests/checklist.test.ts +15 -0
  153. package/examples/mods/token-meter/README.md +1 -0
  154. package/examples/mods/token-meter/main.ts +8 -0
  155. package/examples/mods/token-meter/manifest.json +1 -0
  156. package/examples/mods/tool-guard/README.md +1 -0
  157. package/examples/mods/tool-guard/main.ts +9 -0
  158. package/examples/mods/tool-guard/manifest.json +1 -0
  159. package/out/web/assets/CliSessionsView-CtzUJpK_.css +1 -0
  160. package/out/web/assets/CliSessionsView-D7hw0Mgj.js +1 -0
  161. package/out/web/assets/CodeReviewPage-C7bEOJfd.js +4 -0
  162. package/out/web/assets/CodeReviewPage-Dte9uLiL.css +1 -0
  163. package/out/web/assets/CommandPalette-0RrF-AOT.js +1 -0
  164. package/out/web/assets/ImageStudioPanel-CdxkAf_r.js +1 -0
  165. package/out/web/assets/LibraryPage--Qfisp6D.js +2 -0
  166. package/out/web/assets/LibraryPage-DAxUTAg7.css +1 -0
  167. package/out/web/assets/LinkedFoldersView-2nfZbDgN.js +1 -0
  168. package/out/web/assets/McpRegistryPicker-h9uS8_wT.js +1 -0
  169. package/out/web/assets/McpServersView-slfQJzNB.js +1 -0
  170. package/out/web/assets/MintDashboard-BSR5XpXh.js +25 -0
  171. package/out/web/assets/MintDashboard-CWUcCGhd.css +1 -0
  172. package/out/web/assets/PluginsView-l7LSm503.js +1 -0
  173. package/out/web/assets/ScheduledTasksView-CttmLbq1.js +1 -0
  174. package/out/web/assets/SettingsWindow-BCMLYvEV.js +4 -0
  175. package/out/web/assets/SettingsWindow-DcMVmU9u.css +1 -0
  176. package/out/web/assets/SkillsView-rNs1qr_U.js +2 -0
  177. package/out/web/assets/ToolSurfacePage-B9DzEPWN.js +37 -0
  178. package/out/web/assets/ToolSurfacePage-CTfgggF2.css +1 -0
  179. package/out/web/assets/VeoStudioPanel-DiJs_Cg2.js +4 -0
  180. package/out/web/assets/WorkspaceSelector-B2xIp04D.js +1 -0
  181. package/out/web/assets/WorkspaceSelector-Ca8uJOsS.css +1 -0
  182. package/out/web/assets/{abnfDiagram-VCTEODGH-ByMyfanq.js → abnfDiagram-VCTEODGH-CD0CjoGl.js} +1 -1
  183. package/out/web/assets/{architecture-7GRP2DOG-CLq2kEOB.js → architecture-7GRP2DOG-RKV83OeZ.js} +1 -1
  184. package/out/web/assets/{architectureDiagram-5GKGNRK7-6PoVSmNG.js → architectureDiagram-5GKGNRK7-nN_HAFct.js} +1 -1
  185. package/out/web/assets/{blockDiagram-NRAW4CY4-cKw9mAKi.js → blockDiagram-NRAW4CY4-BrrqzHW5.js} +1 -1
  186. package/out/web/assets/{c4Diagram-UCG6FXSJ-Cqy8N5Ge.js → c4Diagram-UCG6FXSJ-DTdV8_zE.js} +1 -1
  187. package/out/web/assets/{chunk-75Z2AOVW-3qybijF5.js → chunk-75Z2AOVW-_M0z5olV.js} +1 -1
  188. package/out/web/assets/chunk-CKBBP62Z-BpQEgeHF.js +2 -0
  189. package/out/web/assets/{chunk-CLGD4ZFX-CndDQkww.js → chunk-CLGD4ZFX-D54yGvGS.js} +1 -1
  190. package/out/web/assets/{chunk-DSNCTWBM-Cc4NxvgD.js → chunk-DSNCTWBM-C-gvT2ru.js} +1 -1
  191. package/out/web/assets/{chunk-DU6HZSFF-drzh6GsU.js → chunk-DU6HZSFF-CnFngIhW.js} +1 -1
  192. package/out/web/assets/{chunk-F27PBJKO-FiY35l4v.js → chunk-F27PBJKO-BqtWrnEO.js} +1 -1
  193. package/out/web/assets/{chunk-G27WJ6UU-Bjt9Il4A.js → chunk-G27WJ6UU-Ckoq5mi2.js} +1 -1
  194. package/out/web/assets/{chunk-GMAD6QVW-Bppi3Ctd.js → chunk-GMAD6QVW-BuhEcgHq.js} +1 -1
  195. package/out/web/assets/{chunk-JQ64N6SF-DGg5kcEV.js → chunk-JQ64N6SF-CF8T7GiZ.js} +1 -1
  196. package/out/web/assets/{chunk-LCL6LL3I-CCYcjd7p.js → chunk-LCL6LL3I-BhXV9zyH.js} +1 -1
  197. package/out/web/assets/{chunk-OBVCFTLP-DJeNil5M.js → chunk-OBVCFTLP-CRIkunUB.js} +1 -1
  198. package/out/web/assets/{chunk-P2QGCYS3-lRzkRjBB.js → chunk-P2QGCYS3-UFEU6BxZ.js} +1 -1
  199. package/out/web/assets/{chunk-POPQ4Y6H-DouASMBW.js → chunk-POPQ4Y6H-CQcrNbjr.js} +1 -1
  200. package/out/web/assets/{chunk-PWAF6VOD-DMmD1vVf.js → chunk-PWAF6VOD-Cc2uVDsG.js} +1 -1
  201. package/out/web/assets/{chunk-R7TYR2AO-CYLA5UC5.js → chunk-R7TYR2AO-DiCxzdAY.js} +1 -1
  202. package/out/web/assets/{chunk-RHFEMEQ7-BiXwEcUT.js → chunk-RHFEMEQ7-b7hnPmrR.js} +1 -1
  203. package/out/web/assets/{chunk-SVP7TREG-BV-zPslF.js → chunk-SVP7TREG-Bu_yYb-V.js} +1 -1
  204. package/out/web/assets/{chunk-TEH6E4GO-B2RGEohZ.js → chunk-TEH6E4GO-G4Cdlyrt.js} +1 -1
  205. package/out/web/assets/classDiagram-DTDB5LWJ-RnC2mYO4.js +1 -0
  206. package/out/web/assets/classDiagram-v2-JRS7N3AN-RnC2mYO4.js +1 -0
  207. package/out/web/assets/config-CnvCChUM.js +2 -0
  208. package/out/web/assets/config-DM6oIVO3.css +1 -0
  209. package/out/web/assets/core-DsKkQ7ig.js +1 -0
  210. package/out/web/assets/{cynefin-OW5HDTMX-Cas4csHM.js → cynefin-OW5HDTMX-CnzQfOGp.js} +1 -1
  211. package/out/web/assets/{cynefinDiagram-5FMLGOSQ-Bbpj66Y3.js → cynefinDiagram-5FMLGOSQ-DVtQnfpm.js} +1 -1
  212. package/out/web/assets/{dagre-3AP2YEHR-B0-2RDEd.js → dagre-3AP2YEHR-DG76_k5_.js} +1 -1
  213. package/out/web/assets/{diagram-S7CK7UJ4-BdzEjUyH.js → diagram-S7CK7UJ4-CaouUoze.js} +1 -1
  214. package/out/web/assets/{diagram-UQ7AKVKN-CJDwyPxF.js → diagram-UQ7AKVKN-B4bEc26B.js} +1 -1
  215. package/out/web/assets/{diagram-VSXAHHWV-BxaG1r_B.js → diagram-VSXAHHWV-BJ86Ov2Y.js} +1 -1
  216. package/out/web/assets/{diagram-VX7I27RA-BMmUqm8f.js → diagram-VX7I27RA-7hH5IPYf.js} +1 -1
  217. package/out/web/assets/{diagram-Z3DM3KII-CFtd03eE.js → diagram-Z3DM3KII-CCM4clo8.js} +1 -1
  218. package/out/web/assets/dist-js-BkYNznHX.js +1 -0
  219. package/out/web/assets/{ebnfDiagram-PWID7BFC-DwAen1hO.js → ebnfDiagram-PWID7BFC-Da7WAM3k.js} +1 -1
  220. package/out/web/assets/{erDiagram-SSCWMZ5O-BCZSHACj.js → erDiagram-SSCWMZ5O-CzzmnZWT.js} +1 -1
  221. package/out/web/assets/{event-ChBVpRy0.js → event-Cdt7Byyj.js} +1 -1
  222. package/out/web/assets/{eventmodeling-NTZA5JFV-XHStE4E_.js → eventmodeling-NTZA5JFV-xcfsA0XD.js} +1 -1
  223. package/out/web/assets/flowDiagram-A5DVABFB-JdtH1673.js +1 -0
  224. package/out/web/assets/{ganttDiagram-EL5Y4UJY-BAEu1Cql.js → ganttDiagram-EL5Y4UJY-B3ClFGmL.js} +1 -1
  225. package/out/web/assets/{gitGraph-4MIJSDKK-r32Vyper.js → gitGraph-4MIJSDKK-BZ_y_cDU.js} +1 -1
  226. package/out/web/assets/{gitGraphDiagram-WWUBYQGX-z9o9qt6V.js → gitGraphDiagram-WWUBYQGX-drhRSYm3.js} +1 -1
  227. package/out/web/assets/index-BZ9xgmMP.css +1 -0
  228. package/out/web/assets/index-Ca8cCS4h.js +168 -0
  229. package/out/web/assets/{info-A6RAGUB7-BvLaC2cw.js → info-A6RAGUB7-B7I3K0F1.js} +1 -1
  230. package/out/web/assets/{infoDiagram-RXCK75RN-Be6WAXXw.js → infoDiagram-RXCK75RN-deX_1MPh.js} +1 -1
  231. package/out/web/assets/{ishikawaDiagram-5VMMS53U-DZjoHJHC.js → ishikawaDiagram-5VMMS53U-s38yo28y.js} +1 -1
  232. package/out/web/assets/{journeyDiagram-EYS64GPL-CtVkjkGm.js → journeyDiagram-EYS64GPL-CZn2kB8b.js} +1 -1
  233. package/out/web/assets/jsx-runtime-DN4NhQUK.js +1 -0
  234. package/out/web/assets/{kanban-definition-3QL26DDD-CW5FMv1w.js → kanban-definition-3QL26DDD-DodjgySL.js} +1 -1
  235. package/out/web/assets/markdown-CMhYIcWB.js +39 -0
  236. package/out/web/assets/{mermaid-parser.core-aUgCqsZ5.js → mermaid-parser.core-Whu2rlJC.js} +3 -3
  237. package/out/web/assets/{mermaid.core-D57sEiSL.js → mermaid.core-CKyPo8VH.js} +4 -4
  238. package/out/web/assets/{mindmap-definition-FBJOCRG2-DAmSpM3a.js → mindmap-definition-FBJOCRG2-260WBDxZ.js} +1 -1
  239. package/out/web/assets/modelManager-CUaGWMWu.js +2 -0
  240. package/out/web/assets/{oauthManager-9jxicDWJ.js → oauthManager-DlNhXJr6.js} +1 -1
  241. package/out/web/assets/{packet-AYTQ26CC-DJ27iIoJ.js → packet-AYTQ26CC-CEeIRKRG.js} +1 -1
  242. package/out/web/assets/{pegDiagram-XKGWAZYB-Bj3ii-gS.js → pegDiagram-XKGWAZYB-BYadI-KO.js} +1 -1
  243. package/out/web/assets/{pie-WAS4IAKB-DG5mCUbc.js → pie-WAS4IAKB-D8uf4dh5.js} +1 -1
  244. package/out/web/assets/{pieDiagram-E7YTZNPT-BrJLPnDA.js → pieDiagram-E7YTZNPT-CjSDy4hO.js} +1 -1
  245. package/out/web/assets/{quadrantDiagram-AXDQQJYC-3x_TmF3j.js → quadrantDiagram-AXDQQJYC-B8D3gU5d.js} +1 -1
  246. package/out/web/assets/{radar-RG4KPBEZ-CrXaTTuV.js → radar-RG4KPBEZ-DZJxnokY.js} +1 -1
  247. package/out/web/assets/{railroad-74A4TZTK-BpqMH9BE.js → railroad-74A4TZTK-DBysUiUi.js} +1 -1
  248. package/out/web/assets/{railroad-abnf-HS5TGJTU-DHI0uLlV.js → railroad-abnf-HS5TGJTU-CHWxoJYg.js} +1 -1
  249. package/out/web/assets/{railroad-ebnf-LZEXJU2U-CQCb316y.js → railroad-ebnf-LZEXJU2U-DDv7X6bY.js} +1 -1
  250. package/out/web/assets/{railroad-peg-WCYAUIDC-Ph1giKkH.js → railroad-peg-WCYAUIDC-DpfcYYNJ.js} +1 -1
  251. package/out/web/assets/{railroadDiagram-O6MQD6OU-BRq6wIxx.js → railroadDiagram-O6MQD6OU-CYtyv0t3.js} +1 -1
  252. package/out/web/assets/{requirementDiagram-EFPCY7ZU-DIJj6G1g.js → requirementDiagram-EFPCY7ZU-D2X-Ewik.js} +1 -1
  253. package/out/web/assets/{sankeyDiagram-P5KCCOFB-DZajSryq.js → sankeyDiagram-P5KCCOFB-Bn2x6C4Y.js} +1 -1
  254. package/out/web/assets/{sequenceDiagram-WJ2MYXX4-DxJCWyZS.js → sequenceDiagram-WJ2MYXX4-BvFLKtPd.js} +1 -1
  255. package/out/web/assets/{stateDiagram-HBIQ2CUA-k6voi8Vf.js → stateDiagram-HBIQ2CUA-Bx0GWeaY.js} +1 -1
  256. package/out/web/assets/stateDiagram-v2-4QOOHH4V--hol1yg_.js +1 -0
  257. package/out/web/assets/{swimlanes-XN3QIQJK-igYhTjXB.js → swimlanes-XN3QIQJK-CCma0T7L.js} +1 -1
  258. package/out/web/assets/swimlanesDiagram-VK2B7HYN-BkohoVsU.js +8 -0
  259. package/out/web/assets/{timeline-definition-24CTP7MA-Dke2p93p.js → timeline-definition-24CTP7MA-iCRhhJ7C.js} +1 -1
  260. package/out/web/assets/{treeView-Q6P3EWNA-hNELnXUs.js → treeView-Q6P3EWNA-DZ-y08qp.js} +1 -1
  261. package/out/web/assets/{treemap-WGGIJYW6-D2B6wDsx.js → treemap-WGGIJYW6-De0CxzMx.js} +1 -1
  262. package/out/web/assets/{vennDiagram-4TSXK5OY-CDkW7rUP.js → vennDiagram-4TSXK5OY-w_7aZ6xe.js} +1 -1
  263. package/out/web/assets/{wardley-WFR3VGLG-BECdXETi.js → wardley-WFR3VGLG-DT0y0xJ4.js} +1 -1
  264. package/out/web/assets/{wardleyDiagram-VM6X3IG4-B5BycpQ4.js → wardleyDiagram-VM6X3IG4-DAdXELbQ.js} +1 -1
  265. package/out/web/assets/window-BJCVtyET.js +1 -0
  266. package/out/web/assets/{xychartDiagram-S5SC5T6Z-CtJS3b--.js → xychartDiagram-S5SC5T6Z-IZIXf3Vo.js} +1 -1
  267. package/out/web/index-web.html +3 -2
  268. package/out/web/index.html +3 -2
  269. package/package.json +71 -22
  270. package/shared-modules/.github/workflows/ci.yml +120 -0
  271. package/shared-modules/.github/workflows/update.yaml +28 -0
  272. package/slash-commands.json +7 -2
  273. package/src/bin/auto-build.js +66 -0
  274. package/src/bin/desktop.js +113 -0
  275. package/src/bin/desktop.test.js +113 -0
  276. package/src/bin/index.js +18 -25
  277. package/src/bin/index.test.js +89 -0
  278. package/src/bin/measure-effects.mjs +53 -0
  279. package/src/bin/package.test.js +28 -0
  280. package/src/bin/release-notes.test.js +84 -0
  281. package/src/bin/styles.test.js +20 -0
  282. package/src/bin/web.js +5 -0
  283. package/src/bin/web.test.js +39 -0
  284. package/src/renderer/index.html +0 -2
  285. package/src/renderer/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  286. package/src/renderer/shared/agentProgress.ts +33 -0
  287. package/src/renderer/shared/components/AgentActivityDrawer.tsx +3 -2
  288. package/src/renderer/shared/components/AgentActivityTable.tsx +1 -1
  289. package/src/renderer/shared/components/ApprovalCard.test.tsx +24 -0
  290. package/src/renderer/shared/components/ApprovalCard.tsx +10 -3
  291. package/src/renderer/shared/components/ArtifactPreviewPanel.tsx +88 -37
  292. package/src/renderer/shared/components/AuthGate.tsx +75 -39
  293. package/src/renderer/shared/components/BackgroundTerminals.tsx +181 -0
  294. package/src/renderer/shared/components/ChatCodeBlock.tsx +8 -4
  295. package/src/renderer/shared/components/ChatMessageItem.test.tsx +68 -0
  296. package/src/renderer/shared/components/ChatMessageItem.tsx +36 -16
  297. package/src/renderer/shared/components/ChatPanel.test.tsx +21 -0
  298. package/src/renderer/shared/components/ChatPanel.tsx +294 -272
  299. package/src/renderer/shared/components/ChunkErrorBoundary.tsx +4 -102
  300. package/src/renderer/shared/components/CliSessionsView.test.tsx +125 -0
  301. package/src/renderer/shared/components/CliSessionsView.tsx +61 -13
  302. package/src/renderer/shared/components/CodeReviewPage.tsx +111 -8
  303. package/src/renderer/shared/components/CollapsiblePasteInput.tsx +90 -0
  304. package/src/renderer/shared/components/ContextCompactionStatus.tsx +17 -0
  305. package/src/renderer/shared/components/DashboardSidebar.tsx +15 -128
  306. package/src/renderer/shared/components/DesktopTitlebar.tsx +45 -19
  307. package/src/renderer/shared/components/ErrorNotice.tsx +29 -0
  308. package/src/renderer/shared/components/FormattedMessage.tsx +11 -0
  309. package/src/renderer/shared/components/GeminiLiveOverlay.css +86 -0
  310. package/src/renderer/shared/components/GeminiLiveOverlay.test.tsx +24 -0
  311. package/src/renderer/shared/components/GeminiLiveOverlay.tsx +85 -101
  312. package/src/renderer/shared/components/GlideSelect.css +138 -0
  313. package/src/renderer/shared/components/GlideSelect.d.ts +31 -0
  314. package/src/renderer/shared/components/GlideSelect.jsx +266 -0
  315. package/src/renderer/shared/components/ImageSearchCard.tsx +46 -56
  316. package/src/renderer/shared/components/ImageStudioPanel.tsx +9 -8
  317. package/src/renderer/shared/components/LibraryItemCard.tsx +72 -0
  318. package/src/renderer/shared/components/LibraryPage.tsx +165 -0
  319. package/src/renderer/shared/components/LibraryPreview.tsx +59 -0
  320. package/src/renderer/shared/components/McpServersView.tsx +27 -8
  321. package/src/renderer/shared/components/McpToolAllowlist.tsx +2 -4
  322. package/src/renderer/shared/components/McpToolResults.tsx +99 -0
  323. package/src/renderer/shared/components/MintDashboard.tsx +308 -770
  324. package/src/renderer/shared/components/ModSessionControls.tsx +8 -0
  325. package/src/renderer/shared/components/ModUi.test.tsx +65 -0
  326. package/src/renderer/shared/components/ModUi.tsx +26 -0
  327. package/src/renderer/shared/components/ModelSelectorPopover.tsx +14 -7
  328. package/src/renderer/shared/components/ModsPanel.tsx +156 -0
  329. package/src/renderer/shared/components/ProgressActivity.tsx +17 -0
  330. package/src/renderer/shared/components/ReviewHistory.tsx +42 -0
  331. package/src/renderer/shared/components/RewindModal.tsx +5 -12
  332. package/src/renderer/shared/components/RunSummaryDashboard.tsx +6 -12
  333. package/src/renderer/shared/components/ScheduledTasksView.tsx +7 -6
  334. package/src/renderer/shared/components/SelectField.test.tsx +27 -0
  335. package/src/renderer/shared/components/SelectField.tsx +38 -0
  336. package/src/renderer/shared/components/SessionSources.tsx +48 -0
  337. package/src/renderer/shared/components/SessionSourcesPopover.tsx +61 -0
  338. package/src/renderer/shared/components/Settings/AgentsTab.tsx +7 -6
  339. package/src/renderer/shared/components/Settings/AudioTab.tsx +8 -7
  340. package/src/renderer/shared/components/Settings/AutomationTab.tsx +2 -2
  341. package/src/renderer/shared/components/Settings/GeneralTab.tsx +33 -32
  342. package/src/renderer/shared/components/Settings/MemoryTab.test.tsx +37 -0
  343. package/src/renderer/shared/components/Settings/MemoryTab.tsx +71 -31
  344. package/src/renderer/shared/components/Settings/NotificationsTab.test.tsx +15 -0
  345. package/src/renderer/shared/components/Settings/NotificationsTab.tsx +84 -0
  346. package/src/renderer/shared/components/Settings/ThemeTab.tsx +19 -11
  347. package/src/renderer/shared/components/SlashChoicePanel.tsx +88 -0
  348. package/src/renderer/shared/components/SlashSuggestions.test.tsx +33 -0
  349. package/src/renderer/shared/components/SlashSuggestions.tsx +38 -10
  350. package/src/renderer/shared/components/SourcesBlock.tsx +12 -20
  351. package/src/renderer/shared/components/ToolSurfacePage.test.tsx +32 -0
  352. package/src/renderer/shared/components/ToolSurfacePage.tsx +59 -11
  353. package/src/renderer/shared/components/ToolsPanelToggle.tsx +13 -0
  354. package/src/renderer/shared/components/VeoStudioPanel.tsx +9 -8
  355. package/src/renderer/shared/components/ViewedImages.tsx +36 -0
  356. package/src/renderer/shared/components/VirtualChatHistory.tsx +82 -0
  357. package/src/renderer/shared/components/VoicePill.css +85 -0
  358. package/src/renderer/shared/components/VoicePill.d.ts +12 -0
  359. package/src/renderer/shared/components/VoicePill.jsx +190 -0
  360. package/src/renderer/shared/components/VoicePill.test.tsx +22 -0
  361. package/src/renderer/shared/components/WorkspaceContextPopover.tsx +20 -15
  362. package/src/renderer/shared/components/WorkspacePaneResizer.tsx +92 -0
  363. package/src/renderer/shared/components/WorkspacePreviewActions.test.tsx +44 -0
  364. package/src/renderer/shared/components/WorkspacePreviewActions.tsx +19 -0
  365. package/src/renderer/shared/components/WorkspaceSelector.tsx +13 -8
  366. package/src/renderer/shared/components/background-terminals.css +292 -0
  367. package/src/renderer/shared/components/ui/README.md +52 -0
  368. package/src/renderer/shared/components/ui/button.tsx +37 -0
  369. package/src/renderer/shared/components/ui/demo.tsx +26 -0
  370. package/src/renderer/shared/components/ui/error-recovery.css +35 -0
  371. package/src/renderer/shared/components/ui/error-recovery.tsx +35 -0
  372. package/src/renderer/shared/components/ui/voice-powered-orb.css +6 -0
  373. package/src/renderer/shared/components/ui/voice-powered-orb.tsx +374 -0
  374. package/src/renderer/shared/components/workspace-selector.css +248 -0
  375. package/src/renderer/shared/constants/config.ts +30 -1
  376. package/src/renderer/shared/constants/slashCommands.ts +1 -1
  377. package/src/renderer/shared/conversation/lifecycle.test.ts +362 -0
  378. package/src/renderer/shared/conversation/lifecycle.ts +418 -0
  379. package/src/renderer/shared/conversation/projectNavigation.test.ts +105 -0
  380. package/src/renderer/shared/conversation/projectNavigation.ts +39 -0
  381. package/src/renderer/shared/conversation/sourcesTransport.ts +27 -0
  382. package/src/renderer/shared/conversation/syncView.test.ts +1 -34
  383. package/src/renderer/shared/conversation/syncView.ts +0 -37
  384. package/src/renderer/shared/conversation/transport.test.ts +163 -0
  385. package/src/renderer/shared/conversation/transport.ts +159 -0
  386. package/src/renderer/shared/conversation/useConversationCoordinator.ts +30 -72
  387. package/src/renderer/shared/css/agent-observability.css +20 -21
  388. package/src/renderer/shared/css/auth-gate.css +112 -13
  389. package/src/renderer/shared/css/code-review.css +33 -0
  390. package/src/renderer/shared/css/code-sessions.css +27 -0
  391. package/src/renderer/shared/css/collapsed-paste.css +35 -0
  392. package/src/renderer/shared/css/effects.css +15 -0
  393. package/src/renderer/shared/css/error-notice.css +60 -0
  394. package/src/renderer/shared/css/library.css +476 -0
  395. package/src/renderer/shared/css/management-views.css +138 -0
  396. package/src/renderer/shared/css/mcp-results.css +11 -0
  397. package/src/renderer/shared/css/model-selector.css +163 -105
  398. package/src/renderer/shared/css/mods.css +77 -0
  399. package/src/renderer/shared/css/notification-notice.css +28 -0
  400. package/src/renderer/shared/css/session-sources-popover.css +9 -0
  401. package/src/renderer/shared/css/session-sources.css +23 -0
  402. package/src/renderer/shared/css/settings/memory.css +154 -0
  403. package/src/renderer/shared/css/settings/notifications.css +11 -0
  404. package/src/renderer/shared/css/settings/theme.css +5 -0
  405. package/src/renderer/shared/css/slash-choice.css +95 -0
  406. package/src/renderer/shared/css/slash-suggestions.css +68 -0
  407. package/src/renderer/shared/css/sources-block.css +91 -0
  408. package/src/renderer/shared/css/thinking-status.css +46 -0
  409. package/src/renderer/shared/css/tools-panel.css +7 -0
  410. package/src/renderer/shared/css/ui-tailwind.css +19 -0
  411. package/src/renderer/shared/css/viewed-images.css +15 -0
  412. package/src/renderer/shared/fonts.css +46 -0
  413. package/src/renderer/shared/fonts.ts +3 -12
  414. package/src/renderer/shared/lib/utils.ts +6 -0
  415. package/src/renderer/shared/library/controller.test.ts +61 -0
  416. package/src/renderer/shared/library/controller.ts +57 -0
  417. package/src/renderer/shared/library/transport.test.ts +26 -0
  418. package/src/renderer/shared/library/transport.ts +60 -0
  419. package/src/renderer/shared/library/useLibraryFile.ts +38 -0
  420. package/src/renderer/shared/mods.ts +58 -0
  421. package/src/renderer/shared/platform.test.ts +57 -1
  422. package/src/renderer/shared/platform.ts +46 -1
  423. package/src/renderer/shared/theme/themeManager.test.ts +43 -0
  424. package/src/renderer/shared/theme/themeManager.ts +17 -4
  425. package/src/renderer/shared/types.ts +56 -2
  426. package/src/renderer/shared/utils/agentActivity.test.ts +75 -0
  427. package/src/renderer/shared/utils/agentActivity.ts +42 -3
  428. package/src/renderer/shared/utils/approval.tsx +7 -0
  429. package/src/renderer/shared/utils/artifactBrowser.test.ts +80 -0
  430. package/src/renderer/shared/utils/artifactBrowser.ts +41 -0
  431. package/src/renderer/shared/utils/contextCompaction.test.tsx +48 -0
  432. package/src/renderer/shared/utils/contextCompaction.ts +21 -0
  433. package/src/renderer/shared/utils/effectVisibility.ts +9 -0
  434. package/src/renderer/shared/utils/markdown.tsx +3 -3
  435. package/src/renderer/shared/utils/mcpResults.test.tsx +91 -0
  436. package/src/renderer/shared/utils/modViewport.ts +7 -0
  437. package/src/renderer/shared/utils/nativeRecordingSession.test.ts +61 -0
  438. package/src/renderer/shared/utils/nativeRecordingSession.ts +46 -0
  439. package/src/renderer/shared/utils/notificationSettings.test.ts +14 -0
  440. package/src/renderer/shared/utils/notificationSettings.ts +23 -0
  441. package/src/renderer/shared/utils/notifications.test.ts +51 -0
  442. package/src/renderer/shared/utils/notifications.ts +54 -0
  443. package/src/renderer/shared/utils/pastedText.test.ts +20 -0
  444. package/src/renderer/shared/utils/pastedText.ts +13 -0
  445. package/src/renderer/shared/utils/progressCache.test.ts +32 -0
  446. package/src/renderer/shared/utils/sessionSources.test.ts +31 -0
  447. package/src/renderer/shared/utils/sessionSources.ts +34 -0
  448. package/src/renderer/shared/utils/slashCommandProcessor.ts +1 -1
  449. package/src/renderer/shared/utils/sourceAttachments.ts +28 -0
  450. package/src/renderer/shared/utils/speech.ts +51 -9
  451. package/src/renderer/shared/utils/syntaxHighlight.test.tsx +22 -0
  452. package/src/renderer/shared/utils/syntaxHighlight.tsx +26 -0
  453. package/src/renderer/shared/utils/useGeminiLiveVoice.ts +49 -5
  454. package/src/renderer/shared/utils/useLatestCallback.ts +9 -0
  455. package/src/renderer/shared/utils/useNativeVoiceInput.ts +80 -72
  456. package/src/renderer/shared/utils/useSessionSources.ts +33 -0
  457. package/src/renderer/shared/utils/viewedImages.ts +26 -0
  458. package/src/renderer/shared/utils/workspacePane.test.ts +33 -0
  459. package/src/renderer/shared/utils/workspacePane.ts +20 -0
  460. package/src/renderer/shared/utils/workspacePreview.test.ts +24 -0
  461. package/src/renderer/shared/utils/workspacePreview.ts +16 -0
  462. package/src/renderer/shared/utils/workspaceSnapshot.test.ts +49 -0
  463. package/src/renderer/shared/utils/workspaceSnapshot.ts +26 -0
  464. package/src/renderer/shared/utils/workspaces.ts +10 -0
  465. package/src/renderer/shared/workspaceUndo.ts +88 -0
  466. package/src/renderer/src/App.tsx +9 -1
  467. package/src/renderer/src/components/LiveTranslateControls.tsx +65 -0
  468. package/src/renderer/src/components/PicturesLibrary.tsx +2 -288
  469. package/src/renderer/src/components/ScreenPicker.css +67 -30
  470. package/src/renderer/src/components/ScreenPicker.tsx +201 -60
  471. package/src/renderer/src/components/SettingsWindow.tsx +10 -5
  472. package/src/renderer/src/components/WorkspacePanel.tsx +222 -32
  473. package/src/renderer/src/components/browser-shell.css +1 -1
  474. package/src/renderer/src/components/browser-suggestions-popup.css +1 -1
  475. package/src/renderer/src/components/liveTranslateFrames.test.ts +26 -5
  476. package/src/renderer/src/components/liveTranslateFrames.ts +18 -7
  477. package/src/renderer/src/components/liveTranslateLanguage.ts +6 -0
  478. package/src/renderer/src/css/app-shell.css +52 -137
  479. package/src/renderer/src/css/chat.css +21 -495
  480. package/src/renderer/src/css/desktop-tools.css +199 -1
  481. package/src/renderer/src/css/misc.css +0 -52
  482. package/src/renderer/src/css/pictures.css +2 -415
  483. package/src/renderer/src/css/settings/base.css +50 -47
  484. package/src/renderer/src/css/sidebar-workspace.css +151 -94
  485. package/src/renderer/src/css/tool-surfaces.css +65 -9
  486. package/src/renderer/src/css/widget.css +1 -1
  487. package/src/renderer/src/env.d.ts +1 -9
  488. package/src/renderer/src/index.css +1 -1
  489. package/src/renderer/src/main.tsx +2 -1
  490. package/src/renderer/src/proactiveSuggestions.ts +29 -0
  491. package/src/renderer/src/tauri.ts +122 -330
  492. package/src/renderer/src/voiceInput.ts +2 -1
  493. package/src/renderer/src-web/components/PicturesLibrary.tsx +2 -285
  494. package/src/renderer/src-web/components/PullToRefresh.tsx +1 -1
  495. package/src/renderer/src-web/components/SettingsWindow.tsx +10 -5
  496. package/src/renderer/src-web/css/app-shell.css +24 -121
  497. package/src/renderer/src-web/css/chat.css +21 -495
  498. package/src/renderer/src-web/css/misc.css +0 -52
  499. package/src/renderer/src-web/css/mobile.css +15 -14
  500. package/src/renderer/src-web/css/pictures.css +2 -462
  501. package/src/renderer/src-web/css/settings/base.css +50 -47
  502. package/src/renderer/src-web/css/sidebar-workspace.css +9 -95
  503. package/src/renderer/src-web/css/widget.css +1 -1
  504. package/src/renderer/src-web/env.d.ts +1 -12
  505. package/src/renderer/src-web/index.css +1 -1
  506. package/src/renderer/src-web/main.tsx +2 -1
  507. package/src/renderer/src-web/proactiveSuggestions.ts +3 -0
  508. package/src/renderer/src-web/tauri.ts +129 -354
  509. package/src/renderer/tests/backgroundTerminals.browser.html +81 -0
  510. package/src/renderer/tests/chatPanelFixture.ts +23 -0
  511. package/src/renderer/tests/chatPerformance.browser.html +71 -0
  512. package/src/renderer/tests/cliSessions.browser.html +82 -0
  513. package/src/renderer/tests/collapsedPaste.browser.html +70 -0
  514. package/src/renderer/tests/composerMenus.browser.html +116 -0
  515. package/src/renderer/tests/contextCompaction.browser.html +17 -0
  516. package/src/renderer/tests/conversationLifecycle.browser.html +70 -0
  517. package/src/renderer/tests/effectsPerformance.browser.html +13 -0
  518. package/src/renderer/tests/errorRecovery.browser.html +21 -0
  519. package/src/renderer/tests/glideSelect.browser.html +71 -0
  520. package/src/renderer/tests/glideSelect.preview.html +27 -0
  521. package/src/renderer/tests/library.browser.html +1 -0
  522. package/src/renderer/tests/library.browser.tsx +78 -0
  523. package/src/renderer/tests/liveOrb.browser.html +49 -0
  524. package/src/renderer/tests/liveVoice.browser.html +29 -0
  525. package/src/renderer/tests/modInput.browser.html +22 -0
  526. package/src/renderer/tests/sessionSources.browser.html +1 -0
  527. package/src/renderer/tests/sessionSources.browser.tsx +107 -0
  528. package/src/renderer/tests/skills.browser.html +24 -0
  529. package/src/renderer/tests/toolsPanel.browser.html +1 -0
  530. package/src/renderer/tests/toolsPanel.browser.tsx +113 -0
  531. package/src/renderer/tests/viewedImages.browser.html +1 -0
  532. package/src/renderer/tests/viewedImages.browser.tsx +93 -0
  533. package/src/renderer/tests/voicePill.browser.html +80 -0
  534. package/src/renderer/tests/voicePill.preview.html +34 -0
  535. package/src/renderer/tests/webSources.browser.html +1 -0
  536. package/src/renderer/tests/webSources.browser.tsx +98 -0
  537. package/src/renderer/tests/workspaceUndo.browser.html +92 -0
  538. package/src-tauri/Cargo.toml +40 -0
  539. package/src-tauri/build.rs +3 -0
  540. package/src-tauri/src/app/lifecycle.rs +277 -0
  541. package/src-tauri/src/app/mod.rs +4 -0
  542. package/src-tauri/src/app/shortcuts.rs +40 -0
  543. package/src-tauri/src/app/tray.rs +52 -0
  544. package/src-tauri/src/background/events.rs +70 -0
  545. package/src-tauri/src/background/headless.rs +230 -0
  546. package/src-tauri/src/background/mod.rs +4 -0
  547. package/src-tauri/src/background/proactive.rs +262 -0
  548. package/src-tauri/src/commands/approvals.rs +20 -0
  549. package/src-tauri/src/commands/auth.rs +127 -0
  550. package/src-tauri/src/commands/conversation.rs +642 -0
  551. package/src-tauri/src/commands/integrations.rs +157 -0
  552. package/src-tauri/src/commands/media.rs +179 -0
  553. package/src-tauri/src/commands/mod.rs +11 -0
  554. package/src-tauri/src/commands/mods.rs +6 -0
  555. package/src-tauri/src/commands/settings.rs +141 -0
  556. package/src-tauri/src/commands/voice.rs +153 -0
  557. package/src-tauri/src/commands/workspace.rs +501 -0
  558. package/src-tauri/src/lib.rs +10 -0
  559. package/src-tauri/src/main.rs +3 -0
  560. package/src-tauri/src/native/actions.rs +206 -0
  561. package/src-tauri/src/native/browser.rs +252 -0
  562. package/src-tauri/src/native/capture.rs +695 -0
  563. package/src-tauri/src/native/discord_rpc.rs +99 -0
  564. package/src-tauri/src/native/integrations.rs +126 -0
  565. package/src-tauri/src/native/mod.rs +12 -0
  566. package/src-tauri/src/native/notifications.rs +51 -0
  567. package/src-tauri/src/native/plugins.rs +14 -0
  568. package/src-tauri/src/native/system.rs +250 -0
  569. package/src-tauri/src/native/terminal.rs +201 -0
  570. package/src-tauri/src/native/updater.rs +148 -0
  571. package/src-tauri/src/native/windows.rs +143 -0
  572. package/tsconfig.json +2 -0
  573. package/vite.config.ts +4 -1
  574. package/vite.config.web.ts +4 -0
  575. package/.cargo/config.toml +0 -13
  576. package/.claude/settings.local.json +0 -182
  577. package/.codex +0 -0
  578. package/CLAUDE.md +0 -102
  579. package/ROADMAP.md +0 -30
  580. package/mint-presentation-demo.mp4 +0 -0
  581. package/out/web/Live2DCubismCore.js +0 -9
  582. package/out/web/assets/CliSessionsView-BxUVWEEL.js +0 -1
  583. package/out/web/assets/CliSessionsView-CBDTXuQv.css +0 -1
  584. package/out/web/assets/CodeReviewPage-DkMgfcos.css +0 -1
  585. package/out/web/assets/CodeReviewPage-jKlmLJwT.js +0 -3
  586. package/out/web/assets/CommandPalette-DnwPA5hy.js +0 -1
  587. package/out/web/assets/ImageStudioPanel-BR1XFwhR.js +0 -1
  588. package/out/web/assets/LinkedFoldersView-bi-CWQ-I.js +0 -1
  589. package/out/web/assets/McpRegistryPicker-D5tEFnyq.js +0 -1
  590. package/out/web/assets/McpServersView-BGG1dhFM.js +0 -1
  591. package/out/web/assets/MintDashboard-BIglDEWX.js +0 -20
  592. package/out/web/assets/MintDashboard-DSMywSgs.css +0 -1
  593. package/out/web/assets/ModelPanel-CbJ1PFoZ.js +0 -1
  594. package/out/web/assets/PicturesLibrary-CQP0fLP1.css +0 -1
  595. package/out/web/assets/PicturesLibrary-DoYN7T1p.js +0 -1
  596. package/out/web/assets/PluginsView-CU1HWXGk.js +0 -1
  597. package/out/web/assets/ScheduledTasksView-Bnl36y2N.js +0 -1
  598. package/out/web/assets/SettingsWindow-DhWLAn9T.css +0 -1
  599. package/out/web/assets/SettingsWindow-Dw8L01pw.js +0 -2
  600. package/out/web/assets/SkillsView-cnl8aY5p.js +0 -2
  601. package/out/web/assets/ToolSurfacePage-CgsQw6l5.css +0 -1
  602. package/out/web/assets/ToolSurfacePage-Cz2VJAPZ.js +0 -37
  603. package/out/web/assets/VeoStudioPanel-D4JnERWR.js +0 -4
  604. package/out/web/assets/chunk-CKBBP62Z-cIrXq6jN.js +0 -2
  605. package/out/web/assets/classDiagram-DTDB5LWJ-Dq0smRWk.js +0 -1
  606. package/out/web/assets/classDiagram-v2-JRS7N3AN-Dq0smRWk.js +0 -1
  607. package/out/web/assets/config-C-ZFtipU.css +0 -1
  608. package/out/web/assets/config-eEDngJXO.js +0 -1
  609. package/out/web/assets/core-hQ2VA9Ti.js +0 -1
  610. package/out/web/assets/dist-js-Bf2bhoku.js +0 -1
  611. package/out/web/assets/flowDiagram-A5DVABFB-BLg7nEcd.js +0 -1
  612. package/out/web/assets/index-Btsf4L8M.css +0 -1
  613. package/out/web/assets/index-D8D9MeRA.js +0 -11
  614. package/out/web/assets/lucide-react-Ip3L6Jtn.js +0 -1
  615. package/out/web/assets/markdown-BSeeUbJH.js +0 -38
  616. package/out/web/assets/modelManager-tMVmJVAW.js +0 -2
  617. package/out/web/assets/prompt-latin-400-normal-BQ9zjSN8.woff2 +0 -0
  618. package/out/web/assets/prompt-latin-400-normal-CxU4ec_r.woff +0 -0
  619. package/out/web/assets/prompt-latin-500-normal-B1edBDQ9.woff +0 -0
  620. package/out/web/assets/prompt-latin-500-normal-CxzxEHZc.woff2 +0 -0
  621. package/out/web/assets/prompt-latin-600-normal-CSDDLorv.woff +0 -0
  622. package/out/web/assets/prompt-latin-600-normal-hKZWXsc1.woff2 +0 -0
  623. package/out/web/assets/prompt-latin-700-normal-BfbftDSq.woff +0 -0
  624. package/out/web/assets/prompt-latin-700-normal-I2gc831J.woff2 +0 -0
  625. package/out/web/assets/prompt-thai-400-normal-BrkKv8cO.woff2 +0 -0
  626. package/out/web/assets/prompt-thai-400-normal-DJypnfr3.woff +0 -0
  627. package/out/web/assets/prompt-thai-500-normal-C18pDUoL.woff2 +0 -0
  628. package/out/web/assets/prompt-thai-500-normal-D7YNqUJD.woff +0 -0
  629. package/out/web/assets/prompt-thai-600-normal-CYPViXds.woff +0 -0
  630. package/out/web/assets/prompt-thai-600-normal-MrdfU7zR.woff2 +0 -0
  631. package/out/web/assets/prompt-thai-700-normal-Cb5ilR-c.woff +0 -0
  632. package/out/web/assets/prompt-thai-700-normal-Cg4aQ0Nn.woff2 +0 -0
  633. package/out/web/assets/stateDiagram-v2-4QOOHH4V-DeEc0lGZ.js +0 -1
  634. package/out/web/assets/swimlanesDiagram-VK2B7HYN-DpVik9v7.js +0 -8
  635. package/out/web/assets/window-5qYXKoW7.js +0 -1
  636. package/skills-lock.json +0 -77
  637. package/src/renderer/public/Live2DCubismCore.js +0 -9
  638. package/src/renderer/src/companionWidget.ts +0 -95
  639. package/src/renderer/src/components/Live2DStage.tsx +0 -412
  640. package/src/renderer/src/components/ModelPanel.tsx +0 -155
  641. package/src/renderer/src/css/model.css +0 -628
  642. package/src/renderer/src-web/companionWidget.ts +0 -37
  643. package/src/renderer/src-web/components/ModelPanel.tsx +0 -12
  644. package/src/renderer/src-web/css/model.css +0 -628
@@ -0,0 +1,93 @@
1
+ import React, { useState } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import ChatMessageItem from '../shared/components/ChatMessageItem'
4
+ import { ProgressActivity } from '../shared/components/ProgressActivity'
5
+ import ViewedImages from '../shared/components/ViewedImages'
6
+ import type { AgentProgress } from '../shared/types'
7
+ import { compactAgentProgressForPersistence, reduceLiveAgentProgress } from '../shared/agentProgress'
8
+ import '../shared/theme/tokens.css'
9
+ if (new URLSearchParams(location.search).get('platform') === 'desktop') {
10
+ await import('../src/css/app-shell.css'); await import('../src/css/chat.css')
11
+ } else {
12
+ await import('../src-web/css/app-shell.css'); await import('../src-web/css/chat.css')
13
+ }
14
+
15
+ const canvas = document.createElement('canvas'); canvas.width = 960; canvas.height = 600
16
+ const context = canvas.getContext('2d')!
17
+ context.fillStyle = '#1b3534'; context.fillRect(0, 0, 960, 600)
18
+ context.fillStyle = '#8bd8c3'; context.fillRect(56, 56, 848, 100)
19
+ context.fillStyle = '#dce9e4'; context.font = '28px sans-serif'; context.fillText('view_image · screenshot.png', 56, 220)
20
+ context.strokeStyle = '#8bd8c3'; context.lineWidth = 3; context.strokeRect(56, 270, 390, 260); context.strokeRect(480, 270, 424, 260)
21
+ const image = canvas.toDataURL('image/png')
22
+ const svg = `data:image/svg+xml;base64,${btoa('<svg xmlns="http://www.w3.org/2000/svg" width="420" height="260"><rect width="420" height="260" fill="#21343b"/><circle cx="210" cy="130" r="80" fill="#91d6b5"/></svg>')}`
23
+ const input = { path: '/workspace/ภาพตัวอย่างที่มีชื่อไฟล์ยาวเพื่อทดสอบการแสดงผลบนโทรศัพท์มือถือ.png' }
24
+ const start: AgentProgress = { type: 'ToolStart', data: { action: 'view_image', input } }
25
+ const textActivity: AgentProgress = { type: 'ToolEnd', data: { action: 'read_file', input: {}, result: 'Read' } }
26
+ const finished: AgentProgress[] = [textActivity, textActivity, start,
27
+ { type: 'ToolEnd', data: { action: 'view_image', input, result: `${image}\n\n[Hook] Viewed successfully` } },
28
+ { type: 'ToolEnd', data: { callId: 'image-2', action: 'view_image', input: { path: '/workspace/diagram.svg' }, result: svg } },
29
+ ]
30
+ const noop = () => {}
31
+ let continueRun = noop
32
+ function Fixture() {
33
+ const [done, setDone] = useState(false)
34
+ const [mode, setMode] = useState('live')
35
+ const [open, setOpen] = useState(true)
36
+ const [continued, setContinued] = useState(false)
37
+ continueRun = () => setContinued(true)
38
+ const progress = done ? continued ? Array.from({ length: 40 }, () => ({ ...textActivity })).reduce(reduceLiveAgentProgress, finished) : finished : [start]
39
+ return <>
40
+ <style>{`*{box-sizing:border-box}body{margin:0;padding:16px;background:#101112;color:var(--text-main);font-family:Arial,sans-serif}.fixture-controls{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:20px}.fixture-message{max-width:760px;margin:auto;min-width:0}#qa-results{white-space:pre-wrap;font-size:10px;overflow-wrap:anywhere}.message-bubble{width:100%}`}</style>
41
+ <div className="fixture-controls"><button id="finish" onClick={() => setDone(true)}>Finish view_image</button><button id="history" onClick={() => setMode('history')}>Reload saved history</button><button id="switch" onClick={() => setMode('other')}>Other conversation</button><button id="live" onClick={() => setMode('live')}>Live view</button></div>
42
+ <div className="fixture-message">
43
+ {mode === 'live' ? <><ProgressActivity progress={progress} id="live" isOpen={open} onToggle={() => setOpen(value => !value)} /><div className="message ai-message"><div className="bubble-wrapper"><div className="message-bubble"><ViewedImages progress={progress} /></div></div></div></>
44
+ : <ChatMessageItem interaction={{ id: mode === 'other' ? 8 : 7, status: 'completed', aiText: 'I have inspected the images.', userText: 'ช่วยดูรูปภาพนี้หน่อย', createdAt: '2026-10-16T05:00:00Z', agentActivity: mode === 'other' ? [] : JSON.parse(JSON.stringify(compactAgentProgressForPersistence(finished))) }} copiedId={null} speakingText={null} agentActivitySnapshots={{}} thinkingExpanded={{}} onThinkingExpandedChange={noop} handleCopyMessage={noop} speak={noop} toggleActivity={noop} renderFileChanges={() => null} />}
45
+ </div><pre id="qa-results">Running…</pre>
46
+ </>
47
+ }
48
+ createRoot(document.getElementById('root')!).render(<Fixture />)
49
+ const delay = (ms = 40) => new Promise(resolve => setTimeout(resolve, ms))
50
+ async function waitFor(check: () => boolean, name: string) { for (let i = 0; i < 120; i++) { if (check()) return; await delay() } throw new Error(name) }
51
+ const results: string[] = []
52
+ const check = (value: unknown, name: string) => { if (!value) throw new Error(name); results.push(`PASS ${name}`) }
53
+ const click = (selector: string) => { const element = document.querySelector<HTMLElement>(selector); if (!element) throw new Error(`Missing ${selector}`); element.focus(); element.click() }
54
+ async function run() {
55
+ await waitFor(() => Boolean(document.querySelector('.agent-activity-item')), 'Tool starts')
56
+ check(!document.querySelector('[data-viewed-image]'), 'no image appears before view_image completes')
57
+ click('#finish')
58
+ await waitFor(() => document.querySelectorAll('.viewed-image-button img').length === 2, 'Both results appear')
59
+ await waitFor(() => [...document.querySelectorAll<HTMLImageElement>('.viewed-image-button img')].every(img => img.naturalWidth > 0), 'PNG and SVG load')
60
+ // Capture final layout without depending on headless compositor animation timing.
61
+ document.getAnimations().forEach(animation => { if (animation.effect?.getTiming().iterations !== Infinity) animation.finish() })
62
+ check(getComputedStyle(document.querySelector('.message')!).opacity === '1', 'chat content is visibly rendered')
63
+ check(document.querySelector('.agent-activity-target-text')!.getBoundingClientRect().width > 40, 'view_image row keeps room for the file path')
64
+ check(document.documentElement.scrollWidth <= innerWidth, 'images and long filenames fit viewport')
65
+ click('.agent-activity-item')
66
+ await waitFor(() => Boolean(document.querySelector('.agent-activity-output')), 'Expanded tool output')
67
+ check(!document.querySelector('.agent-activity-output')?.textContent?.includes('data:image/'), 'tool output does not dump base64')
68
+ check(document.querySelector('.agent-activity-output')?.textContent?.includes('[Hook] Viewed successfully'), 'hook notes remain readable')
69
+ if (location.search.includes('preview')) { document.getElementById('qa-results')!.textContent = ''; return }
70
+ const trigger = document.querySelector<HTMLButtonElement>('.viewed-image-button')!
71
+ trigger.focus(); trigger.click()
72
+ await waitFor(() => Boolean(document.querySelector('dialog[open] img')), 'Expanded preview')
73
+ check(document.querySelector<HTMLImageElement>('dialog[open] img')?.naturalWidth === 960, 'expanded preview uses original pixels')
74
+ const rect = document.querySelector('dialog[open]')!.getBoundingClientRect()
75
+ check(rect.left >= 0 && rect.right <= innerWidth && rect.bottom <= innerHeight, 'expanded preview fits viewport')
76
+ const openedDialog = document.querySelector('dialog[open]')
77
+ continueRun(); await delay(100)
78
+ check(document.querySelector('dialog[open]') === openedDialog, 'preview stays open as older activity is trimmed during a run')
79
+ click('dialog[open] button')
80
+ await waitFor(() => !document.querySelector('dialog[open]'), 'Preview closes')
81
+ check(document.activeElement === trigger, 'closing preview restores keyboard focus')
82
+ click('#history')
83
+ await waitFor(() => Boolean(document.querySelector('.agent-activity-history')), 'Saved history mounts')
84
+ check(!document.querySelector('.agent-activity-card-history') && document.querySelectorAll('[data-viewed-image]').length === 2, 'saved images remain visible with Activity collapsed')
85
+ click('#switch'); await waitFor(() => !document.querySelector('[data-viewed-image]'), 'Session switch')
86
+ check(!document.querySelector('[data-viewed-image]'), 'images do not leak into another conversation')
87
+ click('#live'); await waitFor(() => document.querySelectorAll('[data-viewed-image]').length === 2, 'Live view returns')
88
+ document.querySelector('.viewed-image-button img')!.dispatchEvent(new Event('error'))
89
+ await waitFor(() => Boolean(document.querySelector('.viewed-image-error')), 'Image error')
90
+ check(document.querySelectorAll('.viewed-image-button').length === 1, 'a broken image leaves other images available')
91
+ document.getElementById('qa-results')!.textContent = results.join('\n') + '\nALL PASSED'
92
+ }
93
+ run().catch(error => { document.getElementById('qa-results')!.textContent = results.join('\n') + `\nFAIL ${error.message}` })
@@ -0,0 +1,80 @@
1
+ <!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Mint VoicePill interaction checks</title></head>
2
+ <body style="background:#18181b;color:#f5f5f5;font-family:system-ui;margin:32px"><h1>Mint VoicePill</h1><div id="root" style="padding:24px 140px"></div><pre id="result">RUNNING</pre>
3
+ <script type="module">
4
+ import React from 'react';import {createRoot} from 'react-dom/client';
5
+ import VoicePill from '../shared/components/VoicePill';
6
+ import {useNativeVoiceInput} from '../shared/utils/useNativeVoiceInput';
7
+ import {useSpeechToText} from '../shared/utils/speech';
8
+ const wait=(ms=60)=>new Promise(done=>setTimeout(done,ms));const lines=[];
9
+ const assert=(ok,line)=>{if(!ok)throw Error(line);lines.push(line)};
10
+ // Drive scheduled component frames deterministically; Chrome virtual-time timers can outrun compositor frames.
11
+ const frames=new Map();let frameId=0;
12
+ window.requestAnimationFrame=callback=>{frames.set(++frameId,callback);return frameId};
13
+ window.cancelAnimationFrame=id=>frames.delete(id);
14
+ const advanceFrames=count=>{const now=performance.now();for(let i=0;i<count;i++){const batch=[...frames.values()];frames.clear();batch.forEach(callback=>callback(now+i*20))}};
15
+ const root=createRoot(document.getElementById('root'));
16
+ const events=[];let setDisabled,unmountPill;
17
+ const button=()=>document.querySelector('.voice-pill');
18
+ const pointer=(type,x=180)=>button().dispatchEvent(new PointerEvent(type,{button:0,pointerId:7,isPrimary:true,clientX:x,bubbles:true,cancelable:true}));
19
+ const tap=async()=>{pointer('pointerdown');await wait(30);pointer('pointerup');await wait()};
20
+ const key=key=>button().dispatchEvent(new KeyboardEvent('keydown',{key,bubbles:true,cancelable:true}));
21
+ try {
22
+ function Fixture(){
23
+ const [disabled,disable]=React.useState(false);setDisabled=disable;
24
+ const [shown,show]=React.useState(true);unmountPill=()=>show(false);
25
+ return shown?React.createElement(VoicePill,{disabled,onStart:e=>events.push(['start',e]),onStop:e=>events.push(['stop',e])}):null;
26
+ }
27
+ root.render(React.createElement(Fixture));await wait(180);
28
+ assert(button().getAttribute('aria-pressed')==='false','idle microphone is not marked recording');
29
+ await tap();assert(button().getAttribute('aria-pressed')==='true','short tap latches recording');
30
+ advanceFrames(64);assert(button().querySelector('.voice-pill__time').textContent!=='0:00','elapsed clock advances');
31
+ const canvas=button().querySelector('canvas');const pixels=canvas.getContext('2d').getImageData(0,0,canvas.width,canvas.height).data;
32
+ assert(pixels.some((v,i)=>i%4===3&&v>0),'authored scrolling waveform renders canvas pixels ('+canvas.width+'x'+canvas.height+')');
33
+ await tap();assert(events.at(-1)[1].reason==='tap'&&button().getAttribute('aria-pressed')==='false','second tap stops latched recording');
34
+ pointer('pointerdown');await wait(360);pointer('pointerup');await wait();assert(events.at(-1)[1].reason==='release','held recording stops on release');
35
+ pointer('pointerdown');await wait();pointer('pointermove',140);await wait();assert(button().dataset.sliding!==undefined,'held left drag reveals cancel affordance');
36
+ pointer('pointermove',110);await wait();const count=events.length;pointer('pointerup',110);await wait();
37
+ assert(events.at(-1)[1].reason==='cancel'&&events.length===count,'crossing cancel distance cancels once without release result');
38
+ pointer('pointerdown');await wait();pointer('pointercancel');await wait();assert(events.at(-1)[1].reason==='cancel','pointer cancellation never submits');
39
+ key('Enter');await wait();assert(button().getAttribute('aria-pressed')==='true','keyboard starts recording');
40
+ key('Escape');await wait();assert(events.at(-1)[1].reason==='escape','Escape cancels keyboard recording');
41
+ await tap();window.dispatchEvent(new Event('blur'));await wait();assert(events.at(-1)[1].reason==='blur','window blur cancels latched recording');
42
+ await tap();setDisabled(true);await wait();assert(events.at(-1)[1].reason==='disabled'&&button().disabled,'disabling cancels microphone');
43
+ setDisabled(false);await wait();await tap();unmountPill();await wait();assert(events.at(-1)[1].reason==='unmount'&&frames.size===0,'unmount stops listening and animation frames');
44
+ const calls=[];let ready;
45
+ function NativeFixture(){
46
+ const voice=useNativeVoiceInput({startRecording:()=>new Promise(resolve=>{calls.push('start');ready=resolve}),
47
+ cancelRecording:async()=>{calls.push('discard')},stopRecordingAndTranscribe:async()=>{calls.push('transcribe');return 'Native words'},onSendVoiceMessage:async text=>calls.push('send:'+text)});
48
+ return React.createElement(VoicePill,{active:voice.isRecording,onStart:voice.startRecognition,
49
+ onStop:e=>['tap','release','key'].includes(e.reason)?voice.stopRecognition():voice.cancelRecognition()});
50
+ }
51
+ root.render(React.createElement(NativeFixture));await wait();pointer('pointerdown');await wait();
52
+ assert(button().getAttribute('aria-pressed')==='false'&&button().getAttribute('aria-busy')==='true','actual state waits for native device startup');
53
+ pointer('pointermove',110);pointer('pointerup',110);ready();await wait();
54
+ assert(calls.join(',')==='start,discard'&&button().getAttribute('aria-pressed')==='false','native pending-start cancellation discards without transcription');
55
+ pointer('pointerdown');await wait();ready();await wait();pointer('pointerup');await wait();
56
+ assert(button().getAttribute('aria-pressed')==='true','native success opens listening capsule');
57
+ await tap();await wait();assert(calls.at(-2)==='transcribe'&&calls.at(-1)==='send:Native words','normal native stop sends one transcript');
58
+ root.render(React.createElement('div'));await wait();
59
+ const instances=[],messages=[],sends=[];let denied=false;
60
+ class Recognition {
61
+ constructor(){instances.push(this)}
62
+ start(){setTimeout(()=>{if(denied){this.onerror?.({error:'not-allowed'});this.onend?.()}else this.onstart?.()},20)}
63
+ result(text){const result=[{transcript:text}];result.isFinal=true;this.onresult?.({resultIndex:0,results:[result]})}
64
+ stop(){setTimeout(()=>this.onend?.(),20)}
65
+ abort(){this.aborted=true;setTimeout(()=>this.onend?.(),20)}
66
+ }
67
+ window.SpeechRecognition=Recognition;
68
+ function WebFixture(){
69
+ const voice=useSpeechToText({language:'en',message:'Existing',sending:false,isSpeaking:false,onSetMessage:text=>messages.push(text),onSendVoiceMessage:async text=>sends.push(text)});
70
+ return React.createElement(VoicePill,{active:voice.isRecording,onStart:()=>voice.startRecognition(),
71
+ onStop:e=>['tap','release','key'].includes(e.reason)?voice.stopRecognition():voice.cancelRecognition()});
72
+ }
73
+ root.render(React.createElement(WebFixture));await wait();await tap();instances.at(-1).result('cancelled words');
74
+ key('Escape');await wait();assert(instances.at(-1).aborted&&messages.length===0&&sends.length===0,'Web cancellation aborts and discards recognized text');
75
+ await tap();instances.at(-1).result('hello');await tap();await wait();
76
+ assert(messages.join(',')==='Existing hello'&&sends.length===0,'Web normal stop preserves dictation into existing composer');
77
+ denied=true;await tap();await wait();assert(button().getAttribute('aria-pressed')==='false'&&!button().getAttribute('aria-busy'),'permission refusal returns to idle');
78
+ document.getElementById('result').textContent='PASS\n'+lines.join('\n');
79
+ } catch(error){document.getElementById('result').textContent='FAIL: '+error.message+'\n'+lines.join('\n');console.error(error)}
80
+ </script></body></html>
@@ -0,0 +1,34 @@
1
+ <!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Mint VoicePill composer preview</title></head>
2
+ <body><div id="root"></div><pre id="result">PREVIEW</pre><script type="module">
3
+ import React from 'react';import {createRoot} from 'react-dom/client';
4
+ import VoicePill from '../shared/components/VoicePill';
5
+ import '../shared/theme/tokens.css';import '../src-web/css/chat.css';
6
+ if(location.search.includes('mobile')) await import('../src-web/css/mobile.css');
7
+ const frames=new Map();let id=0;
8
+ window.requestAnimationFrame=cb=>{frames.set(++id,cb);return id};window.cancelAnimationFrame=id=>frames.delete(id);
9
+ function Preview(){
10
+ return React.createElement('main',{style:{width:'min(760px,calc(100vw - 40px))',margin:'100px auto',fontFamily:'system-ui',color:'#eee'}},
11
+ React.createElement('h2',null,'Voice input'),React.createElement('p',null,'Tap to dictate · Hold to record · Slide left to cancel'),
12
+ React.createElement('div',{className:'input-area voice-active'},React.createElement('form',{id:'chat-form',className:'has-live-btn',onSubmit:e=>e.preventDefault()},
13
+ React.createElement('textarea',{id:'chat-input',placeholder:'Ask Mint anything…',rows:2}),
14
+ React.createElement('span',{className:'chat-tool-menu-wrap'},React.createElement('button',{id:'chat-tool-btn',type:'button'},'+')),
15
+ React.createElement('button',{id:'screen-capture-btn',type:'button','aria-label':'Capture screen'},'▣'),
16
+ React.createElement('div',{className:'model-selector-container',style:{minWidth:0}},React.createElement('button',{className:'model-selector-trigger',type:'button',style:{maxWidth:'100%',overflow:'hidden',whiteSpace:'nowrap',textOverflow:'ellipsis'}},'OpenAI ▾')),
17
+ React.createElement(VoicePill,{id:'voice-input-btn',className:'composer-voice-pill',ariaLabel:'Voice input'}),
18
+ React.createElement('button',{id:'gemini-live-btn',type:'button'},'◉'),React.createElement('button',{id:'send-btn',type:'button'},'↑'))));
19
+ }
20
+ createRoot(document.getElementById('root')).render(React.createElement(Preview));
21
+ setTimeout(()=>{
22
+ const mic=document.getElementById('voice-input-btn');mic.dispatchEvent(new KeyboardEvent('keydown',{key:'Enter',bubbles:true,cancelable:true}));
23
+ setTimeout(()=>{
24
+ const now=performance.now();for(let i=0;i<160;i++){const batch=[...frames.values()];frames.clear();batch.forEach(cb=>cb(now+i*20));}
25
+ const capsule=mic.querySelector('.voice-pill__capsule').getBoundingClientRect();
26
+ const model=document.querySelector('.model-selector-container').getBoundingClientRect();
27
+ const send=document.getElementById('send-btn').getBoundingClientRect();
28
+ const formStyle=getComputedStyle(document.getElementById('chat-form'));
29
+ const flat=formStyle.animationName==='none'&&formStyle.boxShadow==='none'&&getComputedStyle(document.getElementById('send-btn')).boxShadow==='none';
30
+ const ok=flat&&(capsule.left>=model.right||capsule.top>=model.bottom)&&capsule.right<=send.left&&capsule.left>=0&&capsule.right<=window.innerWidth;
31
+ document.getElementById('result').textContent=ok?'PASS: flat composer and VoicePill fit without glow or overlapping controls':'FAIL: composer glow or overlapping controls '+JSON.stringify({flat,animation:formStyle.animationName,shadow:formStyle.boxShadow,capsule:{left:capsule.left,right:capsule.right},model:{left:model.left,right:model.right},send:{left:send.left}});
32
+ },500);
33
+ },500);
34
+ </script><style>body{margin:0;background:#111114}#root{width:100%}#chat-form{width:100%}*{box-sizing:border-box}#result{color:#a1a1aa;text-align:center;font-family:system-ui;font-size:12px}.model-selector-container{grid-column:3;grid-row:2;align-self:center}.model-selector-trigger{background:#27272a;color:#ddd;border:0;border-radius:6px;padding:6px}</style></body></html>
@@ -0,0 +1 @@
1
+ <!doctype html><html data-theme="dark"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"></head><body><div id="root"></div><script type="module" src="./webSources.browser.tsx"></script></body></html>
@@ -0,0 +1,98 @@
1
+ import React, { useState } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import ChatPanel from '../shared/components/ChatPanel'
4
+ import { chatPanelFixture } from './chatPanelFixture'
5
+ import { installRendererPlatform, installWorkspacePlatform } from '../shared/platform'
6
+ import * as webAdapter from '../src-web/tauri'
7
+ import type { AgentProgress, ConversationSources } from '../shared/types'
8
+ import '../shared/theme/tokens.css'
9
+ import '../src-web/css/app-shell.css'
10
+ import '../src-web/css/chat.css'
11
+ import '../src-web/css/mobile.css'
12
+
13
+ const image = 'data:image/svg+xml;base64,' + btoa('<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40"><rect width="40" height="40" fill="#73d6b0"/></svg>')
14
+ const search = (url: string): AgentProgress => ({ type: 'ToolEnd', data: { action: 'web_search', input: {}, result: `1. Source reference\nURL: ${url}\nReference` } })
15
+ const data: ConversationSources = { attachments: [
16
+ { id: 1, interactionId: 2, libraryItemId: 'reference', name: 'reference.png', kind: 'image', mimeType: 'image/png', thumbnailDataUri: image },
17
+ { id: 2, interactionId: 2, libraryItemId: 'notes', name: 'notes.pdf', kind: 'file', mimeType: 'application/pdf', thumbnailDataUri: null },
18
+ ], webSearchProgress: [search('https://example.com/reference')] }
19
+ const requests: string[] = []
20
+ let fail = false, deferA = false
21
+ let resolveA: ((data: ConversationSources) => void) | undefined
22
+ installRendererPlatform({ ...webAdapter,
23
+ getConversationSources: async chatId => { requests.push(chatId); if (fail) throw new Error('Offline'); if (chatId === 'A' && deferA) return new Promise(resolve => { resolveA = resolve }); return chatId === 'A' ? data : { attachments: [], webSearchProgress: [] } },
24
+ modsOperation: async () => ({ mods: [] }), fetchProviderModels: async () => [],
25
+ })
26
+ installWorkspacePlatform({ getGitBranchInfo: async () => ({ isRepository: false, currentBranch: null, branches: [], remoteBranches: [], detachedHead: null, isDirty: false }) } as any)
27
+ const originalFetch = window.fetch.bind(window)
28
+ window.fetch = (input, options) => String(input).includes('localhost:11434') ? Promise.resolve(new Response('{"models":[]}')) : originalFetch(input, options)
29
+ let selectChat = (_id: string) => {}, addLiveSearch = () => {}, setRunning = (_running: boolean) => {}
30
+ let cancellations = 0
31
+ function Fixture() {
32
+ const props = chatPanelFixture()
33
+ const [chatId, setChatId] = useState('A')
34
+ const [draft, setDraft] = useState('Keep my draft')
35
+ const [live, setLive] = useState<AgentProgress[]>([])
36
+ const [running, changeRunning] = useState(false)
37
+ setRunning = changeRunning
38
+ selectChat = id => { setChatId(id); setLive([]) }
39
+ addLiveSearch = () => setLive([search('https://example.com/live')])
40
+ return <>
41
+ <style>{`html,body,#root{margin:0;height:100%;width:100%;background:var(--bg-overlay);color:var(--text-main);font-family:Arial,sans-serif}*{box-sizing:border-box}#root{display:flex;flex-direction:column}.fixture-controls{padding:6px;flex:0 0 auto}.assistant-workspace{flex:1;min-height:0;min-width:0;display:flex}#qa-results{position:fixed;bottom:0;left:0;max-width:100vw;font-size:9px;white-space:pre-wrap;overflow-wrap:anywhere;pointer-events:none;z-index:900}`}</style>
42
+ <div className="fixture-controls">Real Web ChatPanel · Sources fixture</div>
43
+ <main className="assistant-workspace chat-only"><ChatPanel {...props as any} conversation={{ ...props.conversation, chatId, message: draft, sending: running, agentProgress: live, workspacePath: '/workspace/a-very-long-project-name' }} actions={{ ...props.actions, onSetMessage: setDraft, onCancelMessage: () => { cancellations++ } }} showSessionSources /></main>
44
+ <pre id="qa-results">Running…</pre>
45
+ </>
46
+ }
47
+ createRoot(document.getElementById('root')!).render(<Fixture />)
48
+ const delay = (ms = 50) => new Promise(resolve => setTimeout(resolve, ms))
49
+ async function waitFor(check: () => boolean, name: string) { for (let i = 0; i < 100; i++) { if (check()) return; await delay() } throw new Error(name) }
50
+ const results: string[] = []
51
+ const check = (value: unknown, name: string) => { if (!value) throw new Error(name); results.push(`PASS ${name}`) }
52
+ const click = (selector: string) => { const element = document.querySelector<HTMLElement>(selector); if (!element) throw new Error(`Missing ${selector}`); element.focus(); element.click() }
53
+ async function run() {
54
+ await waitFor(() => Boolean(document.querySelector('.session-sources-toggle')), 'Sources entry appears')
55
+ check(requests.length === 0, 'closed Sources does not fetch')
56
+ const actions = document.querySelector('.chat-header-actions')!
57
+ check(actions.firstElementChild?.classList.contains('session-sources-toggle'), 'Sources sits beside Tools in the real chat header')
58
+ check(actions.getBoundingClientRect().right <= innerWidth, 'header actions fit the viewport')
59
+ click('.session-sources-toggle')
60
+ await waitFor(() => document.querySelectorAll('.session-source-row').length === 3, 'Session sources load')
61
+ check(requests[0] === 'A', 'Web fetches the current conversation')
62
+ check(document.querySelector('.session-sources-heading')?.textContent?.includes('This session'), 'panel identifies its session scope')
63
+ const bounds = document.querySelector('.session-sources-popover')!.getBoundingClientRect()
64
+ check(bounds.left >= 0 && bounds.right <= innerWidth && bounds.bottom <= innerHeight, 'Sources panel fits the viewport')
65
+ check(Boolean(document.querySelector('.session-source-icon.is-web img, .session-source-icon.is-web svg')), 'website sources retain their favicon or fallback')
66
+ addLiveSearch(); await waitFor(() => document.querySelectorAll('.session-source-row').length === 4, 'Live source updates')
67
+ check(true, 'live search sources appear without reopening')
68
+ if (location.search.includes('preview')) { document.getElementById('qa-results')!.textContent = ''; return }
69
+ setRunning(true); await delay()
70
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
71
+ await waitFor(() => !document.querySelector('.session-sources-popover'), 'Escape closes Sources')
72
+ check(document.activeElement === document.querySelector('.session-sources-toggle'), 'Escape restores focus to Sources')
73
+ check(cancellations === 0, 'closing Sources with Escape does not cancel the running agent')
74
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
75
+ check(cancellations === 1, 'Escape still cancels the agent when Sources is closed')
76
+ setRunning(false); await delay()
77
+ const closedCount = requests.length; await delay(2200)
78
+ check(requests.length === closedCount, 'closing Sources stops its polling')
79
+ deferA = true; click('.session-sources-toggle'); await waitFor(() => Boolean(resolveA), 'Deferred A request')
80
+ selectChat('B'); await waitFor(() => Boolean(document.querySelector('.session-sources-empty')), 'Session B is empty')
81
+ resolveA!(data); await delay()
82
+ check(document.querySelectorAll('.session-source-row').length === 0, 'late A response cannot leak into B')
83
+ fail = true; deferA = false; selectChat('A'); await waitFor(() => Boolean(document.querySelector('.session-sources-error')), 'Source error')
84
+ fail = false; click('.session-sources-error button'); await waitFor(() => document.querySelectorAll('.session-source-row').length === 3, 'Retry loads saved sources')
85
+ check(true, 'Sources retries a failed request')
86
+ let navigated = false
87
+ const onNavigate = () => { navigated = true }; window.addEventListener('popstate', onNavigate)
88
+ click('.session-source-row[href^="/library"]'); await waitFor(() => !document.querySelector('.session-sources-popover'), 'Library navigation closes Sources')
89
+ check(navigated && location.pathname === '/library', 'source link opens Library through SPA navigation')
90
+ check(document.querySelector<HTMLTextAreaElement>('#chat-input')?.value === 'Keep my draft', 'opening a source preserves the composer draft')
91
+ window.removeEventListener('popstate', onNavigate)
92
+ click('.session-sources-toggle'); await waitFor(() => Boolean(document.querySelector('.session-sources-popover')), 'Sources reopens')
93
+ document.body.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }))
94
+ await waitFor(() => !document.querySelector('.session-sources-popover'), 'Outside click closes')
95
+ check(true, 'outside click closes Sources')
96
+ document.getElementById('qa-results')!.textContent = results.join('\n') + '\nALL PASSED'
97
+ }
98
+ run().catch(error => { document.getElementById('qa-results')!.textContent = results.join('\n') + `\nFAIL ${error.message}` })
@@ -0,0 +1,92 @@
1
+ <!-- Browser regression fixture: serve with Vite and open /tests/workspaceUndo.browser.html. Uses mocked native dialogs and workspace storage. -->
2
+ <!doctype html><html><body><div id="root"></div><pre id="result">RUNNING</pre>
3
+ <script type="module">
4
+ import React from 'react';
5
+ import { createRoot } from 'react-dom/client';
6
+ import WorkspacePanel from '/src/components/WorkspacePanel.tsx';
7
+ import DesktopTitlebar from '/shared/components/DesktopTitlebar.tsx';
8
+ import { installWorkspacePlatform } from '/shared/platform.ts';
9
+ let entries = [{ id: 'first', label: 'Undo Move to Trash: note.txt', path: 'note.txt', kind: 'trash' }];
10
+ let undoCalls = 0, trashCalls = 0, confirmCalls = 0, textCommands = [];
11
+ let confirmation;
12
+ window.__TAURI_INTERNALS__ = { invoke: async (command) => {
13
+ if (command === 'plugin:dialog|message') { confirmCalls++; return new Promise(resolve => confirmation = resolve); }
14
+ return false;
15
+ }};
16
+ window.api = { readClipboard: async () => '', quitApp() {}, closeWindow() {} };
17
+ const nativeExec = document.execCommand.bind(document);
18
+ document.execCommand = (...args) => { textCommands.push(args[0]); return nativeExec(...args); };
19
+ const noop = () => {};
20
+ const root = '/tmp/undo-ui';
21
+ const snapshot = () => ({ path: root, revision: undoCalls + trashCalls + 1,
22
+ tree: { name: 'Demo', path: '.', kind: 'directory', children: [{ name: 'note.txt', path: 'note.txt', kind: 'file', children: [] }] },
23
+ git: { isRepository: false, branches: [], remoteBranches: [], isDirty: false } });
24
+ installWorkspacePlatform({
25
+ getWorkspaceSnapshot: async () => snapshot(), listWorkspaceHistory: async () => [...entries],
26
+ undoWorkspaceAction: async (_root, _rev, expected) => {
27
+ if (expected !== entries[0]?.id) throw new Error('stale history');
28
+ undoCalls++; entries.shift(); return snapshot();
29
+ },
30
+ deleteWorkspaceItem: async () => { trashCalls++; entries.unshift({ id: 'trash', label: 'Undo Move to Trash: note.txt', path: 'note.txt', kind: 'trash' }); return snapshot(); },
31
+ moveWorkspaceItem: async () => { throw new Error('Destination already exists'); },
32
+ getWorkspaceGitDiff: async () => [], getGitBranchInfo: async () => snapshot().git,
33
+ switchGitBranch: noop, createGitBranch: noop, checkoutRemoteGitBranch: noop, getGitGraph: async () => [],
34
+ createWorkspaceFile: noop, createWorkspaceFolder: noop,
35
+ });
36
+ createRoot(document.getElementById('root')).render(React.createElement(React.Fragment, null,
37
+ React.createElement(DesktopTitlebar, { sidebarCollapsed: false, onToggleSidebar: noop, onNewChat: noop, onOpenWorkspace: noop,
38
+ onOpenTerminal: noop, onToggleTerminal: noop, onOpenBrowser: noop, toolsPanelOpen: false, onToggleToolsPanel: noop,
39
+ onOpenSettings: noop, onCheckForUpdates: noop, onShowAbout: noop, workspacePath: root, workspaceActive: true,
40
+ workspaceRevision: 0, sending: false, onWorkspaceUndoError: noop, terminalCount: 0, sourceNames: [], recentChanges: [], onOpenReview: noop, onRefreshWorkspace: noop }),
41
+ React.createElement('textarea', { id: 'composer' }),
42
+ React.createElement(WorkspacePanel, { workspacePath: root, agentMode: true, sending: false,
43
+ onEnableAgentMode: noop, onSetMessage: noop, onWorkspaceReady: noop })));
44
+ const sleep = () => new Promise(resolve => setTimeout(resolve, 25));
45
+ async function until(check) { for (let i = 0; i < 160; i++) { if (check()) return; await sleep(); } throw new Error('Timed out'); }
46
+ function assert(value, name) { if (!value) throw new Error(name); }
47
+ const checks = [];
48
+ function ok(name) { checks.push(name); }
49
+ function click(element) { element.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true })); element.click(); }
50
+ function openMenu() { document.querySelector('.workspace-tree-row').dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, cancelable: true, clientX: 100, clientY: 100 })); }
51
+ function button(container, label) { return [...document.querySelectorAll(container + ' button')].find(element => (element.querySelector('span')?.textContent || element.textContent) === label); }
52
+ try {
53
+ await until(() => document.querySelector('.workspace-tree-row') && document.querySelector('.workspace-undo-bar button'));
54
+ const composer = document.getElementById('composer'); composer.focus(); await sleep();
55
+ const key = new KeyboardEvent('keydown', { bubbles: true, cancelable: true, key: 'z', ctrlKey: true }); composer.dispatchEvent(key);
56
+ assert(!key.defaultPrevented && undoCalls === 0, 'text Ctrl+Z must stay local'); ok('text Ctrl+Z keeps browser text undo');
57
+ click(button('.mint-titlebar-nav', 'Edit') || [...document.querySelectorAll('.mint-titlebar-menu-button')].find(b => b.textContent === 'Edit'));
58
+ await sleep();
59
+ click(button('.mint-titlebar-menu', 'Undo')); await sleep();
60
+ assert(textCommands.includes('undo') && undoCalls === 0, 'Edit Undo must restore text focus'); ok('Edit Undo targets focused text');
61
+ const row = document.querySelector('.workspace-tree-row'); row.focus(); await sleep();
62
+ row.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, cancelable: true, key: 'z', ctrlKey: true }));
63
+ await until(() => undoCalls === 1); ok('workspace Ctrl+Z invokes the labelled file action');
64
+ openMenu(); await until(() => document.querySelector('.workspace-file-menu'));
65
+ assert(trashCalls === 0 && confirmCalls === 0, 'right-click is not deletion'); ok('right-click only opens menu');
66
+ click(button('.workspace-file-menu', 'Rename…'));
67
+ await until(() => document.querySelector('.workspace-file-dialog'));
68
+ document.querySelector('.workspace-file-dialog').dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
69
+ await sleep();
70
+ // The unchanged name closes without changing files. Reopen with a new name.
71
+ openMenu(); await sleep(); click(button('.workspace-file-menu', 'Move…'));
72
+ await until(() => document.querySelector('.workspace-file-dialog'));
73
+ const input = document.querySelector('.workspace-file-dialog input');
74
+ Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value').set.call(input, 'taken.txt');
75
+ input.dispatchEvent(new Event('input', { bubbles: true })); await sleep();
76
+ document.querySelector('.workspace-file-dialog').dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
77
+ await until(() => document.querySelector('.workspace-file-dialog [role=alert]'));
78
+ assert(document.querySelector('.workspace-file-dialog [role=alert]').textContent.includes('already exists'), 'move collision must be visible'); ok('Move keeps dialog open for destination conflicts');
79
+ click(button('.workspace-file-dialog', 'Cancel')); await sleep();
80
+ openMenu(); await sleep(); click(button('.workspace-file-menu', 'Move to Trash'));
81
+ await until(() => confirmCalls === 1);
82
+ assert(trashCalls === 0, 'must wait for native confirmation'); confirmation('Cancel'); await sleep();
83
+ assert(trashCalls === 0, 'Cancel must preserve file'); ok('Trash waits for confirmation; Cancel preserves file');
84
+ openMenu(); await sleep(); click(button('.workspace-file-menu', 'Move to Trash'));
85
+ await until(() => confirmCalls === 2); confirmation('Move to Trash');
86
+ await until(() => trashCalls === 1 && document.querySelector('.workspace-undo-bar button'));
87
+ assert(document.querySelector('.workspace-undo-bar button').textContent.includes('note.txt'), 'undo must name target');
88
+ click(document.querySelector('.workspace-undo-bar button'));
89
+ await until(() => undoCalls === 2); ok('Trash shows named Undo and Undo invokes restoration');
90
+ document.getElementById('result').textContent = JSON.stringify({ status: 'PASS', checks });
91
+ } catch (error) { document.getElementById('result').textContent = JSON.stringify({ status: 'FAIL', error: String(error), checks }); }
92
+ </script></body></html>
@@ -0,0 +1,40 @@
1
+ [package]
2
+ name = "mint-desktop"
3
+ version.workspace = true
4
+ edition.workspace = true
5
+ license.workspace = true
6
+
7
+ [lib]
8
+ name = "mint_desktop_lib"
9
+ crate-type = ["staticlib", "cdylib", "rlib"]
10
+
11
+ [build-dependencies]
12
+ tauri-build = { version = "2", features = [] }
13
+
14
+ [dependencies]
15
+ base64.workspace = true
16
+ dirs.workspace = true
17
+ futures-util.workspace = true
18
+ image.workspace = true
19
+ mint-core = { path = "../crates/mint-core" }
20
+ portable-pty = "0.9"
21
+ notify-rust = "4.18"
22
+ reqwest.workspace = true
23
+ serde.workspace = true
24
+ serde_json.workspace = true
25
+ # `macos-private-api` is required for transparent windows on macOS (the
26
+ # spotlight/widget overlays and the main window all set `transparent`); it is a
27
+ # no-op on other platforms. It also rules out Mac App Store distribution, which
28
+ # is fine — macOS ships as a notarization-optional `.dmg`.
29
+ tauri = { version = "2", features = ["protocol-asset", "tray-icon", "macos-private-api", "unstable"] }
30
+ tauri-plugin-dialog = "2"
31
+ tauri-plugin-global-shortcut = "2"
32
+ tauri-plugin-notification = "2"
33
+ tauri-plugin-updater = "2"
34
+ tokio.workspace = true
35
+ tokio-tungstenite.workspace = true
36
+ uuid.workspace = true
37
+ x11rb = { version = "0.13", features = ["composite"] }
38
+
39
+ [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))'.dependencies]
40
+ webkit2gtk = "2.0"
@@ -0,0 +1,3 @@
1
+ fn main() {
2
+ tauri_build::build()
3
+ }