@pheem49/mint 1.16.0 โ†’ 1.18.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 (984) hide show
  1. package/Cargo.lock +6 -6
  2. package/Cargo.toml +2 -2
  3. package/README.md +8 -2
  4. package/Release_Note.md +222 -72
  5. package/apps/mint-companion/src-tauri/src/compact.rs +69 -0
  6. package/apps/mint-companion/src-tauri/src/main.rs +218 -11
  7. package/apps/mint-companion/vite.config.ts +2 -1
  8. package/crates/mint-cli/src/agent/diff_render.rs +66 -44
  9. package/crates/mint-cli/src/agent/live_status.rs +64 -6
  10. package/crates/mint-cli/src/agent/markdown_render.rs +342 -5
  11. package/crates/mint-cli/src/agent.rs +202 -47
  12. package/crates/mint-cli/src/commands/agent.rs +223 -117
  13. package/crates/mint-cli/src/commands/browser.rs +114 -0
  14. package/crates/mint-cli/src/commands/config.rs +14 -1
  15. package/crates/mint-cli/src/commands/integrations.rs +3 -3
  16. package/crates/mint-cli/src/commands/knowledge.rs +16 -2
  17. package/crates/mint-cli/src/commands/mod.rs +15 -4
  18. package/crates/mint-cli/src/commands/tailnet_web.rs +3 -7
  19. package/crates/mint-cli/src/companion_navigation.rs +268 -0
  20. package/crates/mint-cli/src/interactive/chat_tui/dialog.rs +572 -0
  21. package/crates/mint-cli/src/interactive/chat_tui/mod.rs +1427 -0
  22. package/crates/mint-cli/src/interactive/chat_tui/render.rs +1524 -0
  23. package/crates/mint-cli/src/interactive/chat_tui/selection.rs +401 -0
  24. package/crates/mint-cli/src/interactive/chat_tui/state.rs +1833 -0
  25. package/crates/mint-cli/src/interactive/chat_tui/tests.rs +3414 -0
  26. package/crates/mint-cli/src/interactive/chat_tui/thought.rs +202 -0
  27. package/crates/mint-cli/src/interactive/chat_tui/transcript.rs +728 -0
  28. package/crates/mint-cli/src/interactive/chat_tui/watermark.rs +148 -0
  29. package/crates/mint-cli/src/interactive/command_ui.rs +92 -5
  30. package/crates/mint-cli/src/interactive/composer.rs +186 -0
  31. package/crates/mint-cli/src/interactive/format.rs +78 -3
  32. package/crates/mint-cli/src/interactive/input_box.rs +61 -1
  33. package/crates/mint-cli/src/interactive/resume_picker.rs +367 -25
  34. package/crates/mint-cli/src/interactive/slash_commands.rs +758 -373
  35. package/crates/mint-cli/src/interactive/tool_activity.rs +468 -56
  36. package/crates/mint-cli/src/interactive.rs +74 -5
  37. package/crates/mint-cli/src/main.rs +26 -2
  38. package/crates/mint-cli/src/markdown.rs +2 -37
  39. package/crates/mint-cli/src/onboard.rs +3897 -1321
  40. package/crates/mint-cli/src/setup.rs +1342 -624
  41. package/crates/mint-cli/src/terminal_theme.rs +159 -35
  42. package/crates/mint-cli/tests/library_intake.rs +1 -0
  43. package/crates/mint-cli/tests/mods_testing.rs +5 -1
  44. package/crates/mint-companion-protocol/src/lib.rs +113 -0
  45. package/crates/mint-core/src/agent/chat/anthropic.rs +318 -0
  46. package/crates/mint-core/src/agent/chat/custom.rs +149 -0
  47. package/crates/mint-core/src/agent/chat/gemini.rs +518 -0
  48. package/crates/mint-core/src/agent/chat/mod.rs +857 -0
  49. package/crates/mint-core/src/agent/chat/ollama.rs +321 -0
  50. package/crates/mint-core/src/agent/chat/openai.rs +582 -0
  51. package/crates/mint-core/src/agent/chat/streaming.rs +469 -0
  52. package/crates/mint-core/src/agent/chat/tests.rs +1479 -0
  53. package/crates/mint-core/src/agent/memory.rs +129 -8
  54. package/crates/mint-core/src/agent/safety.rs +56 -4
  55. package/crates/mint-core/src/agent/skill_inventory.rs +3 -1
  56. package/crates/mint-core/src/agent/skills.rs +1 -0
  57. package/crates/mint-core/src/agent/tasks.rs +2 -2
  58. package/crates/mint-core/src/api_server/routes/auth.rs +1 -4
  59. package/crates/mint-core/src/api_server/routes/chat.rs +53 -17
  60. package/crates/mint-core/src/api_server/routes/gemini_live.rs +14 -1
  61. package/crates/mint-core/src/api_server/routes/html_preview.rs +1 -8
  62. package/crates/mint-core/src/api_server/routes/misc.rs +116 -0
  63. package/crates/mint-core/src/api_server/routes/profile_oauth.rs +43 -26
  64. package/crates/mint-core/src/api_server/routes/sessions.rs +114 -76
  65. package/crates/mint-core/src/api_server/routes/skills_subagents.rs +11 -7
  66. package/crates/mint-core/src/api_server/routes/status_health.rs +18 -8
  67. package/crates/mint-core/src/api_server.rs +211 -65
  68. package/crates/mint-core/src/avatar_bridge.rs +5 -24
  69. package/crates/mint-core/src/browser/cdp.rs +92 -30
  70. package/crates/mint-core/src/browser/headless.rs +582 -0
  71. package/crates/mint-core/src/browser/input.rs +7 -62
  72. package/crates/mint-core/src/browser/interact.rs +0 -14
  73. package/crates/mint-core/src/browser/mod.rs +10 -30
  74. package/crates/mint-core/src/browser/navigate.rs +83 -44
  75. package/crates/mint-core/src/browser/runtime.rs +282 -0
  76. package/crates/mint-core/src/browser/session.rs +240 -400
  77. package/crates/mint-core/src/browser/workflow.rs +496 -0
  78. package/crates/mint-core/src/companion/navigation.rs +115 -0
  79. package/crates/mint-core/src/companion.rs +109 -1
  80. package/crates/mint-core/src/cron/store.rs +2 -2
  81. package/crates/mint-core/src/integrations/mcp.rs +6 -8
  82. package/crates/mint-core/src/integrations/mcp_result.rs +45 -0
  83. package/crates/mint-core/src/lib.rs +10 -11
  84. package/crates/mint-core/src/media/gemini_live.rs +636 -86
  85. package/crates/mint-core/src/media/image_proxy.rs +563 -0
  86. package/crates/mint-core/src/media/library/migration.rs +26 -0
  87. package/crates/mint-core/src/media/library/tests.rs +1 -1
  88. package/crates/mint-core/src/media/library/thumbnails.rs +8 -2
  89. package/crates/mint-core/src/media/pictures.rs +1 -1
  90. package/crates/mint-core/src/media/tool_images.rs +287 -0
  91. package/crates/mint-core/src/media/tts/playback.rs +609 -0
  92. package/crates/mint-core/src/media/tts.rs +1 -0
  93. package/crates/mint-core/src/media.rs +2 -0
  94. package/crates/mint-core/src/mods/manager.rs +101 -35
  95. package/crates/mint-core/src/orchestration/context_render.rs +878 -44
  96. package/crates/mint-core/src/orchestration/decision_parsing.rs +536 -39
  97. package/crates/mint-core/src/orchestration/diagnostics.rs +307 -0
  98. package/crates/mint-core/src/orchestration/full_skill_result_tests.rs +12 -0
  99. package/crates/mint-core/src/orchestration/image_regressions.rs +379 -0
  100. package/crates/mint-core/src/orchestration/loop_guard.rs +479 -0
  101. package/crates/mint-core/src/orchestration/mcp_outcome_tests.rs +864 -0
  102. package/crates/mint-core/src/orchestration/memory_skill.rs +88 -28
  103. package/crates/mint-core/src/orchestration/mod.rs +859 -4244
  104. package/crates/mint-core/src/orchestration/reliability.rs +581 -0
  105. package/crates/mint-core/src/orchestration/repeated_failures.rs +8 -0
  106. package/crates/mint-core/src/orchestration/review_regressions.rs +179 -28
  107. package/crates/mint-core/src/orchestration/tests.rs +1665 -0
  108. package/crates/mint-core/src/orchestration/tools/dispatch.rs +967 -0
  109. package/crates/mint-core/src/orchestration/tools/files.rs +32 -3
  110. package/crates/mint-core/src/orchestration/tools/mod.rs +5 -1
  111. package/crates/mint-core/src/orchestration/tools/planning.rs +102 -42
  112. package/crates/mint-core/src/orchestration/tools/plugins_mcp.rs +19 -4
  113. package/crates/mint-core/src/orchestration/tools/project.rs +1 -1
  114. package/crates/mint-core/src/orchestration/tools/shell.rs +157 -62
  115. package/crates/mint-core/src/orchestration/tools/web.rs +5 -1
  116. package/crates/mint-core/src/orchestration/trajectory_schema.rs +353 -0
  117. package/crates/mint-core/src/orchestration/truncation.rs +368 -0
  118. package/crates/mint-core/src/orchestration/types.rs +648 -0
  119. package/crates/mint-core/src/orchestration/verification.rs +36 -9
  120. package/crates/mint-core/src/orchestration/workspace_helpers.rs +76 -27
  121. package/crates/mint-core/src/prompts/agent.rs +69 -102
  122. package/crates/mint-core/src/prompts/tool_catalog.rs +104 -153
  123. package/crates/mint-core/src/search/files.rs +20 -0
  124. package/crates/mint-core/src/search/web_search.rs +44 -3
  125. package/crates/mint-core/src/slash/mod.rs +481 -55
  126. package/crates/mint-core/src/slash/models.rs +6 -1
  127. package/crates/mint-core/src/swarm/batch.rs +643 -0
  128. package/crates/mint-core/src/swarm/dossier.rs +152 -0
  129. package/crates/mint-core/src/swarm/labels.rs +100 -0
  130. package/crates/mint-core/src/swarm/mod.rs +158 -0
  131. package/crates/mint-core/src/swarm/permissions.rs +167 -0
  132. package/crates/mint-core/src/system/auth.rs +156 -7
  133. package/crates/mint-core/src/system/bg_shell.rs +78 -9
  134. package/crates/mint-core/src/system/config.rs +266 -35
  135. package/crates/mint-core/src/system/mint_web.rs +33 -12
  136. package/crates/mint-core/src/system/shell.rs +179 -10
  137. package/crates/mint-core/src/system/workspace.rs +204 -0
  138. package/crates/mint-core/tests/background_retention.rs +1 -1
  139. package/crates/mint-core/tests/memory_persistence.rs +27 -0
  140. package/crates/mint-mod-runtime/src/lib.rs +37 -23
  141. package/out/web/assets/ArtifactPreviewPanel-Cx6BVOOF.js +2 -0
  142. package/out/web/assets/ArtifactPreviewPanel-DAT_Y7i0.css +1 -0
  143. package/out/web/assets/CalculationCard-D2E74u5q.js +1 -0
  144. package/out/web/assets/CliSessionsView-ZbdtSjvK.css +1 -0
  145. package/out/web/assets/CliSessionsView-z5i6qGyb.js +1 -0
  146. package/out/web/assets/CodeReviewPage-BK2bOScd.css +1 -0
  147. package/out/web/assets/CodeReviewPage-Dp6zHuHu.js +2 -0
  148. package/out/web/assets/CommandPalette-DaKlzbKs.js +1 -0
  149. package/out/web/assets/ImageGenCard-BMCJHP9O.js +1 -0
  150. package/out/web/assets/ImageSearchCard-Cld_SOUg.js +1 -0
  151. package/out/web/assets/ImageStudioPanel-B5N7TjeB.js +1 -0
  152. package/out/web/assets/LibraryPage-CMB89rJ0.css +1 -0
  153. package/out/web/assets/LibraryPage-DbZEi4W_.js +2 -0
  154. package/out/web/assets/LinkedFoldersView-9B9DIPoZ.js +1 -0
  155. package/out/web/assets/McpRegistryPicker-DnXPlzI7.js +1 -0
  156. package/out/web/assets/McpServersView-CiNBNUl4.js +1 -0
  157. package/out/web/assets/MermaidCard-BBDNEXbY.js +2 -0
  158. package/out/web/assets/MintDashboard-C_UYPoNV.js +119 -0
  159. package/out/web/assets/MintDashboard-DTd8C_c8.css +1 -0
  160. package/out/web/assets/PlanCard-C2x5pajq.js +1 -0
  161. package/out/web/assets/PluginsView-DoTg9MVa.js +1 -0
  162. package/out/web/assets/RewindModal-B5oowrR0.js +1 -0
  163. package/out/web/assets/ScheduledTasksView-BD5DVPkZ.js +1 -0
  164. package/out/web/assets/SelectField-Cy6CghrU.js +1 -0
  165. package/out/web/assets/SelectField-lFEkkWCU.css +1 -0
  166. package/out/web/assets/SettingsWindow-BYl_oCFh.js +4 -0
  167. package/out/web/assets/SettingsWindow-Ckcgnjt8.css +1 -0
  168. package/out/web/assets/SkillsView-CIeWwq5z.js +2 -0
  169. package/out/web/assets/StockCard-DxUciKyp.js +1 -0
  170. package/out/web/assets/ToolSurfacePage-qBgs_VHq.css +1 -0
  171. package/out/web/assets/ToolSurfacePage-saVbVrkE.js +38 -0
  172. package/out/web/assets/UiFeatureCard-CdY0hGWy.js +1 -0
  173. package/out/web/assets/UiGridCard-BBK3I5hC.js +1 -0
  174. package/out/web/assets/UiMockupWidget-CpR9EDuc.js +1 -0
  175. package/out/web/assets/{VeoStudioPanel-DOj7_WR3.css โ†’ VeoStudioPanel-9kU9YLEN.css} +1 -1
  176. package/out/web/assets/VeoStudioPanel-Co6-wEWM.js +4 -0
  177. package/out/web/assets/WeatherCard-Buzi7Vfu.js +1 -0
  178. package/out/web/assets/WorkspacePanel-BfHKkulU.js +1 -0
  179. package/out/web/assets/WorkspacePdfPreview-Bi8Zzyir.js +2 -0
  180. package/out/web/assets/abnfDiagram-VCTEODGH-CMfR95N2.js +1 -0
  181. package/out/web/assets/architecture-7GRP2DOG-DhAM4HyO.js +1 -0
  182. package/out/web/assets/architectureDiagram-5GKGNRK7-Yk3TUJ_F.js +36 -0
  183. package/out/web/assets/{blockDiagram-NRAW4CY4-BrrqzHW5.js โ†’ blockDiagram-I7D4REHJ-X9fBgJik.js} +4 -4
  184. package/out/web/assets/c4Diagram-7LVT6UL2-Bk9x7N-8.js +38 -0
  185. package/out/web/assets/chunk-2Q5K7J3B-D2JLPQzF.js +1 -0
  186. package/out/web/assets/{chunk-TEH6E4GO-G4Cdlyrt.js โ†’ chunk-4HAMMTFA-Dx5fk1_0.js} +3 -3
  187. package/out/web/assets/{chunk-5VM5RSS4-BiPuE0io.js โ†’ chunk-5VM5RSS4-BZ2oBPYQ.js} +1 -1
  188. package/out/web/assets/chunk-75Z2AOVW-BszTQoM4.js +2 -0
  189. package/out/web/assets/chunk-DU6HZSFF-DK-As3rk.js +128 -0
  190. package/out/web/assets/chunk-F27PBJKO-LmncZZIS.js +1 -0
  191. package/out/web/assets/chunk-FOHPRMQF-JXEeeJ9r.js +161 -0
  192. package/out/web/assets/{chunk-GMAD6QVW-BuhEcgHq.js โ†’ chunk-GMAD6QVW-DSQ_sDRJ.js} +12 -12
  193. package/out/web/assets/chunk-GVQU2GXP-Cno3ulje.js +1 -0
  194. package/out/web/assets/chunk-IMKFNOWR-bIzfY9Jc.js +231 -0
  195. package/out/web/assets/chunk-JWPE2WC7-BeEMUFDw.js +1 -0
  196. package/out/web/assets/chunk-L3NEJ4N5-Dl6eOa0D.js +1 -0
  197. package/out/web/assets/chunk-OSK3NFVY-BaUGJ-cM.js +10 -0
  198. package/out/web/assets/chunk-P2QGCYS3-_066ndhH.js +1 -0
  199. package/out/web/assets/chunk-POPQ4Y6H-YT1AKhTv.js +1 -0
  200. package/out/web/assets/chunk-PWAF6VOD-CrEgDsxh.js +1 -0
  201. package/out/web/assets/chunk-SHT3W25Y-_KwaRLOl.js +168 -0
  202. package/out/web/assets/{chunk-SVP7TREG-Bu_yYb-V.js โ†’ chunk-SVP7TREG-BQ1qb32L.js} +1 -1
  203. package/out/web/assets/{chunk-LCL6LL3I-BhXV9zyH.js โ†’ chunk-TICWLB2K-BDyehCtg.js} +4 -4
  204. package/out/web/assets/chunk-XXDRQBXY-B9YlhOkE.js +1 -0
  205. package/out/web/assets/chunk-Y2CYZVJY-BxCWjNVG.js +1 -0
  206. package/out/web/assets/classDiagram-ZZMXUADV-BoSpzRCJ.js +1 -0
  207. package/out/web/assets/classDiagram-v2-VYDZK3BY-BoSpzRCJ.js +1 -0
  208. package/out/web/assets/config-2suVFPZg.css +1 -0
  209. package/out/web/assets/config-CkRCdkxn.js +2 -0
  210. package/out/web/assets/core-Mi3s5D4_.js +1 -0
  211. package/out/web/assets/cose-bilkent-JH36ORCC-qlna31ty.js +1 -0
  212. package/out/web/assets/cynefin-OW5HDTMX-Dl_31aaN.js +1 -0
  213. package/out/web/assets/cynefinDiagram-5FMLGOSQ-Bpir8jha.js +62 -0
  214. package/out/web/assets/cytoscape.esm-DWtAUG0r.js +321 -0
  215. package/out/web/assets/dagre-CnWJJM5f.js +1 -0
  216. package/out/web/assets/dagre-GXQ25YYZ-D9xu3nsq.js +4 -0
  217. package/out/web/assets/diagram-S7CK7UJ4-DeveoEeB.js +30 -0
  218. package/out/web/assets/diagram-UQ7AKVKN-p4xWRESV.js +41 -0
  219. package/out/web/assets/{diagram-VSXAHHWV-BJ86Ov2Y.js โ†’ diagram-VSXAHHWV-C7qz9NDF.js} +1 -1
  220. package/out/web/assets/diagram-VX7I27RA-DRiCa3Vd.js +24 -0
  221. package/out/web/assets/diagram-Z3DM3KII-Bt7zduQX.js +24 -0
  222. package/out/web/assets/dist-9ISJ7r-g.js +1 -0
  223. package/out/web/assets/dist-js-BV3mI7uw.js +1 -0
  224. package/out/web/assets/ebnfDiagram-PWID7BFC-DV9WpwdR.js +1 -0
  225. package/out/web/assets/{erDiagram-SSCWMZ5O-CzzmnZWT.js โ†’ erDiagram-RLTQ6QDP-BJ_nwG2m.js} +3 -3
  226. package/out/web/assets/event-D7D-EBy9.js +1 -0
  227. package/out/web/assets/eventmodeling-NTZA5JFV-BTBMrfVa.js +1 -0
  228. package/out/web/assets/flowDiagram-HODETNUW-Cdlq3cJL.js +1 -0
  229. package/out/web/assets/ganttDiagram-EL5Y4UJY-DQLdsXrC.js +292 -0
  230. package/out/web/assets/gitGraph-4MIJSDKK-CL1OEOQ_.js +1 -0
  231. package/out/web/assets/gitGraphDiagram-WWUBYQGX-8cSi42H7.js +106 -0
  232. package/out/web/assets/graphlib-Bh9gHply.js +1 -0
  233. package/out/web/assets/index-BocxnrDG.js +168 -0
  234. package/out/web/assets/index-yeh_r55a.css +1 -0
  235. package/out/web/assets/info-A6RAGUB7-C1zsX5sc.js +1 -0
  236. package/out/web/assets/infoDiagram-27XIBGKW-DsRYtIyI.js +2 -0
  237. package/out/web/assets/{ishikawaDiagram-5VMMS53U-s38yo28y.js โ†’ ishikawaDiagram-5VMMS53U-B2crwIXj.js} +4 -4
  238. package/out/web/assets/journeyDiagram-3NMN7TZE-BTH-GyVR.js +139 -0
  239. package/out/web/assets/jsx-runtime-DmUwWVTj.js +1 -0
  240. package/out/web/assets/{kanban-definition-3QL26DDD-DodjgySL.js โ†’ kanban-definition-UXKFOSKX-BeRfCnuA.js} +6 -6
  241. package/out/web/assets/katex-MCdQaEAD.js +257 -0
  242. package/out/web/assets/mermaid-parser.core-BJwgCBBc.js +7 -0
  243. package/out/web/assets/mermaid.core-CsDDodN8.js +44 -0
  244. package/out/web/assets/{mindmap-definition-FBJOCRG2-260WBDxZ.js โ†’ mindmap-definition-YA3MSWOX-B42efOQ1.js} +4 -4
  245. package/out/web/assets/modelManager-B3ZFMh8v.js +2 -0
  246. package/out/web/assets/oauthManager-Ch5Du2fF.js +1 -0
  247. package/out/web/assets/packet-AYTQ26CC-B6xUyE6r.js +1 -0
  248. package/out/web/assets/pdf-Bcahc2yC.js +56 -0
  249. package/out/web/assets/pdf.worker.min-Dkey6ZUl.mjs +27 -0
  250. package/out/web/assets/pegDiagram-XKGWAZYB-1LabVycL.js +1 -0
  251. package/out/web/assets/pie-WAS4IAKB-DJwo-nf_.js +1 -0
  252. package/out/web/assets/pieDiagram-E7YTZNPT-icmAqzy4.js +39 -0
  253. package/out/web/assets/{quadrantDiagram-AXDQQJYC-B8D3gU5d.js โ†’ quadrantDiagram-AXDQQJYC-CZ-wEx41.js} +4 -4
  254. package/out/web/assets/radar-RG4KPBEZ-D7d-Xriw.js +1 -0
  255. package/out/web/assets/railroad-74A4TZTK-viuhdYbs.js +1 -0
  256. package/out/web/assets/railroad-abnf-HS5TGJTU-DNXiCNea.js +1 -0
  257. package/out/web/assets/railroad-ebnf-LZEXJU2U-nkSu1-0C.js +1 -0
  258. package/out/web/assets/railroad-peg-WCYAUIDC-BhbMeQzz.js +1 -0
  259. package/out/web/assets/railroadDiagram-O6MQD6OU-CLpG1jUX.js +1 -0
  260. package/out/web/assets/{requirementDiagram-EFPCY7ZU-D2X-Ewik.js โ†’ requirementDiagram-BXWQKSXE-kRDrvWrc.js} +3 -3
  261. package/out/web/assets/rolldown-runtime-CNOWq4Kh.js +1 -0
  262. package/out/web/assets/rough.esm-CNnFptCR.js +1 -0
  263. package/out/web/assets/sankeyDiagram-P5KCCOFB-DxAwmq4x.js +40 -0
  264. package/out/web/assets/sequenceDiagram-WJ2MYXX4-aLgY-6Wz.js +162 -0
  265. package/out/web/assets/sizeCapture-INFHLROL-C8Q8DbV5.js +1 -0
  266. package/out/web/assets/src-CRDfRlHM.js +1 -0
  267. package/out/web/assets/stateDiagram-D77RDMKH-D5QWfOhp.js +1 -0
  268. package/out/web/assets/stateDiagram-v2-MP3YSRHH-D6OiZoAP.js +1 -0
  269. package/out/web/assets/studio-BBZQ_-QK.js +1 -0
  270. package/out/web/assets/swimlanes-42K2YHIH-CRs5UyA-.js +1 -0
  271. package/out/web/assets/swimlanesDiagram-VR7AAH4N-UgEXIsV0.js +8 -0
  272. package/out/web/assets/syntaxHighlight-C-wAGT84.js +3 -0
  273. package/out/web/assets/timeline-definition-24CTP7MA-Denqd9qb.js +120 -0
  274. package/out/web/assets/treeView-Q6P3EWNA-0my3Z3s4.js +1 -0
  275. package/out/web/assets/treemap-WGGIJYW6-B_EjkLYq.js +1 -0
  276. package/out/web/assets/vennDiagram-4TSXK5OY-DxVg3Ewr.js +34 -0
  277. package/out/web/assets/wardley-WFR3VGLG-CGD-Tj4p.js +1 -0
  278. package/out/web/assets/{wardleyDiagram-VM6X3IG4-DAdXELbQ.js โ†’ wardleyDiagram-VM6X3IG4-CmfS39Xm.js} +35 -35
  279. package/out/web/assets/window-CkUOP7t0.js +1 -0
  280. package/out/web/assets/workspaces-SYPrmbgC.js +1 -0
  281. package/out/web/assets/{xychartDiagram-S5SC5T6Z-IZIXf3Vo.js โ†’ xychartDiagram-S5SC5T6Z-BVM9bKis.js} +4 -4
  282. package/out/web/index-web.html +4 -4
  283. package/out/web/index.html +4 -4
  284. package/out/web/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  285. package/out/web/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  286. package/out/web/pdfjs/cmaps/78-H.bcmap +0 -0
  287. package/out/web/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  288. package/out/web/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  289. package/out/web/pdfjs/cmaps/78-V.bcmap +0 -0
  290. package/out/web/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  291. package/out/web/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  292. package/out/web/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  293. package/out/web/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  294. package/out/web/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  295. package/out/web/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  296. package/out/web/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  297. package/out/web/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  298. package/out/web/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  299. package/out/web/pdfjs/cmaps/Add-H.bcmap +0 -0
  300. package/out/web/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  301. package/out/web/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  302. package/out/web/pdfjs/cmaps/Add-V.bcmap +0 -0
  303. package/out/web/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  304. package/out/web/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  305. package/out/web/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  306. package/out/web/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  307. package/out/web/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  308. package/out/web/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  309. package/out/web/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  310. package/out/web/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  311. package/out/web/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  312. package/out/web/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  313. package/out/web/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  314. package/out/web/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  315. package/out/web/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  316. package/out/web/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  317. package/out/web/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  318. package/out/web/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  319. package/out/web/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  320. package/out/web/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  321. package/out/web/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  322. package/out/web/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  323. package/out/web/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  324. package/out/web/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  325. package/out/web/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  326. package/out/web/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  327. package/out/web/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  328. package/out/web/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  329. package/out/web/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  330. package/out/web/pdfjs/cmaps/B5-H.bcmap +0 -0
  331. package/out/web/pdfjs/cmaps/B5-V.bcmap +0 -0
  332. package/out/web/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  333. package/out/web/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  334. package/out/web/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  335. package/out/web/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  336. package/out/web/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  337. package/out/web/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  338. package/out/web/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  339. package/out/web/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  340. package/out/web/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  341. package/out/web/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  342. package/out/web/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  343. package/out/web/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  344. package/out/web/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  345. package/out/web/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  346. package/out/web/pdfjs/cmaps/EUC-H.bcmap +0 -0
  347. package/out/web/pdfjs/cmaps/EUC-V.bcmap +0 -0
  348. package/out/web/pdfjs/cmaps/Ext-H.bcmap +0 -0
  349. package/out/web/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  350. package/out/web/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  351. package/out/web/pdfjs/cmaps/Ext-V.bcmap +0 -0
  352. package/out/web/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  353. package/out/web/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  354. package/out/web/pdfjs/cmaps/GB-H.bcmap +4 -0
  355. package/out/web/pdfjs/cmaps/GB-V.bcmap +0 -0
  356. package/out/web/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  357. package/out/web/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  358. package/out/web/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  359. package/out/web/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  360. package/out/web/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  361. package/out/web/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  362. package/out/web/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  363. package/out/web/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  364. package/out/web/pdfjs/cmaps/GBT-H.bcmap +0 -0
  365. package/out/web/pdfjs/cmaps/GBT-V.bcmap +0 -0
  366. package/out/web/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  367. package/out/web/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  368. package/out/web/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  369. package/out/web/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  370. package/out/web/pdfjs/cmaps/H.bcmap +0 -0
  371. package/out/web/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  372. package/out/web/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  373. package/out/web/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  374. package/out/web/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  375. package/out/web/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  376. package/out/web/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  377. package/out/web/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  378. package/out/web/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  379. package/out/web/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  380. package/out/web/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  381. package/out/web/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  382. package/out/web/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  383. package/out/web/pdfjs/cmaps/Hankaku.bcmap +0 -0
  384. package/out/web/pdfjs/cmaps/Hiragana.bcmap +0 -0
  385. package/out/web/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  386. package/out/web/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  387. package/out/web/pdfjs/cmaps/KSC-H.bcmap +0 -0
  388. package/out/web/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  389. package/out/web/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  390. package/out/web/pdfjs/cmaps/KSC-V.bcmap +0 -0
  391. package/out/web/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  392. package/out/web/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  393. package/out/web/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  394. package/out/web/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  395. package/out/web/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  396. package/out/web/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  397. package/out/web/pdfjs/cmaps/Katakana.bcmap +0 -0
  398. package/out/web/pdfjs/cmaps/LICENSE +36 -0
  399. package/out/web/pdfjs/cmaps/NWP-H.bcmap +0 -0
  400. package/out/web/pdfjs/cmaps/NWP-V.bcmap +0 -0
  401. package/out/web/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  402. package/out/web/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  403. package/out/web/pdfjs/cmaps/Roman.bcmap +0 -0
  404. package/out/web/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  405. package/out/web/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  406. package/out/web/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  407. package/out/web/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  408. package/out/web/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  409. package/out/web/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  410. package/out/web/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  411. package/out/web/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  412. package/out/web/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  413. package/out/web/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  414. package/out/web/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  415. package/out/web/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  416. package/out/web/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  417. package/out/web/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  418. package/out/web/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  419. package/out/web/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  420. package/out/web/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  421. package/out/web/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  422. package/out/web/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  423. package/out/web/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  424. package/out/web/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  425. package/out/web/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  426. package/out/web/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  427. package/out/web/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  428. package/out/web/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  429. package/out/web/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  430. package/out/web/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  431. package/out/web/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  432. package/out/web/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  433. package/out/web/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  434. package/out/web/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  435. package/out/web/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  436. package/out/web/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  437. package/out/web/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  438. package/out/web/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  439. package/out/web/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  440. package/out/web/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  441. package/out/web/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  442. package/out/web/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  443. package/out/web/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  444. package/out/web/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  445. package/out/web/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  446. package/out/web/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  447. package/out/web/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  448. package/out/web/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  449. package/out/web/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  450. package/out/web/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  451. package/out/web/pdfjs/cmaps/V.bcmap +0 -0
  452. package/out/web/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  453. package/out/web/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  454. package/out/web/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  455. package/out/web/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  456. package/out/web/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  457. package/out/web/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  458. package/out/web/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  459. package/out/web/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  460. package/out/web/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  461. package/out/web/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  462. package/out/web/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  463. package/out/web/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  464. package/out/web/pdfjs/standard_fonts/LICENSE_LIBERATION +363 -0
  465. package/out/web/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  466. package/out/web/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  467. package/out/web/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  468. package/out/web/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  469. package/out/web/pdfjs/wasm/LICENSE_JBIG2 +196 -0
  470. package/out/web/pdfjs/wasm/LICENSE_OPENJPEG +39 -0
  471. package/out/web/pdfjs/wasm/LICENSE_PDFJS_JBIG2 +13 -0
  472. package/out/web/pdfjs/wasm/LICENSE_PDFJS_OPENJPEG +22 -0
  473. package/out/web/pdfjs/wasm/LICENSE_PDFJS_QCMS +19 -0
  474. package/out/web/pdfjs/wasm/LICENSE_QCMS +21 -0
  475. package/out/web/pdfjs/wasm/jbig2.wasm +0 -0
  476. package/out/web/pdfjs/wasm/jbig2_nowasm_fallback.js +15 -0
  477. package/out/web/pdfjs/wasm/openjpeg.wasm +0 -0
  478. package/out/web/pdfjs/wasm/openjpeg_nowasm_fallback.js +17 -0
  479. package/out/web/pdfjs/wasm/qcms_bg.wasm +0 -0
  480. package/out/web/pdfjs/wasm/quickjs-eval.js +16 -0
  481. package/out/web/pdfjs/wasm/quickjs-eval.wasm +0 -0
  482. package/package.json +6 -4
  483. package/shared-modules/CODEOWNERS +3 -3
  484. package/shared-modules/SDL2/SDL2_mixer.json +27 -0
  485. package/shared-modules/appstream/README.md +13 -0
  486. package/shared-modules/appstream/appstream-compose.json +111 -0
  487. package/shared-modules/dbus-glib/dbus-glib.json +2 -2
  488. package/shared-modules/libportal/libportal.json +23 -0
  489. package/shared-modules/linux-audio/fluidsynth2-static.json +2 -2
  490. package/shared-modules/linux-audio/fluidsynth2.json +2 -2
  491. package/shared-modules/linux-audio/libinstpatch.json +2 -2
  492. package/shared-modules/linux-audio/liblo-static.json +3 -0
  493. package/shared-modules/luajit/luajit.json +2 -2
  494. package/shared-modules/squashfs-tools/squashfs-tools.json +0 -3
  495. package/slash-commands.json +14 -3
  496. package/src/bin/index.js +4 -1
  497. package/src/bin/pdfjs-assets.mjs +31 -0
  498. package/src/renderer/node_modules/.vite/vitest/CACHEDIR.TAG +3 -0
  499. package/src/renderer/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  500. package/src/renderer/shared/agentProgress.ts +62 -5
  501. package/src/renderer/shared/components/Settings/AgentsTab.tsx +70 -6
  502. package/src/renderer/shared/components/Settings/AudioTab.tsx +1 -1
  503. package/src/renderer/shared/components/Settings/AutomationTab.tsx +32 -29
  504. package/src/renderer/shared/components/Settings/AvatarCropModal.tsx +32 -12
  505. package/src/renderer/shared/components/Settings/CustomProviderLogoPicker.test.tsx +65 -0
  506. package/src/renderer/shared/components/Settings/CustomProviderLogoPicker.tsx +456 -0
  507. package/src/renderer/shared/components/Settings/GeneralTab.tsx +65 -94
  508. package/src/renderer/shared/components/Settings/PluginsTab.tsx +101 -24
  509. package/src/renderer/shared/components/Settings/ProfileTab.tsx +1 -1
  510. package/src/renderer/shared/components/Settings/SettingsWindow.tsx +796 -0
  511. package/src/renderer/shared/components/Settings/ThemeTab.test.tsx +45 -0
  512. package/src/renderer/shared/components/Settings/ThemeTab.tsx +119 -4
  513. package/src/renderer/shared/components/activity/AgentActivityDrawer.tsx +270 -0
  514. package/src/renderer/shared/components/activity/AgentActivityTable.tsx +582 -0
  515. package/src/renderer/shared/components/activity/AskUserActivityCard.test.tsx +122 -0
  516. package/src/renderer/shared/components/activity/AskUserActivityCard.tsx +70 -0
  517. package/src/renderer/shared/components/{McpToolResults.tsx โ†’ activity/McpToolResults.tsx} +69 -13
  518. package/src/renderer/shared/components/{PlanChecklistWidget.tsx โ†’ activity/PlanChecklistWidget.tsx} +2 -2
  519. package/src/renderer/shared/components/activity/RunSummaryDashboard.test.tsx +127 -0
  520. package/src/renderer/shared/components/activity/RunSummaryDashboard.tsx +222 -0
  521. package/src/renderer/shared/components/activity/SubagentDagView.test.ts +123 -0
  522. package/src/renderer/shared/components/{SubagentDagView.tsx โ†’ activity/SubagentDagView.tsx} +104 -50
  523. package/src/renderer/shared/components/activity/SubagentStatusStrip.test.tsx +82 -0
  524. package/src/renderer/shared/components/activity/SubagentStatusStrip.tsx +107 -0
  525. package/src/renderer/shared/components/activity/ViewedImages.tsx +179 -0
  526. package/src/renderer/shared/components/{AuthGate.tsx โ†’ app/AuthGate.tsx} +3 -3
  527. package/src/renderer/shared/components/{ChunkErrorBoundary.tsx โ†’ app/ChunkErrorBoundary.tsx} +13 -13
  528. package/src/renderer/shared/components/{CommandPalette.tsx โ†’ app/CommandPalette.tsx} +30 -30
  529. package/src/renderer/shared/components/{DashboardSidebar.tsx โ†’ app/DashboardSidebar.tsx} +7 -5
  530. package/src/renderer/shared/components/{DesktopTitlebar.tsx โ†’ app/DesktopTitlebar.tsx} +9 -26
  531. package/src/renderer/shared/components/{ErrorNotice.tsx โ†’ app/ErrorNotice.tsx} +1 -1
  532. package/src/renderer/shared/components/{MintDashboard.tsx โ†’ app/MintDashboard.tsx} +217 -228
  533. package/src/renderer/shared/components/{ModalErrorBoundary.tsx โ†’ app/ModalErrorBoundary.tsx} +8 -8
  534. package/src/renderer/shared/components/{CalculationCard.tsx โ†’ cards/CalculationCard.tsx} +16 -30
  535. package/src/renderer/shared/components/{ImageGenCard.tsx โ†’ cards/ImageGenCard.tsx} +11 -24
  536. package/src/renderer/shared/components/{ImageSearchCard.tsx โ†’ cards/ImageSearchCard.tsx} +11 -24
  537. package/src/renderer/shared/components/{MermaidCard.tsx โ†’ cards/MermaidCard.tsx} +38 -22
  538. package/src/renderer/shared/components/cards/PlanCard.test.tsx +41 -0
  539. package/src/renderer/shared/components/cards/PlanCard.tsx +32 -0
  540. package/src/renderer/shared/components/cards/ReleaseNotesCard.test.tsx +29 -0
  541. package/src/renderer/shared/components/cards/ReleaseNotesCard.tsx +137 -0
  542. package/src/renderer/shared/components/{StockCard.tsx โ†’ cards/StockCard.tsx} +22 -38
  543. package/src/renderer/shared/components/cards/ToolResultCards.tsx +94 -0
  544. package/src/renderer/shared/components/{UiFeatureCard.tsx โ†’ cards/UiFeatureCard.tsx} +6 -6
  545. package/src/renderer/shared/components/{UiGridCard.tsx โ†’ cards/UiGridCard.tsx} +3 -3
  546. package/src/renderer/shared/components/{UiMockupWidget.tsx โ†’ cards/UiMockupWidget.tsx} +4 -4
  547. package/src/renderer/shared/components/{WeatherCard.tsx โ†’ cards/WeatherCard.tsx} +6 -6
  548. package/src/renderer/shared/components/{ApprovalCard.test.tsx โ†’ chat/ApprovalCard.test.tsx} +12 -1
  549. package/src/renderer/shared/components/{ApprovalCard.tsx โ†’ chat/ApprovalCard.tsx} +26 -7
  550. package/src/renderer/shared/components/chat/ArtifactCards.test.tsx +69 -0
  551. package/src/renderer/shared/components/chat/ArtifactCards.tsx +238 -0
  552. package/src/renderer/shared/components/chat/AttachedDocumentCard.test.tsx +39 -0
  553. package/src/renderer/shared/components/chat/AttachedDocumentCard.tsx +220 -0
  554. package/src/renderer/shared/components/chat/ChatCodeBlock.test.tsx +33 -0
  555. package/src/renderer/shared/components/{ChatCodeBlock.tsx โ†’ chat/ChatCodeBlock.tsx} +16 -2
  556. package/src/renderer/shared/components/chat/ChatMessageItem.test.tsx +183 -0
  557. package/src/renderer/shared/components/chat/ChatMessageItem.tsx +388 -0
  558. package/src/renderer/shared/components/chat/ChatModeSelector.css +227 -0
  559. package/src/renderer/shared/components/chat/ChatModeSelector.test.tsx +45 -0
  560. package/src/renderer/shared/components/chat/ChatModeSelector.tsx +198 -0
  561. package/src/renderer/shared/components/chat/ChatPanel.test.tsx +53 -0
  562. package/src/renderer/shared/components/{ChatPanel.tsx โ†’ chat/ChatPanel.tsx} +462 -537
  563. package/src/renderer/shared/components/{CollapsiblePasteInput.tsx โ†’ chat/CollapsiblePasteInput.tsx} +2 -2
  564. package/src/renderer/shared/components/{DiffReviewModal.tsx โ†’ chat/DiffReviewModal.tsx} +44 -44
  565. package/src/renderer/shared/components/chat/GeminiLiveOverlay.test.tsx +165 -0
  566. package/src/renderer/shared/components/{GeminiLiveOverlay.tsx โ†’ chat/GeminiLiveOverlay.tsx} +47 -5
  567. package/src/renderer/shared/components/{ModelSelectorPopover.tsx โ†’ chat/ModelSelectorPopover.tsx} +44 -16
  568. package/src/renderer/shared/components/chat/QueuedMessagesBanner.test.tsx +89 -0
  569. package/src/renderer/shared/components/chat/QueuedMessagesBanner.tsx +201 -0
  570. package/src/renderer/shared/components/{RewindModal.tsx โ†’ chat/RewindModal.tsx} +14 -14
  571. package/src/renderer/shared/components/{SlashChoicePanel.tsx โ†’ chat/SlashChoicePanel.tsx} +2 -2
  572. package/src/renderer/shared/components/{SlashSuggestions.test.tsx โ†’ chat/SlashSuggestions.test.tsx} +14 -0
  573. package/src/renderer/shared/components/{SlashSuggestions.tsx โ†’ chat/SlashSuggestions.tsx} +4 -4
  574. package/src/renderer/shared/components/chat/SourcesBlock.test.tsx +53 -0
  575. package/src/renderer/shared/components/{SourcesBlock.tsx โ†’ chat/SourcesBlock.tsx} +262 -123
  576. package/src/renderer/shared/components/{ThinkingBlock.tsx โ†’ chat/ThinkingBlock.tsx} +1 -1
  577. package/src/renderer/shared/components/chat/TurnFileChanges.test.tsx +130 -0
  578. package/src/renderer/shared/components/chat/TurnFileChanges.tsx +463 -0
  579. package/src/renderer/shared/components/{VoicePill.css โ†’ chat/VoicePill.css} +1 -1
  580. package/src/renderer/shared/components/{VoicePill.jsx โ†’ chat/VoicePill.jsx} +3 -2
  581. package/src/renderer/shared/components/{CliSessionsView.test.tsx โ†’ extensions/CliSessionsView.test.tsx} +2 -2
  582. package/src/renderer/shared/components/{CliSessionsView.tsx โ†’ extensions/CliSessionsView.tsx} +19 -16
  583. package/src/renderer/shared/components/{LinkedFoldersView.tsx โ†’ extensions/LinkedFoldersView.tsx} +3 -3
  584. package/src/renderer/shared/components/{McpRegistryPicker.tsx โ†’ extensions/McpRegistryPicker.tsx} +6 -6
  585. package/src/renderer/shared/components/{McpServersView.tsx โ†’ extensions/McpServersView.tsx} +105 -36
  586. package/src/renderer/shared/components/{McpToolAllowlist.tsx โ†’ extensions/McpToolAllowlist.tsx} +2 -2
  587. package/src/renderer/shared/components/{ModUi.test.tsx โ†’ extensions/ModUi.test.tsx} +9 -4
  588. package/src/renderer/shared/components/{ModsPanel.tsx โ†’ extensions/ModsPanel.tsx} +59 -7
  589. package/src/renderer/shared/components/{PluginsView.tsx โ†’ extensions/PluginsView.tsx} +6 -6
  590. package/src/renderer/shared/components/{ScheduledTasksView.tsx โ†’ extensions/ScheduledTasksView.tsx} +5 -5
  591. package/src/renderer/shared/components/extensions/SkillsView.test.tsx +31 -0
  592. package/src/renderer/shared/components/{SkillsView.tsx โ†’ extensions/SkillsView.tsx} +20 -4
  593. package/src/renderer/shared/components/{ImageStudioPanel.tsx โ†’ studio/ImageStudioPanel.tsx} +6 -6
  594. package/src/renderer/shared/components/{LibraryItemCard.tsx โ†’ studio/LibraryItemCard.tsx} +2 -2
  595. package/src/renderer/shared/components/{LibraryPage.tsx โ†’ studio/LibraryPage.tsx} +53 -10
  596. package/src/renderer/shared/components/{LibraryPreview.tsx โ†’ studio/LibraryPreview.tsx} +2 -2
  597. package/src/renderer/shared/components/{VeoStudioPanel.tsx โ†’ studio/VeoStudioPanel.tsx} +7 -7
  598. package/src/renderer/shared/components/{GlideSelect.css โ†’ ui/GlideSelect.css} +7 -6
  599. package/src/renderer/shared/components/ui/ProviderBrandIcon.test.tsx +67 -0
  600. package/src/renderer/shared/components/ui/ProviderBrandIcon.tsx +167 -0
  601. package/src/renderer/shared/components/ui/SelectField.tsx +506 -0
  602. package/src/renderer/shared/components/ui/error-recovery.css +10 -10
  603. package/src/renderer/shared/components/ui/error-recovery.tsx +1 -1
  604. package/src/renderer/shared/components/{ArtifactPreviewPanel.tsx โ†’ workspace/ArtifactPreviewPanel.tsx} +374 -118
  605. package/src/renderer/shared/components/workspace/BackgroundTerminals.test.tsx +63 -0
  606. package/src/renderer/shared/components/{BackgroundTerminals.tsx โ†’ workspace/BackgroundTerminals.tsx} +40 -9
  607. package/src/renderer/shared/components/workspace/CodeReviewPage.test.tsx +50 -0
  608. package/src/renderer/shared/components/{CodeReviewPage.tsx โ†’ workspace/CodeReviewPage.tsx} +124 -24
  609. package/src/renderer/shared/components/{GitBranchSelector.tsx โ†’ workspace/GitBranchSelector.tsx} +80 -24
  610. package/src/renderer/shared/components/workspace/SessionSources.tsx +113 -0
  611. package/src/renderer/shared/components/{TerminalDock.tsx โ†’ workspace/TerminalDock.tsx} +5 -2
  612. package/src/renderer/shared/components/workspace/ToolSurfacePage.test.tsx +81 -0
  613. package/src/renderer/shared/components/{ToolSurfacePage.tsx โ†’ workspace/ToolSurfacePage.tsx} +361 -90
  614. package/src/renderer/shared/components/{ToolsPanelToggle.tsx โ†’ workspace/ToolsPanelToggle.tsx} +1 -1
  615. package/src/renderer/shared/components/workspace/WorkspaceFileInfo.tsx +28 -0
  616. package/src/renderer/shared/components/workspace/WorkspaceMediaPreview.tsx +17 -0
  617. package/src/renderer/shared/components/{WorkspacePaneResizer.tsx โ†’ workspace/WorkspacePaneResizer.tsx} +1 -1
  618. package/src/renderer/shared/components/workspace/WorkspacePdfPreview.tsx +308 -0
  619. package/src/renderer/shared/components/workspace/WorkspacePreviewActions.test.tsx +101 -0
  620. package/src/renderer/shared/components/{WorkspacePreviewActions.tsx โ†’ workspace/WorkspacePreviewActions.tsx} +3 -3
  621. package/src/renderer/shared/components/{WorkspaceSelector.tsx โ†’ workspace/WorkspaceSelector.tsx} +99 -7
  622. package/src/renderer/shared/components/{background-terminals.css โ†’ workspace/background-terminals.css} +11 -11
  623. package/src/renderer/shared/components/{workspace-selector.css โ†’ workspace/workspace-selector.css} +84 -2
  624. package/src/renderer/shared/constants/config.ts +6 -3
  625. package/src/renderer/shared/constants/models.test.ts +51 -0
  626. package/src/renderer/shared/constants/models.ts +139 -32
  627. package/src/renderer/shared/conversation/coordinator.test.ts +46 -0
  628. package/src/renderer/shared/conversation/coordinator.ts +50 -2
  629. package/src/renderer/shared/conversation/lifecycle.test.ts +254 -4
  630. package/src/renderer/shared/conversation/lifecycle.ts +268 -12
  631. package/src/renderer/shared/conversation/progressiveStream.test.ts +83 -0
  632. package/src/renderer/shared/conversation/progressiveStream.ts +219 -0
  633. package/src/renderer/shared/conversation/projectNavigation.test.ts +18 -0
  634. package/src/renderer/shared/conversation/projectNavigation.ts +11 -0
  635. package/src/renderer/shared/conversation/transport.test.ts +20 -0
  636. package/src/renderer/shared/conversation/transport.ts +51 -9
  637. package/src/renderer/shared/conversation/useConversationCoordinator.ts +42 -12
  638. package/src/renderer/shared/css/agent-observability.css +205 -11
  639. package/src/renderer/shared/css/chat-ui-cards.css +48 -48
  640. package/src/renderer/shared/css/code-review.css +139 -110
  641. package/src/renderer/shared/css/code-sessions.css +56 -27
  642. package/src/renderer/shared/css/collapsed-paste.css +1 -1
  643. package/src/renderer/shared/css/error-notice.css +1 -1
  644. package/src/renderer/shared/css/file-changes.css +298 -51
  645. package/src/renderer/shared/css/library.css +105 -10
  646. package/src/renderer/shared/css/management-views.css +79 -38
  647. package/src/renderer/shared/css/mcp-results.css +48 -5
  648. package/src/renderer/shared/css/model-selector.css +18 -18
  649. package/src/renderer/shared/css/mods.css +7 -7
  650. package/src/renderer/shared/css/notification-notice.css +2 -2
  651. package/src/renderer/shared/css/queued-messages.css +221 -0
  652. package/src/renderer/shared/css/session-sources.css +12 -7
  653. package/src/renderer/shared/css/settings/agents.css +2 -2
  654. package/src/renderer/{src โ†’ shared}/css/settings/base.css +101 -107
  655. package/src/renderer/shared/css/settings/general.css +397 -100
  656. package/src/renderer/shared/css/settings/plugins.css +8 -8
  657. package/src/renderer/shared/css/settings/profile.css +5 -5
  658. package/src/renderer/shared/css/settings/theme.css +49 -37
  659. package/src/renderer/shared/css/slash-choice.css +2 -2
  660. package/src/renderer/shared/css/slash-suggestions.css +3 -3
  661. package/src/renderer/shared/css/sources-block.css +41 -2
  662. package/src/renderer/shared/css/tools-panel.css +2 -2
  663. package/src/renderer/shared/css/ui-tailwind.css +10 -2
  664. package/src/renderer/shared/css/veo-studio.css +2 -2
  665. package/src/renderer/shared/css/viewed-images.css +93 -4
  666. package/src/renderer/shared/css/workspace-file-info.css +12 -0
  667. package/src/renderer/shared/css/workspace-media-preview.css +13 -0
  668. package/src/renderer/shared/env.d.ts +9 -0
  669. package/src/renderer/shared/platform.test.ts +143 -0
  670. package/src/renderer/shared/platform.ts +12 -5
  671. package/src/renderer/shared/speech/player.ts +160 -0
  672. package/src/renderer/shared/speech/types.ts +11 -0
  673. package/src/renderer/shared/theme/themeManager.test.ts +37 -0
  674. package/src/renderer/shared/theme/themeManager.ts +24 -5
  675. package/src/renderer/shared/theme/themes.ts +71 -4
  676. package/src/renderer/shared/theme/tokens.css +452 -53
  677. package/src/renderer/shared/types.ts +57 -2
  678. package/src/renderer/shared/utils/agentActivity.test.ts +633 -8
  679. package/src/renderer/shared/utils/agentActivity.ts +776 -59
  680. package/src/renderer/shared/utils/artifactBrowser.test.ts +37 -32
  681. package/src/renderer/shared/utils/artifactBrowser.ts +18 -20
  682. package/src/renderer/shared/utils/artifacts.ts +55 -0
  683. package/src/renderer/shared/utils/attachedDocument.test.ts +73 -0
  684. package/src/renderer/shared/utils/attachedDocument.ts +49 -0
  685. package/src/renderer/shared/utils/contextCompaction.test.tsx +1 -1
  686. package/src/renderer/shared/utils/externalLinks.ts +91 -0
  687. package/src/renderer/shared/utils/fileIcons.test.ts +59 -0
  688. package/src/renderer/shared/utils/fileIcons.ts +149 -16
  689. package/src/renderer/shared/utils/lazyWithRetry.ts +13 -0
  690. package/src/renderer/shared/utils/markdown.tsx +238 -51
  691. package/src/renderer/shared/utils/markdown.webImages.test.tsx +140 -2
  692. package/src/renderer/shared/utils/mcpResults.test.tsx +53 -1
  693. package/src/renderer/shared/utils/pdfRange.ts +16 -0
  694. package/src/renderer/shared/utils/previewObjectUrls.ts +20 -0
  695. package/src/renderer/shared/utils/sessionSources.test.ts +41 -1
  696. package/src/renderer/shared/utils/sessionSources.ts +2 -0
  697. package/src/renderer/shared/utils/slashCommandProcessor.ts +7 -1
  698. package/src/renderer/shared/utils/speech.ts +18 -4
  699. package/src/renderer/shared/utils/syntaxHighlight.test.tsx +11 -1
  700. package/src/renderer/shared/utils/syntaxHighlight.tsx +51 -3
  701. package/src/renderer/shared/utils/useGeminiLiveVoice.ts +324 -51
  702. package/src/renderer/shared/utils/useNativeVoiceInput.ts +19 -5
  703. package/src/renderer/shared/utils/useSessionSources.ts +4 -0
  704. package/src/renderer/shared/utils/viewedImages.test.ts +129 -0
  705. package/src/renderer/shared/utils/viewedImages.ts +81 -10
  706. package/src/renderer/shared/utils/workspaceDrag.test.ts +153 -0
  707. package/src/renderer/shared/utils/workspaceDrag.ts +172 -0
  708. package/src/renderer/shared/utils/workspaceImage.ts +17 -0
  709. package/src/renderer/shared/utils/workspaceListPreferences.test.ts +64 -0
  710. package/src/renderer/shared/utils/workspaceListPreferences.ts +54 -0
  711. package/src/renderer/shared/utils/workspaceMedia.ts +49 -0
  712. package/src/renderer/shared/utils/workspacePreview.test.ts +147 -2
  713. package/src/renderer/shared/utils/workspacePreview.ts +34 -3
  714. package/src/renderer/shared/utils/workspaces.ts +3 -2
  715. package/src/renderer/src/App.tsx +20 -16
  716. package/src/renderer/src/agentProgress.ts +1 -0
  717. package/src/renderer/src/components/ChatPanel.tsx +1 -1
  718. package/src/renderer/src/components/DashboardSidebar.tsx +2 -2
  719. package/src/renderer/src/components/ImageStudioPanel.tsx +1 -1
  720. package/src/renderer/src/components/LiveTranslateControls.tsx +1 -1
  721. package/src/renderer/src/components/MintDashboard.tsx +1 -1
  722. package/src/renderer/src/components/ProactiveGlow.tsx +1 -1
  723. package/src/renderer/src/components/ScreenPicker.css +1 -1
  724. package/src/renderer/src/components/ScreenPicker.tsx +1 -1
  725. package/src/renderer/src/components/SettingsWindow.tsx +6 -830
  726. package/src/renderer/src/components/SpotlightWindow.tsx +4 -32
  727. package/src/renderer/src/components/VeoStudioPanel.tsx +1 -1
  728. package/src/renderer/src/components/WorkspacePanel.tsx +49 -15
  729. package/src/renderer/src/components/browser-suggestions-popup.css +8 -8
  730. package/src/renderer/src/css/app-shell.css +26 -106
  731. package/src/renderer/src/css/chat.css +1499 -292
  732. package/src/renderer/src/css/desktop-tools.css +17 -348
  733. package/src/renderer/src/css/sidebar-workspace.css +22 -2
  734. package/src/renderer/src/css/spotlight.css +2 -2
  735. package/src/renderer/src/css/tool-surfaces.css +335 -65
  736. package/src/renderer/src/css/widget.css +6 -5
  737. package/src/renderer/src/env.d.ts +13 -0
  738. package/src/renderer/src/index.css +53 -83
  739. package/src/renderer/src/tauri.ts +99 -13
  740. package/src/renderer/src/voiceInput.ts +3 -1
  741. package/src/renderer/src-web/App.tsx +20 -8
  742. package/src/renderer/src-web/agentProgress.ts +1 -0
  743. package/src/renderer/src-web/components/ChatPanel.tsx +1 -1
  744. package/src/renderer/src-web/components/DashboardSidebar.tsx +2 -2
  745. package/src/renderer/src-web/components/ImageStudioPanel.tsx +1 -1
  746. package/src/renderer/src-web/components/MintDashboard.tsx +1 -1
  747. package/src/renderer/src-web/components/SettingsWindow.tsx +6 -851
  748. package/src/renderer/src-web/components/VeoStudioPanel.tsx +1 -1
  749. package/src/renderer/src-web/css/app-shell.css +20 -104
  750. package/src/renderer/src-web/css/chat.css +1536 -261
  751. package/src/renderer/src-web/css/mobile.css +29 -13
  752. package/src/renderer/src-web/css/settings/mobile.css +2 -2
  753. package/src/renderer/src-web/css/sidebar-workspace.css +21 -1
  754. package/src/renderer/src-web/env.d.ts +14 -0
  755. package/src/renderer/src-web/index.css +53 -83
  756. package/src/renderer/src-web/tauri.ts +93 -15
  757. package/src/renderer/tests/browserArtifacts.browser.html +1 -0
  758. package/src/renderer/tests/browserArtifacts.browser.tsx +68 -0
  759. package/src/renderer/tests/chatEscape.browser.html +1 -0
  760. package/src/renderer/tests/chatEscape.browser.tsx +25 -0
  761. package/src/renderer/tests/chatPerformance.browser.html +1 -1
  762. package/src/renderer/tests/collapsedPaste.browser.html +1 -1
  763. package/src/renderer/tests/composerMenus.browser.html +3 -3
  764. package/src/renderer/tests/contextCompaction.browser.html +1 -1
  765. package/src/renderer/tests/errorRecovery.browser.html +1 -1
  766. package/src/renderer/tests/fixtures/preview.webm +0 -0
  767. package/src/renderer/tests/glideSelect.browser.html +1 -2
  768. package/src/renderer/tests/glideSelect.preview.html +1 -1
  769. package/src/renderer/tests/library.browser.tsx +4 -1
  770. package/src/renderer/tests/liveOrb.browser.html +1 -1
  771. package/src/renderer/tests/liveVoice.browser.html +1 -0
  772. package/src/renderer/tests/mediaFixtures.ts +32 -0
  773. package/src/renderer/tests/modInput.browser.html +1 -1
  774. package/src/renderer/tests/sessionSources.browser.tsx +76 -15
  775. package/src/renderer/tests/toolsPanel.browser.tsx +5 -5
  776. package/src/renderer/tests/viewedImages.browser.tsx +3 -3
  777. package/src/renderer/tests/voiceDictation.browser.html +101 -0
  778. package/src/renderer/tests/voicePill.browser.html +3 -3
  779. package/src/renderer/tests/voicePill.preview.html +1 -1
  780. package/src/renderer/tests/webSources.browser.tsx +2 -98
  781. package/src/renderer/tests/workspaceDrop.browser.html +1 -0
  782. package/src/renderer/tests/workspaceDrop.browser.tsx +183 -0
  783. package/src/renderer/tests/workspaceExpansion.browser.html +1 -0
  784. package/src/renderer/tests/workspaceExpansion.browser.tsx +66 -0
  785. package/src/renderer/tests/workspaceRemoval.browser.html +66 -0
  786. package/src/renderer/tests/workspaceUndo.browser.html +10 -2
  787. package/src-tauri/src/app/lifecycle.rs +45 -15
  788. package/src-tauri/src/background/headless.rs +14 -8
  789. package/src-tauri/src/commands/conversation.rs +137 -73
  790. package/src-tauri/src/commands/integrations.rs +7 -1
  791. package/src-tauri/src/commands/media.rs +7 -0
  792. package/src-tauri/src/commands/workspace.rs +38 -0
  793. package/src-tauri/src/native/mod.rs +0 -1
  794. package/src-tauri/src/native/system.rs +4 -47
  795. package/tsconfig.json +15 -1
  796. package/vite.config.ts +2 -1
  797. package/vite.config.web.ts +2 -0
  798. package/crates/mint-cli/src/interactive/chat_tui.rs +0 -7853
  799. package/crates/mint-core/src/agent/chat.rs +0 -4155
  800. package/crates/mint-core/src/browser/lifecycle.rs +0 -191
  801. package/crates/mint-core/src/browser/logging.rs +0 -20
  802. package/crates/mint-core/src/orchestration/tools/browser.rs +0 -31
  803. package/out/web/assets/CliSessionsView-CtzUJpK_.css +0 -1
  804. package/out/web/assets/CliSessionsView-D7hw0Mgj.js +0 -1
  805. package/out/web/assets/CodeReviewPage-C7bEOJfd.js +0 -4
  806. package/out/web/assets/CodeReviewPage-Dte9uLiL.css +0 -1
  807. package/out/web/assets/CommandPalette-0RrF-AOT.js +0 -1
  808. package/out/web/assets/ImageStudioPanel-CdxkAf_r.js +0 -1
  809. package/out/web/assets/LibraryPage--Qfisp6D.js +0 -2
  810. package/out/web/assets/LibraryPage-DAxUTAg7.css +0 -1
  811. package/out/web/assets/LinkedFoldersView-2nfZbDgN.js +0 -1
  812. package/out/web/assets/McpRegistryPicker-h9uS8_wT.js +0 -1
  813. package/out/web/assets/McpServersView-slfQJzNB.js +0 -1
  814. package/out/web/assets/MintDashboard-BSR5XpXh.js +0 -25
  815. package/out/web/assets/MintDashboard-CWUcCGhd.css +0 -1
  816. package/out/web/assets/PluginsView-l7LSm503.js +0 -1
  817. package/out/web/assets/ScheduledTasksView-CttmLbq1.js +0 -1
  818. package/out/web/assets/SettingsWindow-BCMLYvEV.js +0 -4
  819. package/out/web/assets/SettingsWindow-DcMVmU9u.css +0 -1
  820. package/out/web/assets/SkillsView-rNs1qr_U.js +0 -2
  821. package/out/web/assets/ToolSurfacePage-B9DzEPWN.js +0 -37
  822. package/out/web/assets/ToolSurfacePage-CTfgggF2.css +0 -1
  823. package/out/web/assets/VeoStudioPanel-DiJs_Cg2.js +0 -4
  824. package/out/web/assets/WorkspacePanel-CbJ1PFoZ.js +0 -1
  825. package/out/web/assets/WorkspaceSelector-B2xIp04D.js +0 -1
  826. package/out/web/assets/WorkspaceSelector-Ca8uJOsS.css +0 -1
  827. package/out/web/assets/abnfDiagram-VCTEODGH-CD0CjoGl.js +0 -1
  828. package/out/web/assets/architecture-7GRP2DOG-RKV83OeZ.js +0 -1
  829. package/out/web/assets/architectureDiagram-5GKGNRK7-nN_HAFct.js +0 -36
  830. package/out/web/assets/c4Diagram-UCG6FXSJ-DTdV8_zE.js +0 -38
  831. package/out/web/assets/chunk-2Q5K7J3B-Dmqrq8Tp.js +0 -1
  832. package/out/web/assets/chunk-75Z2AOVW-_M0z5olV.js +0 -2
  833. package/out/web/assets/chunk-CKBBP62Z-BpQEgeHF.js +0 -2
  834. package/out/web/assets/chunk-CLGD4ZFX-D54yGvGS.js +0 -1
  835. package/out/web/assets/chunk-CacB07dV.js +0 -1
  836. package/out/web/assets/chunk-DSNCTWBM-C-gvT2ru.js +0 -2
  837. package/out/web/assets/chunk-DU6HZSFF-CnFngIhW.js +0 -128
  838. package/out/web/assets/chunk-F27PBJKO-BqtWrnEO.js +0 -1
  839. package/out/web/assets/chunk-FOHPRMQF-BaVC1uA7.js +0 -161
  840. package/out/web/assets/chunk-G27WJ6UU-Ckoq5mi2.js +0 -231
  841. package/out/web/assets/chunk-JQ64N6SF-CF8T7GiZ.js +0 -1
  842. package/out/web/assets/chunk-JWPE2WC7-BwtYOHqU.js +0 -1
  843. package/out/web/assets/chunk-LNGE3PJU-AdBoOWw2.js +0 -34
  844. package/out/web/assets/chunk-OBVCFTLP-CRIkunUB.js +0 -1
  845. package/out/web/assets/chunk-P2QGCYS3-UFEU6BxZ.js +0 -1
  846. package/out/web/assets/chunk-POPQ4Y6H-CQcrNbjr.js +0 -1
  847. package/out/web/assets/chunk-PWAF6VOD-Cc2uVDsG.js +0 -1
  848. package/out/web/assets/chunk-R7TYR2AO-DiCxzdAY.js +0 -10
  849. package/out/web/assets/chunk-RHFEMEQ7-b7hnPmrR.js +0 -168
  850. package/out/web/assets/chunk-XXDRQBXY-DnJkbUaw.js +0 -1
  851. package/out/web/assets/chunk-Y2CYZVJY-C9o-s6OY.js +0 -1
  852. package/out/web/assets/classDiagram-DTDB5LWJ-RnC2mYO4.js +0 -1
  853. package/out/web/assets/classDiagram-v2-JRS7N3AN-RnC2mYO4.js +0 -1
  854. package/out/web/assets/config-CnvCChUM.js +0 -2
  855. package/out/web/assets/config-DM6oIVO3.css +0 -1
  856. package/out/web/assets/core-DsKkQ7ig.js +0 -1
  857. package/out/web/assets/cose-bilkent-JH36ORCC--UN4aw5-.js +0 -1
  858. package/out/web/assets/cynefin-OW5HDTMX-CnzQfOGp.js +0 -1
  859. package/out/web/assets/cynefinDiagram-5FMLGOSQ-DVtQnfpm.js +0 -62
  860. package/out/web/assets/cytoscape.esm-Df1UN4Y1.js +0 -321
  861. package/out/web/assets/dagre-3AP2YEHR-DG76_k5_.js +0 -4
  862. package/out/web/assets/dagre-BWadQu2F.js +0 -1
  863. package/out/web/assets/diagram-S7CK7UJ4-CaouUoze.js +0 -30
  864. package/out/web/assets/diagram-UQ7AKVKN-B4bEc26B.js +0 -41
  865. package/out/web/assets/diagram-VX7I27RA-7hH5IPYf.js +0 -24
  866. package/out/web/assets/diagram-Z3DM3KII-CCM4clo8.js +0 -24
  867. package/out/web/assets/dist-BoTOASLF.js +0 -1
  868. package/out/web/assets/dist-js-BkYNznHX.js +0 -1
  869. package/out/web/assets/ebnfDiagram-PWID7BFC-Da7WAM3k.js +0 -1
  870. package/out/web/assets/event-Cdt7Byyj.js +0 -1
  871. package/out/web/assets/eventmodeling-NTZA5JFV-xcfsA0XD.js +0 -1
  872. package/out/web/assets/flowDiagram-A5DVABFB-JdtH1673.js +0 -1
  873. package/out/web/assets/ganttDiagram-EL5Y4UJY-B3ClFGmL.js +0 -292
  874. package/out/web/assets/gitGraph-4MIJSDKK-BZ_y_cDU.js +0 -1
  875. package/out/web/assets/gitGraphDiagram-WWUBYQGX-drhRSYm3.js +0 -106
  876. package/out/web/assets/graphlib-CTR5ZhLf.js +0 -1
  877. package/out/web/assets/index-BZ9xgmMP.css +0 -1
  878. package/out/web/assets/index-Ca8cCS4h.js +0 -168
  879. package/out/web/assets/info-A6RAGUB7-B7I3K0F1.js +0 -1
  880. package/out/web/assets/infoDiagram-RXCK75RN-deX_1MPh.js +0 -2
  881. package/out/web/assets/journeyDiagram-EYS64GPL-CZn2kB8b.js +0 -139
  882. package/out/web/assets/jsx-runtime-DN4NhQUK.js +0 -1
  883. package/out/web/assets/katex-O3jvqgnU.js +0 -257
  884. package/out/web/assets/markdown-CMhYIcWB.js +0 -39
  885. package/out/web/assets/mermaid-parser.core-Whu2rlJC.js +0 -7
  886. package/out/web/assets/mermaid.core-CKyPo8VH.js +0 -11
  887. package/out/web/assets/modelManager-CUaGWMWu.js +0 -2
  888. package/out/web/assets/oauthManager-DlNhXJr6.js +0 -1
  889. package/out/web/assets/packet-AYTQ26CC-CEeIRKRG.js +0 -1
  890. package/out/web/assets/pegDiagram-XKGWAZYB-BYadI-KO.js +0 -1
  891. package/out/web/assets/pie-WAS4IAKB-D8uf4dh5.js +0 -1
  892. package/out/web/assets/pieDiagram-E7YTZNPT-CjSDy4hO.js +0 -39
  893. package/out/web/assets/radar-RG4KPBEZ-DZJxnokY.js +0 -1
  894. package/out/web/assets/railroad-74A4TZTK-DBysUiUi.js +0 -1
  895. package/out/web/assets/railroad-abnf-HS5TGJTU-CHWxoJYg.js +0 -1
  896. package/out/web/assets/railroad-ebnf-LZEXJU2U-DDv7X6bY.js +0 -1
  897. package/out/web/assets/railroad-peg-WCYAUIDC-DpfcYYNJ.js +0 -1
  898. package/out/web/assets/railroadDiagram-O6MQD6OU-CYtyv0t3.js +0 -1
  899. package/out/web/assets/rough.esm-DFbTUy8a.js +0 -1
  900. package/out/web/assets/sankeyDiagram-P5KCCOFB-Bn2x6C4Y.js +0 -40
  901. package/out/web/assets/sequenceDiagram-WJ2MYXX4-BvFLKtPd.js +0 -162
  902. package/out/web/assets/sizeCapture-X5ZJPWSS-DKeOCaN2.js +0 -1
  903. package/out/web/assets/src-DnfeXQPr.js +0 -1
  904. package/out/web/assets/stateDiagram-HBIQ2CUA-Bx0GWeaY.js +0 -1
  905. package/out/web/assets/stateDiagram-v2-4QOOHH4V--hol1yg_.js +0 -1
  906. package/out/web/assets/studio-B1mk40wD.js +0 -1
  907. package/out/web/assets/swimlanes-XN3QIQJK-CCma0T7L.js +0 -1
  908. package/out/web/assets/swimlanesDiagram-VK2B7HYN-BkohoVsU.js +0 -8
  909. package/out/web/assets/timeline-definition-24CTP7MA-iCRhhJ7C.js +0 -120
  910. package/out/web/assets/treeView-Q6P3EWNA-DZ-y08qp.js +0 -1
  911. package/out/web/assets/treemap-WGGIJYW6-De0CxzMx.js +0 -1
  912. package/out/web/assets/vennDiagram-4TSXK5OY-w_7aZ6xe.js +0 -34
  913. package/out/web/assets/wardley-WFR3VGLG-DT0y0xJ4.js +0 -1
  914. package/out/web/assets/window-BJCVtyET.js +0 -1
  915. package/shared-modules/libsecret/libsecret.json +0 -23
  916. package/shared-modules/libusb/libusb.json +0 -27
  917. package/shared-modules/lzo/lzo.json +0 -27
  918. package/src/renderer/shared/components/AgentActivityDrawer.tsx +0 -204
  919. package/src/renderer/shared/components/AgentActivityTable.tsx +0 -301
  920. package/src/renderer/shared/components/ChatMessageItem.test.tsx +0 -68
  921. package/src/renderer/shared/components/ChatMessageItem.tsx +0 -326
  922. package/src/renderer/shared/components/ChatPanel.test.tsx +0 -21
  923. package/src/renderer/shared/components/FormattedMessage.tsx +0 -11
  924. package/src/renderer/shared/components/GeminiLiveOverlay.test.tsx +0 -24
  925. package/src/renderer/shared/components/GlideSelect.d.ts +0 -31
  926. package/src/renderer/shared/components/GlideSelect.jsx +0 -266
  927. package/src/renderer/shared/components/InlineThoughtNote.tsx +0 -27
  928. package/src/renderer/shared/components/ModSessionControls.tsx +0 -8
  929. package/src/renderer/shared/components/ModUi.tsx +0 -26
  930. package/src/renderer/shared/components/ProgressActivity.tsx +0 -17
  931. package/src/renderer/shared/components/ReviewHistory.tsx +0 -42
  932. package/src/renderer/shared/components/RunSummaryDashboard.tsx +0 -143
  933. package/src/renderer/shared/components/SelectField.tsx +0 -38
  934. package/src/renderer/shared/components/SessionSources.tsx +0 -48
  935. package/src/renderer/shared/components/SessionSourcesPopover.tsx +0 -61
  936. package/src/renderer/shared/components/ToolSurfacePage.test.tsx +0 -32
  937. package/src/renderer/shared/components/ViewedImages.tsx +0 -36
  938. package/src/renderer/shared/components/WorkspaceContextPopover.tsx +0 -138
  939. package/src/renderer/shared/components/WorkspacePreviewActions.test.tsx +0 -44
  940. package/src/renderer/shared/components/ui/demo.tsx +0 -26
  941. package/src/renderer/shared/css/session-sources-popover.css +0 -9
  942. package/src/renderer/src/components/BrowserShell.tsx +0 -108
  943. package/src/renderer/src/components/BrowserSuggestionsPopup.tsx +0 -91
  944. package/src/renderer/src/components/CalculationCard.tsx +0 -3
  945. package/src/renderer/src/components/ImageGenCard.tsx +0 -2
  946. package/src/renderer/src/components/ImageSearchCard.tsx +0 -2
  947. package/src/renderer/src/components/MermaidCard.tsx +0 -1
  948. package/src/renderer/src/components/PicturesLibrary.tsx +0 -2
  949. package/src/renderer/src/components/Settings/AgentsTab.tsx +0 -4
  950. package/src/renderer/src/components/Settings/AudioTab.tsx +0 -3
  951. package/src/renderer/src/components/Settings/AutomationTab.tsx +0 -3
  952. package/src/renderer/src/components/Settings/GeneralTab.tsx +0 -3
  953. package/src/renderer/src/components/Settings/MemoryTab.tsx +0 -3
  954. package/src/renderer/src/components/Settings/PluginsTab.tsx +0 -3
  955. package/src/renderer/src/components/Settings/ProfileTab.tsx +0 -3
  956. package/src/renderer/src/components/Settings/ShortcutsTab.tsx +0 -3
  957. package/src/renderer/src/components/Settings/ThemeTab.tsx +0 -3
  958. package/src/renderer/src/components/StockCard.tsx +0 -3
  959. package/src/renderer/src/components/WeatherCard.tsx +0 -3
  960. package/src/renderer/src/components/browser-shell.css +0 -185
  961. package/src/renderer/src/css/pictures.css +0 -2
  962. package/src/renderer/src-web/components/PicturesLibrary.tsx +0 -2
  963. package/src/renderer/src-web/components/Settings/AgentsTab.tsx +0 -4
  964. package/src/renderer/src-web/components/Settings/AudioTab.tsx +0 -3
  965. package/src/renderer/src-web/components/Settings/AutomationTab.tsx +0 -3
  966. package/src/renderer/src-web/components/Settings/GeneralTab.tsx +0 -3
  967. package/src/renderer/src-web/components/Settings/MemoryTab.tsx +0 -3
  968. package/src/renderer/src-web/components/Settings/PluginsTab.tsx +0 -3
  969. package/src/renderer/src-web/components/Settings/ProfileTab.tsx +0 -3
  970. package/src/renderer/src-web/components/Settings/ShortcutsTab.tsx +0 -3
  971. package/src/renderer/src-web/components/Settings/ThemeTab.tsx +0 -3
  972. package/src/renderer/src-web/css/pictures.css +0 -2
  973. package/src/renderer/src-web/css/settings/base.css +0 -1266
  974. package/src/renderer/src-web/css/spotlight.css +0 -102
  975. package/src/renderer/src-web/css/widget.css +0 -213
  976. package/src-tauri/src/native/browser.rs +0 -252
  977. /package/src/renderer/shared/components/{ContextCompactionStatus.tsx โ†’ chat/ContextCompactionStatus.tsx} +0 -0
  978. /package/src/renderer/shared/components/{GeminiLiveOverlay.css โ†’ chat/GeminiLiveOverlay.css} +0 -0
  979. /package/src/renderer/shared/components/{VirtualChatHistory.tsx โ†’ chat/VirtualChatHistory.tsx} +0 -0
  980. /package/src/renderer/shared/components/{VoicePill.d.ts โ†’ chat/VoicePill.d.ts} +0 -0
  981. /package/src/renderer/shared/components/{VoicePill.test.tsx โ†’ chat/VoicePill.test.tsx} +0 -0
  982. /package/src/renderer/shared/components/{ScreenCaptureDialog.css โ†’ studio/ScreenCaptureDialog.css} +0 -0
  983. /package/src/renderer/shared/components/{ScreenCaptureDialog.tsx โ†’ studio/ScreenCaptureDialog.tsx} +0 -0
  984. /package/src/renderer/shared/components/{SelectField.test.tsx โ†’ ui/SelectField.test.tsx} +0 -0
@@ -159,14 +159,46 @@ fn first_line_preview(path: &Path) -> String {
159
159
  .map(str::trim)
160
160
  .find(|l| !l.is_empty())
161
161
  .unwrap_or("");
162
- if first.chars().count() > 80 {
163
- let short: String = first.chars().take(80).collect();
162
+ let clean = first.trim_start_matches('#').trim();
163
+ if clean.chars().count() > 80 {
164
+ let short: String = clean.chars().take(80).collect();
164
165
  format!("{short}โ€ฆ")
165
166
  } else {
166
- first.to_string()
167
+ clean.to_string()
167
168
  }
168
169
  }
169
170
 
171
+ fn format_plan_meta(path: &Path) -> String {
172
+ let stem = path.file_stem().and_then(|s| s.to_str()).unwrap_or("");
173
+ if stem.len() >= 15 && stem.as_bytes().get(8) == Some(&b'-') {
174
+ let y = &stem[0..4];
175
+ let m = &stem[4..6];
176
+ let d = &stem[6..8];
177
+ let hh = &stem[9..11];
178
+ let mm = &stem[11..13];
179
+ let ss = &stem[13..15];
180
+ if y.chars().all(|c| c.is_ascii_digit())
181
+ && m.chars().all(|c| c.is_ascii_digit())
182
+ && d.chars().all(|c| c.is_ascii_digit())
183
+ && hh.chars().all(|c| c.is_ascii_digit())
184
+ && mm.chars().all(|c| c.is_ascii_digit())
185
+ && ss.chars().all(|c| c.is_ascii_digit())
186
+ {
187
+ let date_str = format!("{y}-{m}-{d} {hh}:{mm}:{ss}");
188
+ if stem.len() > 16 {
189
+ let slug = &stem[16..];
190
+ return format!("{date_str} ยท {slug}");
191
+ } else {
192
+ return date_str;
193
+ }
194
+ }
195
+ }
196
+ path.file_name()
197
+ .and_then(|n| n.to_str())
198
+ .unwrap_or("")
199
+ .to_string()
200
+ }
201
+
170
202
  async fn execute_core_slash(
171
203
  session: &mut InteractiveSession,
172
204
  ui: &mut dyn CommandUi,
@@ -205,7 +237,19 @@ async fn execute_core_slash(
205
237
  match response {
206
238
  SlashResponse::Message { markdown } => {
207
239
  if !markdown.is_empty() {
208
- ui.push_command_output(markdown);
240
+ if matches!(
241
+ cmd,
242
+ "/release-notes"
243
+ | "/release_notes"
244
+ | "/release-note"
245
+ | "/release_note"
246
+ | "/releasenotes"
247
+ | "/releasenote"
248
+ ) {
249
+ ui.push_release_notes(&markdown);
250
+ } else {
251
+ ui.push_command_output(markdown);
252
+ }
209
253
  }
210
254
  Some(SlashResult::Handled)
211
255
  }
@@ -381,6 +425,7 @@ pub async fn handle_slash_command(
381
425
  | "/shells"
382
426
  | "/palette"
383
427
  | "/theme"
428
+ | "/onboard"
384
429
  | "/image"
385
430
  | "/paste"
386
431
  | "/avatar"
@@ -426,6 +471,34 @@ pub async fn handle_slash_command(
426
471
  mint_core::slash::INIT_AGENTS_MD_PROMPT.to_string(),
427
472
  )),
428
473
 
474
+ "/edit" | "/retry" => {
475
+ let scoped = mint_core::scoped_chat_id(
476
+ &session.chat_id,
477
+ Some(&session.current_dir.to_string_lossy()),
478
+ );
479
+ if let Ok(memory) = MemoryStore::open_default() {
480
+ if let Ok(rows) = memory.interactions_for_chat(&scoped) {
481
+ if let Some(last) = rows.last() {
482
+ let turn_id = last.id;
483
+ let prompt_to_run = if rest.is_empty() {
484
+ last.user_text.clone()
485
+ } else {
486
+ rest.to_string()
487
+ };
488
+ let _ = memory.truncate_interactions_from(&scoped, turn_id);
489
+ ui.push_notice(format!(
490
+ "Truncated turn #{} from history. Resending with prompt:\n{}",
491
+ rows.len(),
492
+ prompt_to_run
493
+ ));
494
+ return Some(SlashResult::ForwardToAgent(prompt_to_run));
495
+ }
496
+ }
497
+ }
498
+ ui.push_notice("No previous turn found to edit or retry.");
499
+ Some(SlashResult::Handled)
500
+ }
501
+
429
502
  "/fast" => {
430
503
  let choice = if rest.is_empty() {
431
504
  let options = vec![
@@ -487,6 +560,7 @@ pub async fn handle_slash_command(
487
560
  ui.push_notice(format!("Already in session '{target_id}'."));
488
561
  } else {
489
562
  session.chat_id = target_id.clone();
563
+ crate::companion_navigation::set_chat(&session.chat_id);
490
564
  mint_core::live_sync::update_live_sync_chat_id(&session.chat_id);
491
565
  ui.reload_transcript(&session.chat_id, &session.current_dir);
492
566
  if let Ok(memory) = MemoryStore::open_default() {
@@ -529,14 +603,15 @@ pub async fn handle_slash_command(
529
603
  };
530
604
  if rest.is_empty() {
531
605
  if checkpoints.is_empty() {
532
- println!("\n{DIM}No git checkpoints recorded for this CLI session yet.{RESET}");
533
- println!(
534
- "{DIM}Checkpoints are created automatically before mutating file actions (write_file, apply_patch).{RESET}\n"
606
+ ui.push_notice(
607
+ "No git checkpoints recorded for this CLI session yet.\nCheckpoints are created automatically before mutating file actions (write_file, apply_patch).",
535
608
  );
536
609
  } else {
537
- println!("\n{BLUE}โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€{RESET}");
538
- println!("{MINT} โ†บ Available Git Checkpoints (Time Machine){RESET}");
539
- println!("{BLUE}โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€{RESET}");
610
+ let mut lines = vec![
611
+ format!("{BLUE}โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€{RESET}"),
612
+ format!("{MINT} โ†บ Available Git Checkpoints (Time Machine){RESET}"),
613
+ format!("{BLUE}โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€{RESET}"),
614
+ ];
540
615
  for cp in checkpoints.iter().rev() {
541
616
  let hash_short = if cp.commit_hash.len() >= 7 {
542
617
  &cp.commit_hash[..7]
@@ -544,24 +619,21 @@ pub async fn handle_slash_command(
544
619
  &cp.commit_hash
545
620
  };
546
621
  let target = cp.target_path.as_deref().unwrap_or("-");
547
- println!(
622
+ lines.push(format!(
548
623
  " {MINT}Step {:<3}{RESET} {DIM}[{}]{RESET} {:<20} {DIM}({}){RESET}",
549
624
  cp.step, hash_short, cp.action, target
550
- );
625
+ ));
551
626
  }
552
- println!(
553
- "\n{DIM}Use {RESET}{MINT}/rewind <step>{RESET}{DIM} to restore workspace to before that step, or {RESET}{MINT}/rewind undo{RESET}{DIM} to recover from rescue snapshot.{RESET}\n"
554
- );
627
+ lines.push(format!(
628
+ "\n{DIM}Use {RESET}{MINT}/rewind <step>{RESET}{DIM} to restore workspace to before that step, or {RESET}{MINT}/rewind undo{RESET}{DIM} to recover from rescue snapshot.{RESET}"
629
+ ));
630
+ ui.push_command_output(lines.join("\n"));
555
631
  }
556
632
  Some(SlashResult::Handled)
557
633
  } else if rest.trim().eq_ignore_ascii_case("undo") {
558
634
  match mint_core::git::undo_rollback(&session.current_dir) {
559
- Ok(msg) => {
560
- println!("\n{MINT}{msg}{RESET}\n");
561
- }
562
- Err(err) => {
563
- println!("\n{ERROR}Failed to undo rewind:{RESET} {err}\n");
564
- }
635
+ Ok(msg) => ui.push_notice(msg),
636
+ Err(err) => ui.push_notice(format!("Failed to undo rewind: {err}")),
565
637
  }
566
638
  Some(SlashResult::Handled)
567
639
  } else {
@@ -572,18 +644,14 @@ pub async fn handle_slash_command(
572
644
  &target_rewind_chat_id,
573
645
  step,
574
646
  ) {
575
- Ok(msg) => {
576
- println!("\n{MINT}{msg}{RESET}\n");
577
- }
578
- Err(err) => {
579
- println!("\n{ERROR}Failed to rollback:{RESET} {err}\n");
580
- }
647
+ Ok(msg) => ui.push_notice(msg),
648
+ Err(err) => ui.push_notice(format!("Failed to rollback: {err}")),
581
649
  }
582
650
  }
583
651
  Err(_) => {
584
- println!(
585
- "\n{ERROR}Invalid step number:{RESET} \"{rest}\". Usage: /rewind <step> or /rewind undo\n"
586
- );
652
+ ui.push_notice(format!(
653
+ "Invalid step number: \"{rest}\". Usage: /rewind <step> or /rewind undo"
654
+ ));
587
655
  }
588
656
  }
589
657
  Some(SlashResult::Handled)
@@ -613,6 +681,19 @@ pub async fn handle_slash_command(
613
681
  Some(SlashResult::Handled)
614
682
  }
615
683
 
684
+ "/onboard" => {
685
+ match ui.prompt_onboard(&mut session.config) {
686
+ Ok(true) => {
687
+ ui.push_notice("โœ” Configuration updated successfully.");
688
+ }
689
+ Ok(false) => {
690
+ ui.push_notice("Onboarding cancelled.");
691
+ }
692
+ Err(error) => ui.report_error(&error),
693
+ }
694
+ Some(SlashResult::Handled)
695
+ }
696
+
616
697
  "/palette" => {
617
698
  let options = vec![
618
699
  ChoiceItem::with_description(
@@ -687,28 +768,75 @@ pub async fn handle_slash_command(
687
768
  }
688
769
 
689
770
  "/thought" | "/think" => {
690
- if let Some(record) = get_last_thought() {
691
- let _ = show_thought_viewer(&record.thought, &record.elapsed_str);
692
- } else {
693
- ui.push_notice("No recent thought process recorded for this turn.");
771
+ if let Err(err) = ui.open_thought_viewer() {
772
+ ui.push_notice(format!("Could not open thought viewer: {err}"));
694
773
  }
695
774
  Some(SlashResult::Handled)
696
775
  }
697
776
 
698
- "/plan" if rest == "list" => {
777
+ "/plan" if rest == "list" || rest.starts_with("list ") => {
778
+ let arg = rest.trim_start_matches("list").trim();
699
779
  let files = list_plan_files(&session.current_dir);
700
780
  if files.is_empty() {
701
- ui.push_notice("No saved plans yet.");
781
+ ui.push_notice("No saved plans yet under .agents/plans/");
782
+ } else if !arg.is_empty() {
783
+ let found = if let Ok(idx) = arg.parse::<usize>() {
784
+ idx.checked_sub(1).and_then(|i| files.get(i))
785
+ } else {
786
+ files.iter().find(|p| {
787
+ p.file_name()
788
+ .and_then(|n| n.to_str())
789
+ .is_some_and(|n| n.contains(arg))
790
+ })
791
+ };
792
+ match found {
793
+ Some(path) => match std::fs::read_to_string(path) {
794
+ Ok(content) => ui.push_plan(&content),
795
+ Err(e) => ui.push_notice(format!("Could not read plan file: {e}")),
796
+ },
797
+ None => ui.push_notice(format!(
798
+ "No saved plan matching \"{arg}\" โ€” run /plan list to see saved plans."
799
+ )),
800
+ }
702
801
  } else {
703
- let mut lines = vec![format!("{BLUE}Saved plans:{RESET}")];
704
- for (idx, path) in files.iter().enumerate() {
705
- lines.push(format!(
706
- " {DIM}[{}]{RESET} {BLUE}{}{RESET}",
707
- idx + 1,
708
- first_line_preview(path)
709
- ));
802
+ let options = files
803
+ .iter()
804
+ .enumerate()
805
+ .map(|(idx, path)| {
806
+ let preview = first_line_preview(path);
807
+ let display_title = if preview.is_empty() {
808
+ path.file_name()
809
+ .and_then(|n| n.to_str())
810
+ .unwrap_or("Untitled Plan")
811
+ } else {
812
+ &preview
813
+ };
814
+ let meta = format_plan_meta(path);
815
+ ChoiceItem::with_description(
816
+ format!("[{}] {}", idx + 1, display_title),
817
+ meta,
818
+ path.to_string_lossy().to_string(),
819
+ )
820
+ })
821
+ .collect::<Vec<_>>();
822
+
823
+ match ui.prompt_choice(
824
+ "Select Saved Plan",
825
+ "Choose a plan to view its content (Press Enter to view, Esc to cancel)",
826
+ &options,
827
+ ) {
828
+ Ok(Some(idx)) => {
829
+ if let Some(path) = files.get(idx) {
830
+ match std::fs::read_to_string(path) {
831
+ Ok(content) => {
832
+ ui.push_plan(&content);
833
+ }
834
+ Err(e) => ui.push_notice(format!("Could not read plan file: {e}")),
835
+ }
836
+ }
837
+ }
838
+ _ => {}
710
839
  }
711
- ui.push_command_output(lines.join("\n"));
712
840
  }
713
841
  Some(SlashResult::Handled)
714
842
  }
@@ -727,7 +855,7 @@ pub async fn handle_slash_command(
727
855
  };
728
856
  match found {
729
857
  Some(path) => match std::fs::read_to_string(path) {
730
- Ok(content) => ui.push_command_output(content),
858
+ Ok(content) => ui.push_plan(&content),
731
859
  Err(e) => ui.push_notice(format!("Could not read plan file: {e}")),
732
860
  },
733
861
  None => ui.push_notice(format!(
@@ -774,18 +902,18 @@ pub async fn handle_slash_command(
774
902
  "/models" => {
775
903
  let selected_provider = if rest.is_empty() {
776
904
  let providers = session.config.available_providers();
777
- match prompt_interactive_select(
778
- "Select AI provider",
779
- &providers,
780
- &session.config.ai_provider,
781
- ) {
782
- Ok(Some(p)) => Some(p),
905
+ let choices: Vec<ChoiceItem> = providers
906
+ .iter()
907
+ .map(|p| ChoiceItem::new(p.clone(), p.clone()))
908
+ .collect();
909
+ match ui.prompt_choice("Select AI provider", "", &choices) {
910
+ Ok(Some(idx)) => providers.get(idx).cloned(),
783
911
  Ok(None) => {
784
- println!("Cancelled provider selection.\n");
912
+ ui.push_notice("Cancelled provider selection.");
785
913
  None
786
914
  }
787
915
  Err(e) => {
788
- println!("{ERROR}Error selecting provider:{RESET} {e}\n");
916
+ ui.push_notice(format!("Error selecting provider: {e}"));
789
917
  None
790
918
  }
791
919
  }
@@ -794,25 +922,16 @@ pub async fn handle_slash_command(
794
922
  };
795
923
 
796
924
  if let Some(provider) = selected_provider {
797
- // Switch provider first so `active_model()` reflects that
798
- // provider's own default/last-used model, then offer a
799
- // second picker (when a model list is known for it) so the
800
- // user isn't stuck with the default after choosing a provider.
801
925
  match session.config.set_active_model(&provider, None) {
802
926
  Ok(mut display_name) => {
803
- // Try live fetch from the provider API; fall back to
804
- // static presets if the network is unavailable or the
805
- // user hasn't entered an API key yet.
806
- print!("{DIM}Fetching available models for {provider}...{RESET}\r");
807
- let _ = std::io::Write::flush(&mut std::io::stdout());
927
+ ui.set_status(vec![format!("Fetching available models for {provider}...")]);
808
928
  let mut model_options =
809
929
  mint_core::slash::models::model_options_for_provider_async(
810
930
  &session.config,
811
931
  &provider,
812
932
  )
813
933
  .await;
814
- print!("\r\x1b[2K");
815
- let _ = std::io::Write::flush(&mut std::io::stdout());
934
+ ui.clear_status();
816
935
  let current_model = session.config.active_model().to_string();
817
936
  if !current_model.is_empty()
818
937
  && !model_options.iter().any(|m| m == &current_model)
@@ -821,32 +940,40 @@ pub async fn handle_slash_command(
821
940
  }
822
941
 
823
942
  if !model_options.is_empty() {
824
- match prompt_interactive_select(
943
+ let choices: Vec<ChoiceItem> = model_options
944
+ .iter()
945
+ .map(|m| ChoiceItem::new(m.clone(), m.clone()))
946
+ .collect();
947
+ match ui.prompt_choice(
825
948
  &format!("Select {provider} model"),
826
- &model_options,
827
- &current_model,
949
+ "",
950
+ &choices,
828
951
  ) {
829
- Ok(Some(model)) if model != current_model => {
830
- match session.config.set_active_model(&provider, Some(&model)) {
831
- Ok(name) => display_name = name,
832
- Err(error) => {
833
- println!("{ERROR}Config error:{RESET} {error}")
952
+ Ok(Some(idx)) => {
953
+ if let Some(model) = model_options.get(idx)
954
+ && model != &current_model
955
+ {
956
+ match session
957
+ .config
958
+ .set_active_model(&provider, Some(model))
959
+ {
960
+ Ok(name) => display_name = name,
961
+ Err(error) => {
962
+ ui.push_notice(format!("Config error: {error}"));
963
+ }
834
964
  }
835
965
  }
836
966
  }
837
- Ok(_) => {}
967
+ Ok(None) => {}
838
968
  Err(e) => {
839
- println!("{ERROR}Error selecting model:{RESET} {e}\n")
969
+ ui.push_notice(format!("Error selecting model: {e}"));
840
970
  }
841
971
  }
842
972
  }
843
973
 
844
- println!(
845
- "\n{DIM}โ”€โ”€โ”€{RESET} {MINT}{}{RESET} {DIM}โ”€โ”€โ”€{RESET}\n",
846
- display_name
847
- );
974
+ ui.push_notice(format!("Active model: {display_name}"));
848
975
  }
849
- Err(error) => println!("{ERROR}Config error:{RESET} {error}"),
976
+ Err(error) => ui.push_notice(format!("Config error: {error}")),
850
977
  }
851
978
  }
852
979
  Some(SlashResult::Handled)
@@ -856,29 +983,31 @@ pub async fn handle_slash_command(
856
983
  if rest == "on" || rest == "off" {
857
984
  session.config.enable_agent_collaboration = rest == "on";
858
985
  match mint_core::save_config(&session.config) {
859
- Ok(()) => println!(
860
- "{DIM}Multi-Agent collaboration set to: {}{RESET}\n",
986
+ Ok(()) => ui.push_notice(format!(
987
+ "Multi-Agent collaboration set to: {}",
861
988
  if session.config.enable_agent_collaboration {
862
989
  "Enabled"
863
990
  } else {
864
991
  "Disabled"
865
992
  }
866
- ),
867
- Err(error) => println!("{ERROR}Config error:{RESET} {error}\n"),
993
+ )),
994
+ Err(error) => ui.push_notice(format!("Config error: {error}")),
868
995
  }
869
996
  } else if !rest.is_empty() {
870
- println!("{WARN}Usage: /multi-agent [on|off]{RESET}\n");
997
+ ui.push_notice("Usage: /multi-agent [on|off]");
871
998
  } else {
872
- println!("\n{BLUE}Multi-Agent System Settings:{RESET}");
873
999
  let collab_status = if session.config.enable_agent_collaboration {
874
1000
  format!("{MINT}Enabled (on){RESET}")
875
1001
  } else {
876
1002
  format!("{DIM}Disabled (off){RESET}")
877
1003
  };
878
- println!(" Global Collaboration: {collab_status}");
879
- println!("\n{BLUE}Configured Agents:{RESET}");
1004
+ let mut lines = vec![
1005
+ format!("{BLUE}Multi-Agent System Settings:{RESET}"),
1006
+ format!(" Global Collaboration: {collab_status}"),
1007
+ format!("\n{BLUE}Configured Agents:{RESET}"),
1008
+ ];
880
1009
  if session.config.agents.is_empty() {
881
- println!(" No agents configured.");
1010
+ lines.push(" No agents configured.".to_string());
882
1011
  } else {
883
1012
  for agent in &session.config.agents {
884
1013
  let status_label = if agent.enabled {
@@ -886,10 +1015,10 @@ pub async fn handle_slash_command(
886
1015
  } else {
887
1016
  format!("{DIM}[Disabled]{RESET}")
888
1017
  };
889
- println!(
1018
+ lines.push(format!(
890
1019
  " {:<15} {} Provider: {:<12} Model: {}",
891
1020
  agent.name, status_label, agent.provider, agent.model
892
- );
1021
+ ));
893
1022
  let truncated_instruction = if agent.system_instruction.chars().count() > 60
894
1023
  {
895
1024
  let head: String = agent.system_instruction.chars().take(60).collect();
@@ -897,38 +1026,34 @@ pub async fn handle_slash_command(
897
1026
  } else {
898
1027
  agent.system_instruction.replace('\n', " ")
899
1028
  };
900
- println!(" {DIM}Instruction: {truncated_instruction}{RESET}");
1029
+ lines.push(format!(
1030
+ " {DIM}Instruction: {truncated_instruction}{RESET}"
1031
+ ));
901
1032
  }
902
1033
  }
903
- println!();
1034
+ ui.push_command_output(lines.join("\n"));
904
1035
 
905
- let options = vec![
906
- "Keep current status".to_string(),
907
- "on (enable collaboration)".to_string(),
908
- "off (disable collaboration)".to_string(),
1036
+ let choices = vec![
1037
+ ChoiceItem::new("Keep current status", "keep"),
1038
+ ChoiceItem::new("on (enable collaboration)", "on"),
1039
+ ChoiceItem::new("off (disable collaboration)", "off"),
909
1040
  ];
910
- let current = &options[0];
911
- match prompt_interactive_select("Toggle Collaboration Status?", &options, current) {
912
- Ok(Some(sel)) => {
913
- if sel.starts_with("on") {
914
- session.config.enable_agent_collaboration = true;
915
- match mint_core::save_config(&session.config) {
916
- Ok(()) => println!(
917
- "{DIM}Multi-Agent collaboration set to: Enabled{RESET}\n"
918
- ),
919
- Err(error) => println!("{ERROR}Config error:{RESET} {error}\n"),
920
- }
921
- } else if sel.starts_with("off") {
922
- session.config.enable_agent_collaboration = false;
923
- match mint_core::save_config(&session.config) {
924
- Ok(()) => println!(
925
- "{DIM}Multi-Agent collaboration set to: Disabled{RESET}\n"
926
- ),
927
- Err(error) => println!("{ERROR}Config error:{RESET} {error}\n"),
928
- }
1041
+ if let Ok(Some(idx)) =
1042
+ ui.prompt_choice("Toggle Collaboration Status?", "", &choices)
1043
+ {
1044
+ if idx == 1 {
1045
+ session.config.enable_agent_collaboration = true;
1046
+ match mint_core::save_config(&session.config) {
1047
+ Ok(()) => ui.push_notice("Multi-Agent collaboration set to: Enabled"),
1048
+ Err(error) => ui.push_notice(format!("Config error: {error}")),
1049
+ }
1050
+ } else if idx == 2 {
1051
+ session.config.enable_agent_collaboration = false;
1052
+ match mint_core::save_config(&session.config) {
1053
+ Ok(()) => ui.push_notice("Multi-Agent collaboration set to: Disabled"),
1054
+ Err(error) => ui.push_notice(format!("Config error: {error}")),
929
1055
  }
930
1056
  }
931
- _ => {}
932
1057
  }
933
1058
  }
934
1059
  Some(SlashResult::Handled)
@@ -939,19 +1064,21 @@ pub async fn handle_slash_command(
939
1064
 
940
1065
  // Soft toggle: `avatar_signal_disabled` hides the tool while keeping
941
1066
  // the token so the paired viewer never needs re-linking.
942
- let set_signal_disabled = |session: &mut InteractiveSession, disabled: bool| {
1067
+ let set_signal_disabled = |session: &mut InteractiveSession,
1068
+ ui: &mut dyn CommandUi,
1069
+ disabled: bool| {
943
1070
  session.config.avatar_signal_disabled = disabled;
944
1071
  match mint_core::save_config(&session.config) {
945
1072
  Ok(()) => {
946
1073
  if disabled {
947
- println!(
948
- "{DIM}[Avatar] avatar_signal disabled (token kept โ€” run /avatar to re-enable).{RESET}\n"
949
- );
1074
+ ui.push_notice(
1075
+ "[Avatar] avatar_signal disabled (token kept โ€” run /avatar to re-enable).",
1076
+ );
950
1077
  } else {
951
- println!("{DIM}[Avatar] avatar_signal enabled.{RESET}\n");
1078
+ ui.push_notice("[Avatar] avatar_signal enabled.");
952
1079
  }
953
1080
  }
954
- Err(error) => println!("{ERROR}Config error:{RESET} {error}\n"),
1081
+ Err(error) => ui.push_notice(format!("Config error: {error}")),
955
1082
  }
956
1083
  };
957
1084
 
@@ -961,33 +1088,33 @@ pub async fn handle_slash_command(
961
1088
  "web" | "link web" => "web",
962
1089
  "desktop" | "link desktop" => "desktop",
963
1090
  "on" | "enable" => {
964
- set_signal_disabled(session, false);
1091
+ set_signal_disabled(session, ui, false);
965
1092
  return Some(SlashResult::Handled);
966
1093
  }
967
1094
  "off" | "disable" => {
968
- set_signal_disabled(session, true);
1095
+ set_signal_disabled(session, ui, true);
969
1096
  return Some(SlashResult::Handled);
970
1097
  }
971
1098
  "" | "link" => {
972
1099
  let options = vec![
973
- "No".to_string(),
974
- "Off (disable avatar_signal)".to_string(),
975
- "Web browser".to_string(),
976
- "Desktop app".to_string(),
1100
+ ChoiceItem::new("Web browser", "web"),
1101
+ ChoiceItem::new("Desktop app", "desktop"),
1102
+ ChoiceItem::new("Off (disable avatar_signal)", "off"),
1103
+ ChoiceItem::new("No", "no"),
977
1104
  ];
978
- match prompt_interactive_select("Avatar output", &options, &options[2]) {
979
- Ok(Some(sel)) if sel == "No" => return Some(SlashResult::Handled),
980
- Ok(Some(sel)) if sel.starts_with("Off") => {
981
- set_signal_disabled(session, true);
982
- return Some(SlashResult::Handled);
983
- }
984
- Ok(Some(sel)) if sel.starts_with("Desktop") => "desktop",
985
- Ok(Some(_)) => "web",
986
- // Cancelled / no TTY โ€” the picker has an explicit "No",
987
- // so treat a cancel as "do nothing".
1105
+ match ui.prompt_choice("Avatar output", "", &options) {
1106
+ Ok(Some(idx)) => match options[idx].value.as_str() {
1107
+ "no" => return Some(SlashResult::Handled),
1108
+ "off" => {
1109
+ set_signal_disabled(session, ui, true);
1110
+ return Some(SlashResult::Handled);
1111
+ }
1112
+ "desktop" => "desktop",
1113
+ _ => "web",
1114
+ },
988
1115
  Ok(None) => return Some(SlashResult::Handled),
989
1116
  Err(e) => {
990
- println!("{ERROR}Error selecting target:{RESET} {e}\n");
1117
+ ui.push_notice(format!("Error selecting target: {e}"));
991
1118
  return Some(SlashResult::Handled);
992
1119
  }
993
1120
  }
@@ -995,44 +1122,41 @@ pub async fn handle_slash_command(
995
1122
  "status" => {
996
1123
  let cfg = AvatarBridgeConfig::from_mint_config(&session.config);
997
1124
  if !cfg.enabled {
998
- println!("{WARN}[Avatar] No token yet โ€” run /avatar link first.{RESET}\n");
1125
+ ui.push_notice("[Avatar] No token yet โ€” run /avatar link first.");
999
1126
  } else {
1000
- println!(
1001
- "{DIM}[Avatar] avatar_signal tool: {}{RESET}",
1002
- if session.config.avatar_signal_disabled {
1003
- "disabled"
1004
- } else {
1005
- "enabled"
1006
- }
1007
- );
1127
+ let tool_state = if session.config.avatar_signal_disabled {
1128
+ "disabled"
1129
+ } else {
1130
+ "enabled"
1131
+ };
1008
1132
  match fetch_channel_state(&cfg).await {
1009
1133
  Ok(state) => {
1010
1134
  let now_ms = std::time::SystemTime::now()
1011
1135
  .duration_since(std::time::UNIX_EPOCH)
1012
1136
  .map(|d| d.as_millis() as i64)
1013
1137
  .unwrap_or(0);
1014
- println!("\n{BLUE}[Avatar] Channel status:{RESET}");
1015
- println!(
1016
- " Model: {}",
1017
- state.model.unwrap_or_else(|| "not selected".into())
1018
- );
1019
- println!(" Viewers: {}", state.connected_clients);
1020
- println!(
1021
- " Last event: {}\n",
1022
- state
1023
- .last_agent_event_at
1024
- .map(|t| format!("{}s ago", (now_ms - t).max(0) / 1000))
1025
- .unwrap_or_else(|| "never".into())
1026
- );
1138
+ let last_ev = state
1139
+ .last_agent_event_at
1140
+ .map(|t| format!("{}s ago", (now_ms - t).max(0) / 1000))
1141
+ .unwrap_or_else(|| "never".into());
1142
+ ui.push_command_output(format!(
1143
+ "{DIM}[Avatar] avatar_signal tool: {tool_state}{RESET}\n\
1144
+ {BLUE}[Avatar] Channel status:{RESET}\n \
1145
+ Model: {}\n \
1146
+ Viewers: {}\n \
1147
+ Last event: {last_ev}",
1148
+ state.model.unwrap_or_else(|| "not selected".into()),
1149
+ state.connected_clients
1150
+ ));
1027
1151
  }
1028
- Err(error) => println!("{ERROR}[Avatar] {error}{RESET}\n"),
1152
+ Err(error) => ui.push_notice(format!("[Avatar] {error}")),
1029
1153
  }
1030
1154
  }
1031
1155
  return Some(SlashResult::Handled);
1032
1156
  }
1033
1157
  _ => {
1034
- println!(
1035
- "{WARN}Usage: /avatar [web|desktop|on|off|status] โ€” connects agent activity to Project Avatar{RESET}\n"
1158
+ ui.push_notice(
1159
+ "Usage: /avatar [web|desktop|on|off|status] โ€” connects agent activity to Project Avatar",
1036
1160
  );
1037
1161
  return Some(SlashResult::Handled);
1038
1162
  }
@@ -1045,175 +1169,185 @@ pub async fn handle_slash_command(
1045
1169
  session.config.avatar_token = AvatarBridgeConfig::generate_token();
1046
1170
  }
1047
1171
  if let Err(error) = mint_core::save_config(&session.config) {
1048
- println!("{ERROR}Config error:{RESET} {error}\n");
1172
+ ui.push_notice(format!("Config error: {error}"));
1049
1173
  return Some(SlashResult::Handled);
1050
1174
  }
1051
1175
  let cfg = AvatarBridgeConfig::from_mint_config(&session.config);
1052
1176
  let token = session.config.avatar_token.clone();
1053
1177
  if target == "desktop" {
1054
- println!(
1055
- "\n{MINT}[Avatar] Desktop app:{RESET}\n\
1178
+ ui.push_command_output(format!(
1179
+ "{MINT}[Avatar] Desktop app:{RESET}\n\
1056
1180
  1. Open the Project Avatar desktop app.\n\
1057
1181
  2. It has no address bar, so on first launch it generates its \
1058
1182
  own token โ€” paste this one into its \"Paste existing token...\" \
1059
1183
  field instead so it connects to the same channel Mint pushes to:\n\
1060
1184
  {DIM}{token}{RESET}\n\
1061
- It remembers the token after that; you won't need to paste it again.\n"
1062
- );
1185
+ It remembers the token after that; you won't need to paste it again."
1186
+ ));
1063
1187
  } else {
1064
- println!(
1065
- "\n{MINT}[Avatar] Share link:{RESET}\n{}\n",
1188
+ ui.push_command_output(format!(
1189
+ "{MINT}[Avatar] Share link:{RESET}\n{}",
1066
1190
  cfg.share_link().expect("token was just ensured non-empty")
1067
- );
1191
+ ));
1068
1192
  }
1069
1193
  Some(SlashResult::Handled)
1070
1194
  }
1071
1195
 
1072
1196
  "/autoskill" => {
1073
- if rest == "on" || rest == "off" {
1074
- session.config.auto_skill_writing = rest == "on";
1197
+ let apply = |session: &mut InteractiveSession, ui: &mut dyn CommandUi, on: bool| {
1198
+ session.config.auto_skill_writing = on;
1075
1199
  match mint_core::save_config(&session.config) {
1076
- Ok(()) => println!(
1077
- "{DIM}Skill suggestions (approval required to save) set to: {}{RESET}\n",
1078
- if session.config.auto_skill_writing {
1079
- "Enabled"
1080
- } else {
1081
- "Disabled"
1082
- }
1083
- ),
1084
- Err(error) => println!("{ERROR}Config error:{RESET} {error}\n"),
1200
+ Ok(()) => ui.push_notice(format!(
1201
+ "Skill suggestions (approval required to save) set to: {}",
1202
+ if on { "Enabled" } else { "Disabled" }
1203
+ )),
1204
+ Err(error) => ui.push_notice(format!("Config error: {error}")),
1085
1205
  }
1206
+ };
1207
+ if rest == "on" || rest == "off" {
1208
+ apply(session, ui, rest == "on");
1086
1209
  } else if !rest.is_empty() {
1087
- println!("{WARN}Usage: /autoskill [on|off]{RESET}\n");
1210
+ ui.push_notice("Usage: /autoskill [on|off]");
1088
1211
  } else {
1089
- println!(
1090
- "{DIM}When enabled, the agent proposes a skill after a reusable task. Each proposed diff needs your approval before saving.{RESET}"
1091
- );
1092
- let options = vec!["on (enable)".to_string(), "off (disable)".to_string()];
1093
- let current = if session.config.auto_skill_writing {
1094
- &options[0]
1212
+ let options = if session.config.auto_skill_writing {
1213
+ vec![
1214
+ ChoiceItem::new("on (current)", "on"),
1215
+ ChoiceItem::new("off", "off"),
1216
+ ]
1095
1217
  } else {
1096
- &options[1]
1218
+ vec![
1219
+ ChoiceItem::new("off (current)", "off"),
1220
+ ChoiceItem::new("on", "on"),
1221
+ ]
1097
1222
  };
1098
- match prompt_interactive_select("Skill Suggestions", &options, current) {
1099
- Ok(Some(sel)) => {
1100
- session.config.auto_skill_writing = sel.starts_with("on");
1101
- match mint_core::save_config(&session.config) {
1102
- Ok(()) => println!(
1103
- "{DIM}Skill suggestions (approval required to save) set to: {}{RESET}\n",
1104
- if session.config.auto_skill_writing {
1105
- "Enabled"
1106
- } else {
1107
- "Disabled"
1108
- }
1109
- ),
1110
- Err(error) => println!("{ERROR}Config error:{RESET} {error}\n"),
1111
- }
1112
- }
1113
- Ok(None) => println!("{DIM}Cancelled.{RESET}\n"),
1114
- Err(e) => println!("{ERROR}Error selecting option:{RESET} {e}\n"),
1223
+ match ui.prompt_choice(
1224
+ "Skill Suggestions",
1225
+ "When enabled, the agent proposes a skill after a reusable task. Each proposed diff needs your approval before saving.",
1226
+ &options,
1227
+ ) {
1228
+ Ok(Some(idx)) => apply(session, ui, options[idx].value == "on"),
1229
+ Ok(None) => ui.push_notice("Cancelled."),
1230
+ Err(e) => ui.push_notice(format!("Error selecting option: {e}")),
1115
1231
  }
1116
1232
  }
1117
1233
  Some(SlashResult::Handled)
1118
1234
  }
1119
1235
 
1120
1236
  "/autorecall" => {
1121
- let apply = |session: &mut InteractiveSession, on: bool| {
1237
+ let apply = |session: &mut InteractiveSession, ui: &mut dyn CommandUi, on: bool| {
1122
1238
  session.config.memory_recall = on;
1123
1239
  match mint_core::save_config(&session.config) {
1124
- Ok(()) => println!(
1125
- "{DIM}Memory recall set to: {}{RESET}\n",
1240
+ Ok(()) => ui.push_notice(format!(
1241
+ "Memory recall set to: {}",
1126
1242
  if on { "Enabled" } else { "Disabled" }
1127
- ),
1128
- Err(error) => println!("{ERROR}Config error:{RESET} {error}\n"),
1243
+ )),
1244
+ Err(error) => ui.push_notice(format!("Config error: {error}")),
1129
1245
  }
1130
1246
  };
1131
1247
  if rest == "on" || rest == "off" {
1132
- apply(session, rest == "on");
1248
+ apply(session, ui, rest == "on");
1133
1249
  } else if !rest.is_empty() {
1134
- println!("{WARN}Usage: /autorecall [on|off]{RESET}\n");
1250
+ ui.push_notice("Usage: /autorecall [on|off]");
1135
1251
  } else {
1136
- println!(
1137
- "{DIM}When enabled, each turn full-text-searches this conversation's older messages and injects the few most relevant to what you just said.{RESET}"
1138
- );
1139
- let options = vec!["on (enable)".to_string(), "off (disable)".to_string()];
1140
- let current = if session.config.memory_recall {
1141
- &options[0]
1252
+ let options = if session.config.memory_recall {
1253
+ vec![
1254
+ ChoiceItem::new("on (enable)", "on"),
1255
+ ChoiceItem::new("off (disable)", "off"),
1256
+ ]
1142
1257
  } else {
1143
- &options[1]
1258
+ vec![
1259
+ ChoiceItem::new("off (disable)", "off"),
1260
+ ChoiceItem::new("on (enable)", "on"),
1261
+ ]
1144
1262
  };
1145
- match prompt_interactive_select("Memory Recall", &options, current) {
1146
- Ok(Some(sel)) => apply(session, sel.starts_with("on")),
1147
- Ok(None) => println!("{DIM}Cancelled.{RESET}\n"),
1148
- Err(e) => println!("{ERROR}Error selecting option:{RESET} {e}\n"),
1263
+ match ui.prompt_choice(
1264
+ "Memory Recall",
1265
+ "When enabled, each turn full-text-searches this conversation's older messages and injects the few most relevant to what you just said.",
1266
+ &options,
1267
+ ) {
1268
+ Ok(Some(idx)) => apply(session, ui, options[idx].value == "on"),
1269
+ Ok(None) => ui.push_notice("Cancelled."),
1270
+ Err(e) => ui.push_notice(format!("Error selecting option: {e}")),
1149
1271
  }
1150
1272
  }
1151
1273
  Some(SlashResult::Handled)
1152
1274
  }
1153
1275
 
1154
1276
  "/autofacts" => {
1155
- let apply = |session: &mut InteractiveSession, on: bool| {
1277
+ let apply = |session: &mut InteractiveSession, ui: &mut dyn CommandUi, on: bool| {
1156
1278
  session.config.auto_fact_extraction = on;
1157
1279
  match mint_core::save_config(&session.config) {
1158
- Ok(()) => println!(
1159
- "{DIM}Auto fact extraction set to: {}{RESET}\n",
1280
+ Ok(()) => ui.push_notice(format!(
1281
+ "Auto fact extraction set to: {}",
1160
1282
  if on { "Enabled" } else { "Disabled" }
1161
- ),
1162
- Err(error) => println!("{ERROR}Config error:{RESET} {error}\n"),
1283
+ )),
1284
+ Err(error) => ui.push_notice(format!("Config error: {error}")),
1163
1285
  }
1164
1286
  };
1165
1287
  if rest == "on" || rest == "off" {
1166
- apply(session, rest == "on");
1288
+ apply(session, ui, rest == "on");
1167
1289
  } else if !rest.is_empty() {
1168
- println!("{WARN}Usage: /autofacts [on|off]{RESET}\n");
1290
+ ui.push_notice("Usage: /autofacts [on|off]");
1169
1291
  } else {
1170
- println!(
1171
- "{DIM}When enabled, a turn that states a durable preference, naming, or standing instruction triggers a background pass that saves it to long-term memory.{RESET}"
1172
- );
1173
- let options = vec!["on (enable)".to_string(), "off (disable)".to_string()];
1174
- let current = if session.config.auto_fact_extraction {
1175
- &options[0]
1292
+ let options = if session.config.auto_fact_extraction {
1293
+ vec![
1294
+ ChoiceItem::new("on (enable)", "on"),
1295
+ ChoiceItem::new("off (disable)", "off"),
1296
+ ]
1176
1297
  } else {
1177
- &options[1]
1298
+ vec![
1299
+ ChoiceItem::new("off (disable)", "off"),
1300
+ ChoiceItem::new("on (enable)", "on"),
1301
+ ]
1178
1302
  };
1179
- match prompt_interactive_select("Auto Fact Extraction", &options, current) {
1180
- Ok(Some(sel)) => apply(session, sel.starts_with("on")),
1181
- Ok(None) => println!("{DIM}Cancelled.{RESET}\n"),
1182
- Err(e) => println!("{ERROR}Error selecting option:{RESET} {e}\n"),
1303
+ match ui.prompt_choice(
1304
+ "Auto Fact Extraction",
1305
+ "When enabled, a turn that states a durable preference, naming, or standing instruction triggers a background pass that saves it to long-term memory.",
1306
+ &options,
1307
+ ) {
1308
+ Ok(Some(idx)) => apply(session, ui, options[idx].value == "on"),
1309
+ Ok(None) => ui.push_notice("Cancelled."),
1310
+ Err(e) => ui.push_notice(format!("Error selecting option: {e}")),
1183
1311
  }
1184
1312
  }
1185
1313
  Some(SlashResult::Handled)
1186
1314
  }
1187
1315
 
1188
1316
  "/factrecall" => {
1189
- let apply = |session: &mut InteractiveSession, on: bool| {
1317
+ let apply = |session: &mut InteractiveSession, ui: &mut dyn CommandUi, on: bool| {
1190
1318
  session.config.semantic_fact_recall = on;
1191
1319
  match mint_core::save_config(&session.config) {
1192
- Ok(()) => println!(
1193
- "{DIM}Semantic fact recall set to: {}{RESET}\n",
1320
+ Ok(()) => ui.push_notice(format!(
1321
+ "Semantic fact recall set to: {}",
1194
1322
  if on { "Enabled" } else { "Disabled" }
1195
- ),
1196
- Err(error) => println!("{ERROR}Config error:{RESET} {error}\n"),
1323
+ )),
1324
+ Err(error) => ui.push_notice(format!("Config error: {error}")),
1197
1325
  }
1198
1326
  };
1199
1327
  if rest == "on" || rest == "off" {
1200
- apply(session, rest == "on");
1328
+ apply(session, ui, rest == "on");
1201
1329
  } else if !rest.is_empty() {
1202
- println!("{WARN}Usage: /factrecall [on|off]{RESET}\n");
1330
+ ui.push_notice("Usage: /factrecall [on|off]");
1203
1331
  } else {
1204
- println!(
1205
- "{DIM}When your stored facts overflow their per-turn budget, this fills the overflow with the facts most relevant to your message instead of just the newest ones (the newest few are always kept).{RESET}"
1206
- );
1207
- let options = vec!["on (enable)".to_string(), "off (disable)".to_string()];
1208
- let current = if session.config.semantic_fact_recall {
1209
- &options[0]
1332
+ let options = if session.config.semantic_fact_recall {
1333
+ vec![
1334
+ ChoiceItem::new("on (enable)", "on"),
1335
+ ChoiceItem::new("off (disable)", "off"),
1336
+ ]
1210
1337
  } else {
1211
- &options[1]
1338
+ vec![
1339
+ ChoiceItem::new("off (disable)", "off"),
1340
+ ChoiceItem::new("on (enable)", "on"),
1341
+ ]
1212
1342
  };
1213
- match prompt_interactive_select("Semantic Fact Recall", &options, current) {
1214
- Ok(Some(sel)) => apply(session, sel.starts_with("on")),
1215
- Ok(None) => println!("{DIM}Cancelled.{RESET}\n"),
1216
- Err(e) => println!("{ERROR}Error selecting option:{RESET} {e}\n"),
1343
+ match ui.prompt_choice(
1344
+ "Semantic Fact Recall",
1345
+ "When your stored facts overflow their per-turn budget, this fills the overflow with the facts most relevant to your message instead of just the newest ones (the newest few are always kept).",
1346
+ &options,
1347
+ ) {
1348
+ Ok(Some(idx)) => apply(session, ui, options[idx].value == "on"),
1349
+ Ok(None) => ui.push_notice("Cancelled."),
1350
+ Err(e) => ui.push_notice(format!("Error selecting option: {e}")),
1217
1351
  }
1218
1352
  }
1219
1353
  Some(SlashResult::Handled)
@@ -1234,25 +1368,25 @@ pub async fn handle_slash_command(
1234
1368
  ("user", None, rest)
1235
1369
  };
1236
1370
  if body.is_empty() {
1237
- println!("{WARN}Usage: /remember [here] <text>{RESET}\n");
1371
+ ui.push_notice("Usage: /remember [here] <text>");
1238
1372
  return Some(SlashResult::Handled);
1239
1373
  }
1240
1374
  match MemoryStore::open_default() {
1241
1375
  Ok(memory) => {
1242
1376
  match memory.add_fact(scope, project_path.as_deref(), body, None, None) {
1243
- Ok(Some(_)) => println!(
1244
- "{DIM}Remembered{}.{RESET}\n",
1377
+ Ok(Some(_)) => ui.push_notice(format!(
1378
+ "Remembered{}.",
1245
1379
  if scope == "project" {
1246
1380
  " (this project)"
1247
1381
  } else {
1248
1382
  ""
1249
1383
  }
1250
- ),
1251
- Ok(None) => println!("{DIM}Already remembered.{RESET}\n"),
1252
- Err(e) => println!("{ERROR}Error:{RESET} {e}\n"),
1384
+ )),
1385
+ Ok(None) => ui.push_notice("Already remembered."),
1386
+ Err(e) => ui.push_notice(format!("Error: {e}")),
1253
1387
  }
1254
1388
  }
1255
- Err(e) => println!("{ERROR}Memory error:{RESET} {e}\n"),
1389
+ Err(e) => ui.push_notice(format!("Memory error: {e}")),
1256
1390
  }
1257
1391
  Some(SlashResult::Handled)
1258
1392
  }
@@ -1282,42 +1416,45 @@ pub async fn handle_slash_command(
1282
1416
  }
1283
1417
 
1284
1418
  let selected_provider = if rest.is_empty() {
1285
- let options: Vec<String> = available.iter().map(|s| s.to_string()).collect();
1286
- match prompt_interactive_select(
1287
- "Select Image Generation provider",
1288
- &options,
1289
- &session.config.image_gen_provider,
1290
- ) {
1291
- Ok(Some(p)) => Some(p),
1419
+ let mut options: Vec<ChoiceItem> =
1420
+ available.iter().map(|s| ChoiceItem::new(*s, *s)).collect();
1421
+ if let Some(pos) = options
1422
+ .iter()
1423
+ .position(|o| o.value == session.config.image_gen_provider)
1424
+ && pos > 0
1425
+ {
1426
+ let item = options.remove(pos);
1427
+ options.insert(0, item);
1428
+ }
1429
+ match ui.prompt_choice("Select Image Generation provider", "", &options) {
1430
+ Ok(Some(idx)) => Some(options[idx].value.clone()),
1292
1431
  Ok(None) => {
1293
- println!("Cancelled image provider selection.\n");
1432
+ ui.push_notice("Cancelled image provider selection.");
1294
1433
  None
1295
1434
  }
1296
1435
  Err(e) => {
1297
- println!("{ERROR}Error selecting provider:{RESET} {e}\n");
1436
+ ui.push_notice(format!("Error selecting provider: {e}"));
1298
1437
  None
1299
1438
  }
1300
1439
  }
1440
+ } else if available.contains(&rest) {
1441
+ Some(rest.to_owned())
1301
1442
  } else {
1302
- if available.contains(&rest) {
1303
- Some(rest.to_owned())
1304
- } else {
1305
- println!("{ERROR}Provider '{rest}' is not configured or invalid.{RESET}\n");
1306
- None
1307
- }
1443
+ ui.push_notice(format!("Provider '{rest}' is not configured or invalid."));
1444
+ None
1308
1445
  };
1309
1446
 
1310
1447
  if let Some(provider) = selected_provider {
1311
- print!("{DIM}Fetching available image models for {provider}...{RESET}\r");
1312
- let _ = std::io::Write::flush(&mut std::io::stdout());
1448
+ ui.set_status(vec![format!(
1449
+ "Fetching available image models for {provider}..."
1450
+ )]);
1313
1451
  let mut model_options =
1314
1452
  mint_core::media::image_models::image_model_options_for_provider_async(
1315
1453
  &session.config,
1316
1454
  &provider,
1317
1455
  )
1318
1456
  .await;
1319
- print!("\r\x1b[2K");
1320
- let _ = std::io::Write::flush(&mut std::io::stdout());
1457
+ ui.clear_status();
1321
1458
 
1322
1459
  let current_model =
1323
1460
  mint_core::media::image_models::active_image_model_for_provider(
@@ -1330,19 +1467,29 @@ pub async fn handle_slash_command(
1330
1467
  }
1331
1468
 
1332
1469
  if !model_options.is_empty() {
1333
- match prompt_interactive_select(
1470
+ let mut choices: Vec<ChoiceItem> = model_options
1471
+ .iter()
1472
+ .map(|m| ChoiceItem::new(m.clone(), m.clone()))
1473
+ .collect();
1474
+ if let Some(pos) = choices.iter().position(|c| c.value == current_model)
1475
+ && pos > 0
1476
+ {
1477
+ let item = choices.remove(pos);
1478
+ choices.insert(0, item);
1479
+ }
1480
+ match ui.prompt_choice(
1334
1481
  &format!(
1335
1482
  "Select {} model",
1336
1483
  mint_core::media::image_models::image_provider_display_name(&provider)
1337
1484
  ),
1338
- &model_options,
1339
- &current_model,
1485
+ "",
1486
+ &choices,
1340
1487
  ) {
1341
- Ok(Some(model)) => {
1488
+ Ok(Some(idx)) => {
1342
1489
  mint_core::media::image_models::set_active_image_provider_model(
1343
1490
  &mut session.config,
1344
1491
  &provider,
1345
- Some(&model),
1492
+ Some(&choices[idx].value),
1346
1493
  );
1347
1494
  }
1348
1495
  Ok(None) => {
@@ -1353,7 +1500,7 @@ pub async fn handle_slash_command(
1353
1500
  );
1354
1501
  }
1355
1502
  Err(e) => {
1356
- println!("{ERROR}Error selecting image model:{RESET} {e}\n");
1503
+ ui.push_notice(format!("Error selecting image model: {e}"));
1357
1504
  }
1358
1505
  }
1359
1506
  } else {
@@ -1371,13 +1518,13 @@ pub async fn handle_slash_command(
1371
1518
  &session.config,
1372
1519
  &provider,
1373
1520
  );
1374
- println!(
1375
- "{DIM}Switched default image provider to: {} โ€ข {}{RESET}\n",
1521
+ ui.push_notice(format!(
1522
+ "Switched default image provider to: {} โ€ข {}",
1376
1523
  mint_core::media::image_models::image_provider_display_name(&provider),
1377
1524
  active
1378
- );
1525
+ ));
1379
1526
  }
1380
- Err(error) => println!("{ERROR}Config error:{RESET} {error}"),
1527
+ Err(error) => ui.push_notice(format!("Config error: {error}")),
1381
1528
  }
1382
1529
  }
1383
1530
  Some(SlashResult::Handled)
@@ -1393,49 +1540,24 @@ pub async fn handle_slash_command(
1393
1540
  available.push("veo");
1394
1541
  }
1395
1542
 
1396
- let current_provider = session
1397
- .config
1398
- .extra
1399
- .get("videoGenProvider")
1400
- .and_then(|v| v.as_str())
1401
- .unwrap_or("veo")
1402
- .to_string();
1403
-
1404
1543
  let selected_provider = if rest.is_empty() {
1405
- let options = vec!["Google Veo (Gemini Videos)".to_string()];
1406
- let current_display = if current_provider == "veo" {
1407
- "Google Veo (Gemini Videos)"
1408
- } else {
1409
- &current_provider
1410
- };
1411
- match prompt_interactive_select(
1412
- "Select Video Generation provider",
1413
- &options,
1414
- current_display,
1415
- ) {
1416
- Ok(Some(p)) => {
1417
- if p == "Google Veo (Gemini Videos)" {
1418
- Some("veo".to_string())
1419
- } else {
1420
- Some(p)
1421
- }
1422
- }
1544
+ let options = vec![ChoiceItem::new("Google Veo (Gemini Videos)", "veo")];
1545
+ match ui.prompt_choice("Select Video Generation provider", "", &options) {
1546
+ Ok(Some(idx)) => Some(options[idx].value.clone()),
1423
1547
  Ok(None) => {
1424
- println!("Cancelled video provider selection.\n");
1548
+ ui.push_notice("Cancelled video provider selection.");
1425
1549
  None
1426
1550
  }
1427
1551
  Err(e) => {
1428
- println!("{ERROR}Error selecting provider:{RESET} {e}\n");
1552
+ ui.push_notice(format!("Error selecting provider: {e}"));
1429
1553
  None
1430
1554
  }
1431
1555
  }
1556
+ } else if rest == "veo" || rest == "Google Veo (Gemini Videos)" {
1557
+ Some("veo".to_string())
1432
1558
  } else {
1433
- if rest == "veo" || rest == "Google Veo (Gemini Videos)" {
1434
- Some("veo".to_string())
1435
- } else {
1436
- println!("{ERROR}Provider '{rest}' is not configured or invalid.{RESET}\n");
1437
- None
1438
- }
1559
+ ui.push_notice(format!("Provider '{rest}' is not configured or invalid."));
1560
+ None
1439
1561
  };
1440
1562
 
1441
1563
  if let Some(provider) = selected_provider {
@@ -1450,12 +1572,11 @@ pub async fn handle_slash_command(
1450
1572
  } else {
1451
1573
  &provider
1452
1574
  };
1453
- println!(
1454
- "{DIM}Switched default video provider to: {}{RESET}\n",
1455
- display_name
1456
- );
1575
+ ui.push_notice(format!(
1576
+ "Switched default video provider to: {display_name}"
1577
+ ));
1457
1578
  }
1458
- Err(error) => println!("{ERROR}Config error:{RESET} {error}"),
1579
+ Err(error) => ui.push_notice(format!("Config error: {error}")),
1459
1580
  }
1460
1581
  }
1461
1582
  Some(SlashResult::Handled)
@@ -1498,8 +1619,8 @@ pub async fn handle_slash_command(
1498
1619
  }
1499
1620
 
1500
1621
  if available.is_empty() {
1501
- println!(
1502
- "{ERROR}No search provider is configured yet.{RESET} Run onboarding or set a Google/Brave key or SearXNG URL in Settings first.\n"
1622
+ ui.push_notice(
1623
+ "No search provider is configured yet. Run onboarding or set a Google/Brave key or SearXNG URL in Settings first.",
1503
1624
  );
1504
1625
  return Some(SlashResult::Handled);
1505
1626
  }
@@ -1513,30 +1634,24 @@ pub async fn handle_slash_command(
1513
1634
  .to_string();
1514
1635
 
1515
1636
  let selected_provider = if rest.is_empty() {
1516
- let options: Vec<String> = available
1637
+ let mut options: Vec<ChoiceItem> = available
1517
1638
  .iter()
1518
- .map(|(_, label)| label.to_string())
1639
+ .map(|(key, label)| ChoiceItem::new(*label, *key))
1519
1640
  .collect();
1520
- let current_display = available
1521
- .iter()
1522
- .find(|(key, _)| *key == current_provider)
1523
- .map(|(_, label)| *label)
1524
- .unwrap_or(available[0].1);
1525
- match prompt_interactive_select(
1526
- "Select Web Search provider",
1527
- &options,
1528
- current_display,
1529
- ) {
1530
- Ok(Some(label)) => available
1531
- .iter()
1532
- .find(|(_, l)| *l == label)
1533
- .map(|(key, _)| key.to_string()),
1641
+ if let Some(pos) = options.iter().position(|o| o.value == current_provider)
1642
+ && pos > 0
1643
+ {
1644
+ let item = options.remove(pos);
1645
+ options.insert(0, item);
1646
+ }
1647
+ match ui.prompt_choice("Select Web Search provider", "", &options) {
1648
+ Ok(Some(idx)) => Some(options[idx].value.clone()),
1534
1649
  Ok(None) => {
1535
- println!("Cancelled search provider selection.\n");
1650
+ ui.push_notice("Cancelled search provider selection.");
1536
1651
  None
1537
1652
  }
1538
1653
  Err(e) => {
1539
- println!("{ERROR}Error selecting provider:{RESET} {e}\n");
1654
+ ui.push_notice(format!("Error selecting provider: {e}"));
1540
1655
  None
1541
1656
  }
1542
1657
  }
@@ -1546,7 +1661,7 @@ pub async fn handle_slash_command(
1546
1661
  {
1547
1662
  Some(key.to_string())
1548
1663
  } else {
1549
- println!("{ERROR}Provider '{rest}' is not configured or invalid.{RESET}\n");
1664
+ ui.push_notice(format!("Provider '{rest}' is not configured or invalid."));
1550
1665
  None
1551
1666
  };
1552
1667
 
@@ -1562,12 +1677,11 @@ pub async fn handle_slash_command(
1562
1677
  .find(|(key, _)| *key == provider)
1563
1678
  .map(|(_, label)| *label)
1564
1679
  .unwrap_or(&provider);
1565
- println!(
1566
- "{DIM}Switched default web search provider to: {}{RESET}\n",
1567
- display_name
1568
- );
1680
+ ui.push_notice(format!(
1681
+ "Switched default web search provider to: {display_name}"
1682
+ ));
1569
1683
  }
1570
- Err(error) => println!("{ERROR}Config error:{RESET} {error}"),
1684
+ Err(error) => ui.push_notice(format!("Config error: {error}")),
1571
1685
  }
1572
1686
  }
1573
1687
  Some(SlashResult::Handled)
@@ -1710,6 +1824,17 @@ pub async fn handle_slash_command(
1710
1824
  .unwrap_or((rest, ""));
1711
1825
 
1712
1826
  match sub {
1827
+ "stop" if arg.is_empty() => {
1828
+ match mint_core::bg_shell::shells_command(
1829
+ "stop",
1830
+ &session.current_dir,
1831
+ &None,
1832
+ &session.config,
1833
+ ) {
1834
+ Ok(message) => ui.push_notice(message),
1835
+ Err(error) => ui.push_notice(error.to_string()),
1836
+ }
1837
+ }
1713
1838
  "show" if !arg.is_empty() => match mint_core::bg_shell::snapshot(arg) {
1714
1839
  Ok(job) => {
1715
1840
  let mut lines =
@@ -1737,7 +1862,7 @@ pub async fn handle_slash_command(
1737
1862
  Ok(msg) => ui.push_notice(msg),
1738
1863
  Err(_) => ui.push_notice("No such job."),
1739
1864
  },
1740
- _ => ui.push_notice("Usage: /shells [all|show <id>|stop <id>|kill <id>]"),
1865
+ _ => ui.push_notice("Usage: /shells [all|show <id>|stop [<id>]|kill <id>]"),
1741
1866
  }
1742
1867
  Some(SlashResult::Handled)
1743
1868
  }
@@ -1988,9 +2113,15 @@ pub async fn handle_slash_command(
1988
2113
  }
1989
2114
  };
1990
2115
  if unique_skills.is_empty() {
1991
- println!("No learned skills found. Use '/learn <path>' to add one.\n");
2116
+ println!(
2117
+ "No learned skills found in workspace: {}. Use '/learn <path>' to add one.\n",
2118
+ session.current_dir.display()
2119
+ );
1992
2120
  } else {
1993
- println!("Learned AI Skills:");
2121
+ println!(
2122
+ "Learned AI Skills (Workspace: {}):",
2123
+ session.current_dir.display()
2124
+ );
1994
2125
  for entry in &unique_skills {
1995
2126
  let skill = &entry.skill;
1996
2127
  let name = &skill.name;
@@ -2036,10 +2167,11 @@ pub async fn handle_slash_command(
2036
2167
  let skills = load_all_available_skills(&session.current_dir);
2037
2168
  if skills.is_empty() {
2038
2169
  println!(
2039
- "No skills found. Use `/skill add <path|github-repo|url>` to add one.\n"
2170
+ "No skills found in workspace: {}. Use `/skill add <path|github-repo|url>` to add one.\n",
2171
+ session.current_dir.display()
2040
2172
  );
2041
2173
  } else {
2042
- println!("Skills:");
2174
+ println!("Skills (Workspace: {}):", session.current_dir.display());
2043
2175
  for skill in &skills {
2044
2176
  let loc = if skill.source_path.contains("/.config/mint/mint-skills") {
2045
2177
  "Global"
@@ -2234,6 +2366,77 @@ pub async fn handle_slash_command(
2234
2366
  Some(SlashResult::Handled)
2235
2367
  }
2236
2368
 
2369
+ "/trajectory" => {
2370
+ let memory = match MemoryStore::open_default() {
2371
+ Ok(m) => m,
2372
+ Err(e) => {
2373
+ println!("{ERROR}Memory error:{RESET} {e}\n");
2374
+ return Some(SlashResult::Handled);
2375
+ }
2376
+ };
2377
+ let chat_id = mint_core::scoped_chat_id(
2378
+ CHAT_CLI_ID,
2379
+ Some(&session.current_dir.to_string_lossy()),
2380
+ );
2381
+ let (subcmd, args) = rest
2382
+ .split_once(char::is_whitespace)
2383
+ .map(|(c, a)| (c, a.trim()))
2384
+ .unwrap_or((rest, ""));
2385
+
2386
+ match subcmd {
2387
+ "export" => {
2388
+ let (run_id_opt, path_opt) = if args.is_empty() {
2389
+ (None, None)
2390
+ } else if args.starts_with("run-") {
2391
+ let mut parts = args.split_whitespace();
2392
+ let r = parts.next();
2393
+ let p = parts.next();
2394
+ (r, p)
2395
+ } else {
2396
+ (None, Some(args))
2397
+ };
2398
+
2399
+ match memory.export_trajectory_json(&chat_id, run_id_opt) {
2400
+ Ok(json) => {
2401
+ let default_path = format!("trajectory-{}.json", chrono::Local::now().format("%Y%m%d%H%M%S"));
2402
+ let dest_path = path_opt.unwrap_or(&default_path);
2403
+ match std::fs::write(dest_path, &json) {
2404
+ Ok(_) => println!("{MINT}Exported SWE-bench trajectory to {dest_path}{RESET}\n"),
2405
+ Err(err) => println!("{ERROR}Failed to write trajectory to {dest_path}:{RESET} {err}\n"),
2406
+ }
2407
+ }
2408
+ Err(e) => println!("{ERROR}Failed to export trajectory:{RESET} {e}\n"),
2409
+ }
2410
+ }
2411
+ _ => {
2412
+ match memory.export_trajectory_json(&chat_id, None) {
2413
+ Ok(json) => {
2414
+ if let Ok(run) = mint_core::orchestration::trajectory_schema::StandardTrajectoryRun::from_json(&json) {
2415
+ println!("\n{BLUE}Execution Trajectory (v{}){RESET}", run.schema_version);
2416
+ println!(" {DIM}Run ID:{RESET} {}", run.run_id);
2417
+ println!(" {DIM}Task:{RESET} {}", run.task);
2418
+ println!(" {DIM}Model:{RESET} {} ({})", run.model, run.provider);
2419
+ println!(" {DIM}Outcome:{RESET} {}", run.outcome);
2420
+ println!(" {DIM}Metrics:{RESET} {} steps | {} tokens | {:.1}s", run.total_steps, run.total_tokens, run.duration_secs);
2421
+ if !run.trajectory.is_empty() {
2422
+ println!("\n {BLUE}Step Timeline:{RESET}");
2423
+ for s in &run.trajectory {
2424
+ let status_color = if s.status == "success" { MINT } else { ERROR };
2425
+ println!(" {DIM}Step {:>2}:{RESET} {:<15} {status_color}{:<10}{RESET} ({}ms)", s.step, s.action, s.status, s.duration_ms);
2426
+ }
2427
+ }
2428
+ println!("\n{DIM}Use '/trajectory export [path.json]' to save SWE-bench JSON.{RESET}\n");
2429
+ } else {
2430
+ println!("{DIM}Trajectory JSON ({} bytes). Use '/trajectory export' to save.{RESET}\n", json.len());
2431
+ }
2432
+ }
2433
+ Err(e) => println!("{DIM}No recorded trajectory for this session:{RESET} {e}\n"),
2434
+ }
2435
+ }
2436
+ }
2437
+ Some(SlashResult::Handled)
2438
+ }
2439
+
2237
2440
  "/cron" => {
2238
2441
  let cron_jobs = match mint_core::CronStore::open_default() {
2239
2442
  Ok(store) => store,
@@ -2557,11 +2760,9 @@ pub async fn handle_slash_command(
2557
2760
  Some(SlashResult::Handled)
2558
2761
  }
2559
2762
 
2560
- "/release-notes" => {
2561
- ui.push_command_output(format!(
2562
- "\n{BLUE}โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€{RESET}\n{}\n{BLUE}โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€{RESET}",
2563
- mint_core::release_notes::text()
2564
- ));
2763
+ "/release-notes" | "/release_notes" | "/release-note" | "/release_note"
2764
+ | "/releasenotes" | "/releasenote" => {
2765
+ ui.push_release_notes(&mint_core::release_notes::text());
2565
2766
  Some(SlashResult::Handled)
2566
2767
  }
2567
2768
 
@@ -2993,6 +3194,74 @@ pub async fn handle_slash_command(
2993
3194
  }
2994
3195
  }
2995
3196
 
3197
+ "/voice" => {
3198
+ let sub = rest.trim().to_ascii_lowercase();
3199
+ if sub == "stop" || sub == "cancel" {
3200
+ let _ = super::stop_cli_voice_recording();
3201
+ ui.push_notice("Voice recording stopped.");
3202
+ return Some(SlashResult::Handled);
3203
+ }
3204
+ if !super::is_cli_voice_recording()
3205
+ && let Err(err) = super::start_cli_voice_recording()
3206
+ {
3207
+ ui.push_notice(format!("Microphone error: {err}"));
3208
+ return Some(SlashResult::Handled);
3209
+ }
3210
+ let choices = vec![
3211
+ ChoiceItem::with_description(
3212
+ "Transcribe & Send",
3213
+ "Stop recording, transcribe speech, and send prompt to Mint",
3214
+ "send",
3215
+ ),
3216
+ ChoiceItem::with_description("Cancel", "Discard current voice recording", "cancel"),
3217
+ ];
3218
+ match ui.prompt_choice(
3219
+ "๐ŸŽ™ Recording Voice",
3220
+ "Speak into your microphone, then select an action:",
3221
+ &choices,
3222
+ ) {
3223
+ Ok(Some(0)) => {
3224
+ let wav_bytes = match super::stop_cli_voice_recording() {
3225
+ Ok(Some(bytes)) => bytes,
3226
+ Ok(None) => {
3227
+ ui.push_notice("No active voice recording found.");
3228
+ return Some(SlashResult::Handled);
3229
+ }
3230
+ Err(err) => {
3231
+ ui.push_notice(format!("Voice recording error: {err}"));
3232
+ return Some(SlashResult::Handled);
3233
+ }
3234
+ };
3235
+ ui.push_notice("Transcribing voice recordingโ€ฆ");
3236
+ match mint_core::mic_transcribe::transcribe_recording(
3237
+ &session.config,
3238
+ wav_bytes,
3239
+ )
3240
+ .await
3241
+ {
3242
+ Ok(text) if !text.trim().is_empty() => {
3243
+ let cleaned = text.trim().to_string();
3244
+ ui.push_notice(format!("๐ŸŽ™ Heard: {cleaned}"));
3245
+ Some(SlashResult::ForwardToAgent(cleaned))
3246
+ }
3247
+ Ok(_) => {
3248
+ ui.push_notice("No speech detected in voice recording.");
3249
+ Some(SlashResult::Handled)
3250
+ }
3251
+ Err(err) => {
3252
+ ui.push_notice(format!("Voice transcription failed: {err}"));
3253
+ Some(SlashResult::Handled)
3254
+ }
3255
+ }
3256
+ }
3257
+ _ => {
3258
+ let _ = super::stop_cli_voice_recording();
3259
+ ui.push_notice("Voice recording cancelled.");
3260
+ Some(SlashResult::Handled)
3261
+ }
3262
+ }
3263
+ }
3264
+
2996
3265
  _ => {
2997
3266
  // Unknown slash command โ€” treat as normal message to the agent
2998
3267
  None
@@ -4155,4 +4424,120 @@ mod tests {
4155
4424
  assert!(matches!(res, Some(SlashResult::Handled)));
4156
4425
  assert!(session.fast_mode);
4157
4426
  }
4427
+
4428
+ #[tokio::test]
4429
+ async fn slash_release_notes_routes_to_push_release_notes() {
4430
+ let mut session = InteractiveSession {
4431
+ chat_id: mint_core::CHAT_CLI_ID.to_string(),
4432
+ config: MintConfig::default(),
4433
+ current_dir: std::env::current_dir().unwrap(),
4434
+ fast_mode: false,
4435
+ plan_mode: false,
4436
+ pending_image: None,
4437
+ history: Vec::new(),
4438
+ jobs: BackgroundJobs::new(),
4439
+ };
4440
+
4441
+ for cmd in [
4442
+ "/release-notes",
4443
+ "/release_notes",
4444
+ "/release-note",
4445
+ "/release_note",
4446
+ ] {
4447
+ let mut ui = MockCommandUi::new();
4448
+ let res = handle_slash_command(&mut session, &mut ui, cmd).await;
4449
+ assert!(matches!(res, Some(SlashResult::Handled)));
4450
+ assert!(
4451
+ ui.command_outputs.is_empty(),
4452
+ "must not route {cmd} to push_command_output"
4453
+ );
4454
+ assert_eq!(
4455
+ ui.release_notes.len(),
4456
+ 1,
4457
+ "must route {cmd} to push_release_notes"
4458
+ );
4459
+ assert!(ui.release_notes[0].contains("Release Notes"));
4460
+ }
4461
+ }
4462
+
4463
+ #[test]
4464
+ fn format_plan_meta_parses_timestamp() {
4465
+ let p1 = Path::new("/tmp/plans/20261102-182231-my-plan.md");
4466
+ assert_eq!(format_plan_meta(p1), "2026-11-02 18:22:31 ยท my-plan");
4467
+
4468
+ let p2 = Path::new("/tmp/plans/20261102-180001.md");
4469
+ assert_eq!(format_plan_meta(p2), "2026-11-02 18:00:01");
4470
+
4471
+ let p3 = Path::new("/tmp/plans/custom-plan.md");
4472
+ assert_eq!(format_plan_meta(p3), "custom-plan.md");
4473
+ }
4474
+
4475
+ #[tokio::test]
4476
+ async fn slash_plan_list_interactive_selection_and_show() {
4477
+ let temp = std::env::temp_dir().join(format!("mint-plan-test-{}", std::process::id()));
4478
+ let plans_dir = temp.join(".agents").join("plans");
4479
+ std::fs::create_dir_all(&plans_dir).unwrap();
4480
+
4481
+ let plan1_content = "# First Plan\n- [ ] Task 1";
4482
+ let plan2_content = "# Second Plan\n- [x] Done";
4483
+ std::fs::write(plans_dir.join("20261102-180000-plan-one.md"), plan1_content).unwrap();
4484
+ std::fs::write(plans_dir.join("20261102-183000-plan-two.md"), plan2_content).unwrap();
4485
+
4486
+ let mut session = InteractiveSession {
4487
+ chat_id: mint_core::CHAT_CLI_ID.to_string(),
4488
+ config: MintConfig::default(),
4489
+ current_dir: temp.clone(),
4490
+ fast_mode: false,
4491
+ plan_mode: false,
4492
+ pending_image: None,
4493
+ history: Vec::new(),
4494
+ jobs: BackgroundJobs::new(),
4495
+ };
4496
+
4497
+ // 1. /plan list with interactive selection (pick index 0, which is the newest plan2)
4498
+ let mut ui = MockCommandUi::new();
4499
+ ui.choice_answers.push(Some(0));
4500
+ let res = handle_slash_command(&mut session, &mut ui, "/plan list").await;
4501
+ assert!(matches!(res, Some(SlashResult::Handled)));
4502
+ assert_eq!(ui.plans.len(), 1);
4503
+ assert_eq!(ui.plans[0], plan2_content);
4504
+
4505
+ // 2. /plan list 1 directly views the first plan
4506
+ let mut ui = MockCommandUi::new();
4507
+ let res = handle_slash_command(&mut session, &mut ui, "/plan list 1").await;
4508
+ assert!(matches!(res, Some(SlashResult::Handled)));
4509
+ assert_eq!(ui.plans.len(), 1);
4510
+ assert_eq!(ui.plans[0], plan2_content);
4511
+
4512
+ // 3. /plan show 2 views the second plan
4513
+ let mut ui = MockCommandUi::new();
4514
+ let res = handle_slash_command(&mut session, &mut ui, "/plan show 2").await;
4515
+ assert!(matches!(res, Some(SlashResult::Handled)));
4516
+ assert_eq!(ui.plans.len(), 1);
4517
+ assert_eq!(ui.plans[0], plan1_content);
4518
+
4519
+ let _ = std::fs::remove_dir_all(temp);
4520
+ }
4521
+
4522
+ #[tokio::test]
4523
+ async fn slash_voice_stop_is_handled_cleanly() {
4524
+ let mut session = InteractiveSession {
4525
+ chat_id: mint_core::CHAT_CLI_ID.to_string(),
4526
+ config: MintConfig::default(),
4527
+ current_dir: std::env::current_dir().unwrap(),
4528
+ fast_mode: false,
4529
+ plan_mode: false,
4530
+ pending_image: None,
4531
+ history: Vec::new(),
4532
+ jobs: BackgroundJobs::new(),
4533
+ };
4534
+ let mut ui = MockCommandUi::new();
4535
+ let res = handle_slash_command(&mut session, &mut ui, "/voice stop").await;
4536
+ assert!(matches!(res, Some(SlashResult::Handled)));
4537
+ assert!(
4538
+ ui.notices.iter().any(|n| n.contains("Voice recording")),
4539
+ "expected voice notice, got: {:?}",
4540
+ ui.notices
4541
+ );
4542
+ }
4158
4543
  }