@pheem49/mint 1.14.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (925) hide show
  1. package/Cargo.lock +1258 -35
  2. package/Cargo.toml +5 -2
  3. package/LICENSE +21 -654
  4. package/README.md +93 -756
  5. package/Release_Note.md +53 -446
  6. package/apps/mint-companion/src-tauri/Cargo.toml +20 -0
  7. package/apps/mint-companion/src-tauri/build.rs +3 -0
  8. package/apps/mint-companion/src-tauri/src/main.rs +468 -0
  9. package/apps/mint-companion/tsconfig.json +20 -0
  10. package/apps/mint-companion/vite.config.ts +3 -0
  11. package/components.json +19 -0
  12. package/crates/mint-cli/Cargo.toml +9 -1
  13. package/crates/mint-cli/src/agent/approval_prompts.rs +16 -3
  14. package/crates/mint-cli/src/agent/live_status.rs +545 -148
  15. package/crates/mint-cli/src/agent/markdown_render.rs +601 -61
  16. package/crates/mint-cli/src/agent.rs +723 -258
  17. package/crates/mint-cli/src/commands/agent.rs +83 -74
  18. package/crates/mint-cli/src/commands/eval.rs +9 -5
  19. package/crates/mint-cli/src/commands/git.rs +204 -0
  20. package/crates/mint-cli/src/commands/integrations.rs +35 -0
  21. package/crates/mint-cli/src/commands/knowledge.rs +13 -32
  22. package/crates/mint-cli/src/commands/mod.rs +81 -2
  23. package/crates/mint-cli/src/commands/tailnet_web.rs +235 -0
  24. package/crates/mint-cli/src/image.rs +32 -11
  25. package/crates/mint-cli/src/interactive/chat_tui.rs +7853 -0
  26. package/crates/mint-cli/src/interactive/command_ui.rs +477 -0
  27. package/crates/mint-cli/src/interactive/format.rs +8 -0
  28. package/crates/mint-cli/src/interactive/input_box.rs +94 -8
  29. package/crates/mint-cli/src/interactive/picker.rs +180 -37
  30. package/crates/mint-cli/src/interactive/resume_picker.rs +686 -0
  31. package/crates/mint-cli/src/interactive/slash_commands.rs +1071 -501
  32. package/crates/mint-cli/src/interactive/thought_viewer.rs +286 -0
  33. package/crates/mint-cli/src/interactive/tool_activity.rs +328 -0
  34. package/crates/mint-cli/src/interactive.rs +454 -166
  35. package/crates/mint-cli/src/main.rs +93 -26
  36. package/crates/mint-cli/src/markdown.rs +12 -5
  37. package/crates/mint-cli/src/mcp.rs +5 -0
  38. package/crates/mint-cli/src/mod_host.rs +6 -0
  39. package/crates/mint-cli/src/mods_cli.rs +62 -0
  40. package/crates/mint-cli/src/mods_ui.rs +187 -0
  41. package/crates/mint-cli/src/onboard.rs +37 -61
  42. package/crates/mint-cli/src/plugins_cli.rs +8 -5
  43. package/crates/mint-cli/src/setup.rs +10 -8
  44. package/crates/mint-cli/src/terminal_theme.rs +189 -0
  45. package/crates/mint-cli/src/updater.rs +112 -23
  46. package/crates/mint-cli/tests/library_intake.rs +77 -0
  47. package/crates/mint-cli/tests/mods_testing.rs +133 -0
  48. package/crates/mint-companion-protocol/Cargo.toml +10 -0
  49. package/crates/mint-companion-protocol/src/lib.rs +163 -0
  50. package/crates/mint-core/Cargo.toml +6 -3
  51. package/crates/mint-core/build.rs +26 -0
  52. package/crates/mint-core/src/agent/agent_loop.rs +1 -0
  53. package/crates/mint-core/src/agent/chat.rs +1003 -209
  54. package/crates/mint-core/src/agent/code_tools.rs +98 -2
  55. package/crates/mint-core/src/agent/memory/sources.rs +240 -0
  56. package/crates/mint-core/src/agent/memory.rs +805 -33
  57. package/crates/mint-core/src/agent/skill_inventory.rs +325 -0
  58. package/crates/mint-core/src/agent/skills.rs +437 -90
  59. package/crates/mint-core/src/agent.rs +1 -0
  60. package/crates/mint-core/src/api_server/routes/background_jobs.rs +310 -0
  61. package/crates/mint-core/src/api_server/routes/chat.rs +233 -190
  62. package/crates/mint-core/src/api_server/routes/html_preview.rs +77 -0
  63. package/crates/mint-core/src/api_server/routes/library.rs +97 -0
  64. package/crates/mint-core/src/api_server/routes/linked_folders.rs +118 -3
  65. package/crates/mint-core/src/api_server/routes/media_gen.rs +10 -57
  66. package/crates/mint-core/src/api_server/routes/misc.rs +114 -121
  67. package/crates/mint-core/src/api_server/routes/mod.rs +6 -0
  68. package/crates/mint-core/src/api_server/routes/mods.rs +31 -0
  69. package/crates/mint-core/src/api_server/routes/sessions.rs +85 -0
  70. package/crates/mint-core/src/api_server/routes/skills_subagents.rs +12 -42
  71. package/crates/mint-core/src/api_server/routes/slash.rs +50 -1
  72. package/crates/mint-core/src/api_server/routes/sources.rs +101 -0
  73. package/crates/mint-core/src/api_server.rs +140 -12
  74. package/crates/mint-core/src/avatar_bridge.rs +13 -2
  75. package/crates/mint-core/src/browser/cdp.rs +74 -83
  76. package/crates/mint-core/src/browser/evidence.rs +260 -0
  77. package/crates/mint-core/src/browser/input.rs +1 -1
  78. package/crates/mint-core/src/browser/interact.rs +98 -124
  79. package/crates/mint-core/src/browser/lifecycle.rs +75 -4
  80. package/crates/mint-core/src/browser/mod.rs +16 -2
  81. package/crates/mint-core/src/browser/navigate.rs +27 -19
  82. package/crates/mint-core/src/browser/observe.js +40 -0
  83. package/crates/mint-core/src/browser/session.rs +1610 -0
  84. package/crates/mint-core/src/companion.rs +716 -0
  85. package/crates/mint-core/src/cron/scheduler.rs +34 -2
  86. package/crates/mint-core/src/git/branches.rs +348 -0
  87. package/crates/mint-core/src/git/checkpoint.rs +40 -0
  88. package/crates/mint-core/src/git/diff.rs +206 -0
  89. package/crates/mint-core/src/git/mod.rs +10 -2
  90. package/crates/mint-core/src/integrations/channels.rs +88 -345
  91. package/crates/mint-core/src/integrations/mcp.rs +397 -50
  92. package/crates/mint-core/src/integrations/mcp_calls.rs +823 -0
  93. package/crates/mint-core/src/integrations/mcp_catalog.rs +267 -0
  94. package/crates/mint-core/src/integrations/mcp_device.rs +319 -0
  95. package/crates/mint-core/src/integrations/mcp_result.rs +356 -0
  96. package/crates/mint-core/src/integrations/webhooks.rs +539 -0
  97. package/crates/mint-core/src/integrations.rs +2 -0
  98. package/crates/mint-core/src/lib.rs +107 -40
  99. package/crates/mint-core/src/live_sync.rs +28 -9
  100. package/crates/mint-core/src/media/auto_shorts.rs +1 -0
  101. package/crates/mint-core/src/media/gemini_live.rs +145 -14
  102. package/crates/mint-core/src/media/image_models.rs +3 -27
  103. package/crates/mint-core/src/media/image_workflow.rs +216 -0
  104. package/crates/mint-core/src/media/library/intake.rs +144 -0
  105. package/crates/mint-core/src/media/library/migration.rs +56 -0
  106. package/crates/mint-core/src/media/library/removal.rs +55 -0
  107. package/crates/mint-core/src/media/library/tests.rs +730 -0
  108. package/crates/mint-core/src/media/library/thumbnails.rs +72 -0
  109. package/crates/mint-core/src/media/library.rs +545 -0
  110. package/crates/mint-core/src/media/mic_transcribe.rs +1 -0
  111. package/crates/mint-core/src/media/model_catalog.rs +375 -0
  112. package/crates/mint-core/src/media/pictures.rs +79 -222
  113. package/crates/mint-core/src/media/subtitle.rs +1 -0
  114. package/crates/mint-core/src/media/video_models.rs +3 -22
  115. package/crates/mint-core/src/media.rs +3 -0
  116. package/crates/mint-core/src/mods/manager.rs +1124 -0
  117. package/crates/mint-core/src/mods/mod.rs +569 -0
  118. package/crates/mint-core/src/mods/operations.rs +204 -0
  119. package/crates/mint-core/src/mods/session.rs +146 -0
  120. package/crates/mint-core/src/mods/slash.rs +59 -0
  121. package/crates/mint-core/src/mods/telemetry.rs +306 -0
  122. package/crates/mint-core/src/orchestration/approvals.rs +344 -0
  123. package/crates/mint-core/src/orchestration/context_render.rs +105 -0
  124. package/crates/mint-core/src/orchestration/mcp_review.rs +153 -0
  125. package/crates/mint-core/src/orchestration/memory_skill.rs +110 -33
  126. package/crates/mint-core/src/orchestration/mod.rs +3129 -481
  127. package/crates/mint-core/src/orchestration/mod_authoring_regressions.rs +209 -0
  128. package/crates/mint-core/src/orchestration/progress_clock.rs +80 -0
  129. package/crates/mint-core/src/orchestration/repeated_failures.rs +116 -0
  130. package/crates/mint-core/src/orchestration/review_regressions.rs +449 -0
  131. package/crates/mint-core/src/orchestration/run_control.rs +196 -0
  132. package/crates/mint-core/src/orchestration/tools/browser.rs +16 -139
  133. package/crates/mint-core/src/orchestration/tools/files.rs +161 -14
  134. package/crates/mint-core/src/orchestration/tools/media.rs +37 -41
  135. package/crates/mint-core/src/orchestration/tools/misc.rs +5 -3
  136. package/crates/mint-core/src/orchestration/tools/mod.rs +2 -0
  137. package/crates/mint-core/src/orchestration/tools/mods.rs +161 -0
  138. package/crates/mint-core/src/orchestration/tools/plugins_mcp.rs +303 -71
  139. package/crates/mint-core/src/orchestration/tools/shell.rs +95 -2
  140. package/crates/mint-core/src/orchestration/tools/web.rs +1 -1
  141. package/crates/mint-core/src/orchestration/workspace_helpers.rs +4 -1
  142. package/crates/mint-core/src/prompts/agent.rs +75 -31
  143. package/crates/mint-core/src/prompts/chat.rs +1 -1
  144. package/crates/mint-core/src/prompts/persona.rs +1 -1
  145. package/crates/mint-core/src/prompts/tool_catalog.rs +121 -27
  146. package/crates/mint-core/src/search/knowledge.rs +7 -1
  147. package/crates/mint-core/src/search/linked_folders/index.rs +896 -0
  148. package/crates/mint-core/src/search/linked_folders.rs +473 -131
  149. package/crates/mint-core/src/slash/catalog.rs +1 -1
  150. package/crates/mint-core/src/slash/mod.rs +644 -33
  151. package/crates/mint-core/src/slash/model_fetcher.rs +12 -3
  152. package/crates/mint-core/src/slash/models.rs +66 -10
  153. package/crates/mint-core/src/slash/mods.rs +155 -0
  154. package/crates/mint-core/src/system/bg_shell.rs +1129 -95
  155. package/crates/mint-core/src/system/config.rs +235 -10
  156. package/crates/mint-core/src/system/html_preview.rs +398 -0
  157. package/crates/mint-core/src/system/mint_web.rs +164 -0
  158. package/crates/mint-core/src/system/release_notes.rs +18 -0
  159. package/crates/mint-core/src/system/shell.rs +21 -6
  160. package/crates/mint-core/src/system/workspace.rs +292 -0
  161. package/crates/mint-core/src/system/workspace_history.rs +604 -0
  162. package/crates/mint-core/src/system.rs +5 -0
  163. package/crates/mint-core/tests/background_retention.rs +34 -0
  164. package/crates/mint-core/tests/background_shutdown.rs +24 -0
  165. package/crates/mint-core/tests/library_http.rs +209 -0
  166. package/crates/mint-core/tests/mcp_contract.rs +283 -0
  167. package/crates/mint-core/tests/mcp_stdio.rs +11 -10
  168. package/crates/mint-core/tests/media_model_catalog_http.rs +403 -0
  169. package/crates/mint-core/tests/memory_persistence.rs +39 -0
  170. package/crates/mint-core/tests/mods_http.rs +215 -0
  171. package/crates/mint-core/tests/terminal_shutdown.rs +109 -0
  172. package/crates/mint-mod-runtime/Cargo.toml +18 -0
  173. package/crates/mint-mod-runtime/src/lib.rs +507 -0
  174. package/crates/mint-mod-runtime/src/sdk.js +56 -0
  175. package/crates/mint-mod-runtime/src/test_sdk.js +32 -0
  176. package/crates/mint-mod-runtime/src/testing.rs +94 -0
  177. package/crates/mint-mod-runtime/tests/runtime.rs +156 -0
  178. package/docs/mods/AUTHORING.md +61 -0
  179. package/docs/mods/README.md +139 -0
  180. package/docs/mods/TESTING.md +56 -0
  181. package/docs/mods/mint-mods.d.ts +66 -0
  182. package/examples/device-mcp/README.md +22 -0
  183. package/examples/device-mcp/contract.md +49 -0
  184. package/examples/device-mcp/mock-device.mjs +66 -0
  185. package/examples/device-mcp/server.mjs +48 -0
  186. package/examples/device-mcp/server.test.mjs +78 -0
  187. package/examples/mods/task-checklist/README.md +1 -0
  188. package/examples/mods/task-checklist/main.ts +17 -0
  189. package/examples/mods/task-checklist/manifest.json +1 -0
  190. package/examples/mods/task-checklist/tests/checklist.test.ts +15 -0
  191. package/examples/mods/token-meter/README.md +1 -0
  192. package/examples/mods/token-meter/main.ts +8 -0
  193. package/examples/mods/token-meter/manifest.json +1 -0
  194. package/examples/mods/tool-guard/README.md +1 -0
  195. package/examples/mods/tool-guard/main.ts +9 -0
  196. package/examples/mods/tool-guard/manifest.json +1 -0
  197. package/out/web/assets/CliSessionsView-CtzUJpK_.css +1 -0
  198. package/out/web/assets/CliSessionsView-D7hw0Mgj.js +1 -0
  199. package/out/web/assets/CodeReviewPage-C7bEOJfd.js +4 -0
  200. package/out/web/assets/CodeReviewPage-Dte9uLiL.css +1 -0
  201. package/out/web/assets/CommandPalette-0RrF-AOT.js +1 -0
  202. package/out/web/assets/ImageStudioPanel-CdxkAf_r.js +1 -0
  203. package/out/web/assets/ImageStudioPanel-D0lnhQV5.css +1 -0
  204. package/out/web/assets/LibraryPage--Qfisp6D.js +2 -0
  205. package/out/web/assets/LibraryPage-DAxUTAg7.css +1 -0
  206. package/out/web/assets/LinkedFoldersView-2nfZbDgN.js +1 -0
  207. package/out/web/assets/McpRegistryPicker-h9uS8_wT.js +1 -0
  208. package/out/web/assets/McpServersView-slfQJzNB.js +1 -0
  209. package/out/web/assets/MintDashboard-BSR5XpXh.js +25 -0
  210. package/out/web/assets/MintDashboard-CWUcCGhd.css +1 -0
  211. package/out/web/assets/PluginsView-l7LSm503.js +1 -0
  212. package/out/web/assets/ScheduledTasksView-CttmLbq1.js +1 -0
  213. package/out/web/assets/SettingsWindow-BCMLYvEV.js +4 -0
  214. package/out/web/assets/SettingsWindow-DcMVmU9u.css +1 -0
  215. package/out/web/assets/SkillsView-rNs1qr_U.js +2 -0
  216. package/out/web/assets/ToolSurfacePage-B9DzEPWN.js +37 -0
  217. package/out/web/assets/ToolSurfacePage-CTfgggF2.css +1 -0
  218. package/out/web/assets/VeoStudioPanel-DOj7_WR3.css +1 -0
  219. package/out/web/assets/VeoStudioPanel-DiJs_Cg2.js +4 -0
  220. package/out/web/assets/WorkspacePanel-CbJ1PFoZ.js +1 -0
  221. package/out/web/assets/WorkspaceSelector-B2xIp04D.js +1 -0
  222. package/out/web/assets/WorkspaceSelector-Ca8uJOsS.css +1 -0
  223. package/out/web/assets/{abnfDiagram-VCTEODGH-DAOBA7ZG.js → abnfDiagram-VCTEODGH-CD0CjoGl.js} +1 -1
  224. package/out/web/assets/{architecture-7GRP2DOG-CgSwQOPQ.js → architecture-7GRP2DOG-RKV83OeZ.js} +1 -1
  225. package/out/web/assets/{architectureDiagram-5GKGNRK7-CYp3yupP.js → architectureDiagram-5GKGNRK7-nN_HAFct.js} +1 -1
  226. package/out/web/assets/{blockDiagram-NRAW4CY4-CyWybDWr.js → blockDiagram-NRAW4CY4-BrrqzHW5.js} +1 -1
  227. package/out/web/assets/{c4Diagram-UCG6FXSJ-BvY3U709.js → c4Diagram-UCG6FXSJ-DTdV8_zE.js} +1 -1
  228. package/out/web/assets/{chunk-75Z2AOVW-TLXCoZYv.js → chunk-75Z2AOVW-_M0z5olV.js} +1 -1
  229. package/out/web/assets/chunk-CKBBP62Z-BpQEgeHF.js +2 -0
  230. package/out/web/assets/{chunk-CLGD4ZFX-xjsKtNS7.js → chunk-CLGD4ZFX-D54yGvGS.js} +1 -1
  231. package/out/web/assets/chunk-DSNCTWBM-C-gvT2ru.js +2 -0
  232. package/out/web/assets/chunk-DU6HZSFF-CnFngIhW.js +128 -0
  233. package/out/web/assets/{chunk-F27PBJKO-BFpgF55A.js → chunk-F27PBJKO-BqtWrnEO.js} +1 -1
  234. package/out/web/assets/{chunk-G27WJ6UU-DfF7qW-C.js → chunk-G27WJ6UU-Ckoq5mi2.js} +1 -1
  235. package/out/web/assets/{chunk-GMAD6QVW-C-558kh_.js → chunk-GMAD6QVW-BuhEcgHq.js} +1 -1
  236. package/out/web/assets/{chunk-JQ64N6SF-wJmeGKAw.js → chunk-JQ64N6SF-CF8T7GiZ.js} +1 -1
  237. package/out/web/assets/{chunk-LCL6LL3I-C1wHD8Ie.js → chunk-LCL6LL3I-BhXV9zyH.js} +1 -1
  238. package/out/web/assets/{chunk-OBVCFTLP-BsRTPBqs.js → chunk-OBVCFTLP-CRIkunUB.js} +1 -1
  239. package/out/web/assets/{chunk-P2QGCYS3-HZIiM7Ni.js → chunk-P2QGCYS3-UFEU6BxZ.js} +1 -1
  240. package/out/web/assets/{chunk-POPQ4Y6H-Dk9wvVb0.js → chunk-POPQ4Y6H-CQcrNbjr.js} +1 -1
  241. package/out/web/assets/{chunk-PWAF6VOD-BmjYLNbq.js → chunk-PWAF6VOD-Cc2uVDsG.js} +1 -1
  242. package/out/web/assets/{chunk-R7TYR2AO-CaHIf-lK.js → chunk-R7TYR2AO-DiCxzdAY.js} +1 -1
  243. package/out/web/assets/{chunk-RHFEMEQ7-_T561hOU.js → chunk-RHFEMEQ7-b7hnPmrR.js} +1 -1
  244. package/out/web/assets/{chunk-SVP7TREG-CM-GGYoY.js → chunk-SVP7TREG-Bu_yYb-V.js} +1 -1
  245. package/out/web/assets/{chunk-TEH6E4GO-K2A8Vg2C.js → chunk-TEH6E4GO-G4Cdlyrt.js} +1 -1
  246. package/out/web/assets/classDiagram-DTDB5LWJ-RnC2mYO4.js +1 -0
  247. package/out/web/assets/classDiagram-v2-JRS7N3AN-RnC2mYO4.js +1 -0
  248. package/out/web/assets/config-CnvCChUM.js +2 -0
  249. package/out/web/assets/config-DM6oIVO3.css +1 -0
  250. package/out/web/assets/core-DsKkQ7ig.js +1 -0
  251. package/out/web/assets/{cynefin-OW5HDTMX-ClzaB6cc.js → cynefin-OW5HDTMX-CnzQfOGp.js} +1 -1
  252. package/out/web/assets/{cynefinDiagram-5FMLGOSQ-D_JzZBzf.js → cynefinDiagram-5FMLGOSQ-DVtQnfpm.js} +1 -1
  253. package/out/web/assets/{dagre-3AP2YEHR-BDuUeMHj.js → dagre-3AP2YEHR-DG76_k5_.js} +1 -1
  254. package/out/web/assets/{diagram-S7CK7UJ4-DgtcfE8P.js → diagram-S7CK7UJ4-CaouUoze.js} +1 -1
  255. package/out/web/assets/{diagram-UQ7AKVKN-DTLoEYti.js → diagram-UQ7AKVKN-B4bEc26B.js} +1 -1
  256. package/out/web/assets/{diagram-VSXAHHWV-ChGl9pXz.js → diagram-VSXAHHWV-BJ86Ov2Y.js} +1 -1
  257. package/out/web/assets/{diagram-VX7I27RA-Be8DWz0S.js → diagram-VX7I27RA-7hH5IPYf.js} +1 -1
  258. package/out/web/assets/{diagram-Z3DM3KII-BMXjRTOF.js → diagram-Z3DM3KII-CCM4clo8.js} +1 -1
  259. package/out/web/assets/dist-js-BkYNznHX.js +1 -0
  260. package/out/web/assets/{ebnfDiagram-PWID7BFC-8Q9pl1CJ.js → ebnfDiagram-PWID7BFC-Da7WAM3k.js} +1 -1
  261. package/out/web/assets/{erDiagram-SSCWMZ5O-DjH8Lnkn.js → erDiagram-SSCWMZ5O-CzzmnZWT.js} +1 -1
  262. package/out/web/assets/event-Cdt7Byyj.js +1 -0
  263. package/out/web/assets/{eventmodeling-NTZA5JFV-BKUH_DOp.js → eventmodeling-NTZA5JFV-xcfsA0XD.js} +1 -1
  264. package/out/web/assets/fira-code-latin-600-normal-BmSSHshu.woff +0 -0
  265. package/out/web/assets/fira-code-latin-600-normal-CvYZpPHg.woff2 +0 -0
  266. package/out/web/assets/fira-code-symbols2-600-normal-Dvq6IQE5.woff +0 -0
  267. package/out/web/assets/flowDiagram-A5DVABFB-JdtH1673.js +1 -0
  268. package/out/web/assets/{ganttDiagram-EL5Y4UJY-D7fZKJNM.js → ganttDiagram-EL5Y4UJY-B3ClFGmL.js} +1 -1
  269. package/out/web/assets/{gitGraph-4MIJSDKK-BypWaaBU.js → gitGraph-4MIJSDKK-BZ_y_cDU.js} +1 -1
  270. package/out/web/assets/{gitGraphDiagram-WWUBYQGX-DWiw_3bq.js → gitGraphDiagram-WWUBYQGX-drhRSYm3.js} +1 -1
  271. package/out/web/assets/index-BZ9xgmMP.css +1 -0
  272. package/out/web/assets/index-Ca8cCS4h.js +168 -0
  273. package/out/web/assets/{info-A6RAGUB7-KkAUxT4j.js → info-A6RAGUB7-B7I3K0F1.js} +1 -1
  274. package/out/web/assets/{infoDiagram-RXCK75RN-BNb6E48y.js → infoDiagram-RXCK75RN-deX_1MPh.js} +1 -1
  275. package/out/web/assets/{ishikawaDiagram-5VMMS53U-Caa-JoAK.js → ishikawaDiagram-5VMMS53U-s38yo28y.js} +1 -1
  276. package/out/web/assets/{journeyDiagram-EYS64GPL-DOrmFGz6.js → journeyDiagram-EYS64GPL-CZn2kB8b.js} +1 -1
  277. package/out/web/assets/jsx-runtime-DN4NhQUK.js +1 -0
  278. package/out/web/assets/{kanban-definition-3QL26DDD-BOWCYcK0.js → kanban-definition-3QL26DDD-DodjgySL.js} +1 -1
  279. package/out/web/assets/markdown-CMhYIcWB.js +39 -0
  280. package/out/web/assets/{mermaid-parser.core-BQqjCkS_.js → mermaid-parser.core-Whu2rlJC.js} +3 -3
  281. package/out/web/assets/mermaid.core-CKyPo8VH.js +11 -0
  282. package/out/web/assets/{mindmap-definition-FBJOCRG2-jTceWpr0.js → mindmap-definition-FBJOCRG2-260WBDxZ.js} +1 -1
  283. package/out/web/assets/modelManager-CUaGWMWu.js +2 -0
  284. package/out/web/assets/oauthManager-DlNhXJr6.js +1 -0
  285. package/out/web/assets/{packet-AYTQ26CC-CJ5RXgol.js → packet-AYTQ26CC-CEeIRKRG.js} +1 -1
  286. package/out/web/assets/{pegDiagram-XKGWAZYB-y8wMtd0y.js → pegDiagram-XKGWAZYB-BYadI-KO.js} +1 -1
  287. package/out/web/assets/{pie-WAS4IAKB-72fTBbl4.js → pie-WAS4IAKB-D8uf4dh5.js} +1 -1
  288. package/out/web/assets/{pieDiagram-E7YTZNPT-e0O02qWq.js → pieDiagram-E7YTZNPT-CjSDy4hO.js} +1 -1
  289. package/out/web/assets/{quadrantDiagram-AXDQQJYC-C9phYLom.js → quadrantDiagram-AXDQQJYC-B8D3gU5d.js} +1 -1
  290. package/out/web/assets/{radar-RG4KPBEZ-BAU2hzUT.js → radar-RG4KPBEZ-DZJxnokY.js} +1 -1
  291. package/out/web/assets/{railroad-74A4TZTK-B0bCAVHC.js → railroad-74A4TZTK-DBysUiUi.js} +1 -1
  292. package/out/web/assets/{railroad-abnf-HS5TGJTU-WhxO7ndE.js → railroad-abnf-HS5TGJTU-CHWxoJYg.js} +1 -1
  293. package/out/web/assets/{railroad-ebnf-LZEXJU2U-BkA0m7-F.js → railroad-ebnf-LZEXJU2U-DDv7X6bY.js} +1 -1
  294. package/out/web/assets/{railroad-peg-WCYAUIDC-BsVpHIaj.js → railroad-peg-WCYAUIDC-DpfcYYNJ.js} +1 -1
  295. package/out/web/assets/{railroadDiagram-O6MQD6OU-CyOLN65Q.js → railroadDiagram-O6MQD6OU-CYtyv0t3.js} +1 -1
  296. package/out/web/assets/{requirementDiagram-EFPCY7ZU-DQXJ7Dud.js → requirementDiagram-EFPCY7ZU-D2X-Ewik.js} +1 -1
  297. package/out/web/assets/{sankeyDiagram-P5KCCOFB-B2XLyIIc.js → sankeyDiagram-P5KCCOFB-Bn2x6C4Y.js} +1 -1
  298. package/out/web/assets/{sequenceDiagram-WJ2MYXX4-DGQY4wwm.js → sequenceDiagram-WJ2MYXX4-BvFLKtPd.js} +1 -1
  299. package/out/web/assets/{stateDiagram-HBIQ2CUA-DHZpDwNy.js → stateDiagram-HBIQ2CUA-Bx0GWeaY.js} +1 -1
  300. package/out/web/assets/stateDiagram-v2-4QOOHH4V--hol1yg_.js +1 -0
  301. package/out/web/assets/studio-B1mk40wD.js +1 -0
  302. package/out/web/assets/{swimlanes-XN3QIQJK-Bn_jcZz-.js → swimlanes-XN3QIQJK-CCma0T7L.js} +1 -1
  303. package/out/web/assets/swimlanesDiagram-VK2B7HYN-BkohoVsU.js +8 -0
  304. package/out/web/assets/{timeline-definition-24CTP7MA-CdTERuJZ.js → timeline-definition-24CTP7MA-iCRhhJ7C.js} +1 -1
  305. package/out/web/assets/{treeView-Q6P3EWNA-TKBKQG6R.js → treeView-Q6P3EWNA-DZ-y08qp.js} +1 -1
  306. package/out/web/assets/{treemap-WGGIJYW6-BP7gQoiC.js → treemap-WGGIJYW6-De0CxzMx.js} +1 -1
  307. package/out/web/assets/{vennDiagram-4TSXK5OY-BHUmxDuK.js → vennDiagram-4TSXK5OY-w_7aZ6xe.js} +1 -1
  308. package/out/web/assets/{wardley-WFR3VGLG-9bct5AAN.js → wardley-WFR3VGLG-DT0y0xJ4.js} +1 -1
  309. package/out/web/assets/{wardleyDiagram-VM6X3IG4-BfJwDDso.js → wardleyDiagram-VM6X3IG4-DAdXELbQ.js} +1 -1
  310. package/out/web/assets/window-BJCVtyET.js +1 -0
  311. package/out/web/assets/{xychartDiagram-S5SC5T6Z-Dqd9Mvpo.js → xychartDiagram-S5SC5T6Z-IZIXf3Vo.js} +1 -1
  312. package/out/web/index-web.html +4 -4
  313. package/out/web/index.html +4 -4
  314. package/package.json +80 -20
  315. package/shared-modules/.github/workflows/ci.yml +120 -0
  316. package/shared-modules/.github/workflows/update.yaml +28 -0
  317. package/slash-commands.json +16 -2
  318. package/src/bin/auto-build.js +66 -0
  319. package/src/bin/desktop.js +113 -0
  320. package/src/bin/desktop.test.js +113 -0
  321. package/src/bin/index.js +18 -25
  322. package/src/bin/index.test.js +89 -0
  323. package/src/bin/measure-effects.mjs +53 -0
  324. package/src/bin/package.test.js +28 -0
  325. package/src/bin/release-notes.test.js +84 -0
  326. package/src/bin/styles.test.js +20 -0
  327. package/src/bin/web.js +5 -0
  328. package/src/bin/web.test.js +39 -0
  329. package/src/renderer/index-web.html +1 -0
  330. package/src/renderer/index.html +1 -2
  331. package/src/renderer/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  332. package/src/renderer/shared/agentProgress.ts +201 -3
  333. package/src/renderer/shared/components/AgentActivityDrawer.tsx +9 -8
  334. package/src/renderer/shared/components/AgentActivityTable.tsx +193 -133
  335. package/src/renderer/shared/components/ApprovalCard.test.tsx +24 -0
  336. package/src/renderer/shared/components/ApprovalCard.tsx +10 -3
  337. package/src/renderer/shared/components/ArtifactPreviewPanel.tsx +91 -40
  338. package/src/renderer/shared/components/AuthGate.tsx +79 -48
  339. package/src/renderer/shared/components/BackgroundTerminals.tsx +181 -0
  340. package/src/renderer/shared/components/CalculationCard.tsx +41 -15
  341. package/src/renderer/shared/components/ChatCodeBlock.tsx +8 -4
  342. package/src/renderer/shared/components/ChatMessageItem.test.tsx +68 -0
  343. package/src/renderer/shared/components/ChatMessageItem.tsx +52 -33
  344. package/src/renderer/shared/components/ChatPanel.test.tsx +21 -0
  345. package/src/renderer/shared/components/ChatPanel.tsx +676 -415
  346. package/src/renderer/shared/components/ChunkErrorBoundary.tsx +115 -64
  347. package/src/renderer/shared/components/CliSessionsView.test.tsx +125 -0
  348. package/src/renderer/shared/components/CliSessionsView.tsx +543 -0
  349. package/src/renderer/shared/components/CodeReviewPage.tsx +668 -0
  350. package/src/renderer/shared/components/CollapsiblePasteInput.tsx +90 -0
  351. package/src/renderer/shared/components/CommandPalette.tsx +8 -8
  352. package/src/renderer/shared/components/ContextCompactionStatus.tsx +17 -0
  353. package/src/renderer/shared/components/DashboardSidebar.tsx +853 -229
  354. package/src/renderer/shared/components/DesktopTitlebar.tsx +371 -0
  355. package/src/renderer/shared/components/DiffReviewModal.tsx +3 -3
  356. package/src/renderer/shared/components/ErrorNotice.tsx +29 -0
  357. package/src/renderer/shared/components/FormattedMessage.tsx +11 -0
  358. package/src/renderer/shared/components/GeminiLiveOverlay.css +86 -0
  359. package/src/renderer/shared/components/GeminiLiveOverlay.test.tsx +24 -0
  360. package/src/renderer/shared/components/GeminiLiveOverlay.tsx +85 -101
  361. package/src/renderer/shared/components/GitBranchSelector.tsx +442 -0
  362. package/src/renderer/shared/components/GlideSelect.css +138 -0
  363. package/src/renderer/shared/components/GlideSelect.d.ts +31 -0
  364. package/src/renderer/shared/components/GlideSelect.jsx +266 -0
  365. package/src/renderer/shared/components/ImageGenCard.tsx +31 -12
  366. package/src/renderer/shared/components/ImageSearchCard.tsx +76 -65
  367. package/src/renderer/shared/components/ImageStudioPanel.tsx +49 -49
  368. package/src/renderer/shared/components/InlineThoughtNote.tsx +27 -0
  369. package/src/renderer/shared/components/LibraryItemCard.tsx +72 -0
  370. package/src/renderer/shared/components/LibraryPage.tsx +165 -0
  371. package/src/renderer/shared/components/LibraryPreview.tsx +59 -0
  372. package/src/renderer/shared/components/LinkedFoldersView.tsx +365 -46
  373. package/src/renderer/shared/components/McpRegistryPicker.tsx +1 -1
  374. package/src/renderer/shared/components/McpServersView.tsx +51 -30
  375. package/src/renderer/shared/components/McpToolAllowlist.tsx +2 -4
  376. package/src/renderer/shared/components/McpToolResults.tsx +99 -0
  377. package/src/renderer/shared/components/MermaidCard.tsx +14 -8
  378. package/src/renderer/shared/components/MintDashboard.tsx +1002 -831
  379. package/src/renderer/shared/components/ModSessionControls.tsx +8 -0
  380. package/src/renderer/shared/components/ModUi.test.tsx +65 -0
  381. package/src/renderer/shared/components/ModUi.tsx +26 -0
  382. package/src/renderer/shared/components/ModelSelectorPopover.tsx +547 -219
  383. package/src/renderer/shared/components/ModsPanel.tsx +156 -0
  384. package/src/renderer/shared/components/PlanChecklistWidget.tsx +1 -1
  385. package/src/renderer/shared/components/PluginsView.tsx +1 -1
  386. package/src/renderer/shared/components/ProgressActivity.tsx +17 -0
  387. package/src/renderer/shared/components/ReviewHistory.tsx +42 -0
  388. package/src/renderer/shared/components/RewindModal.tsx +11 -18
  389. package/src/renderer/shared/components/RunSummaryDashboard.tsx +8 -14
  390. package/src/renderer/shared/components/ScheduledTasksView.tsx +11 -10
  391. package/src/renderer/shared/components/ScreenCaptureDialog.css +221 -0
  392. package/src/renderer/shared/components/ScreenCaptureDialog.tsx +199 -0
  393. package/src/renderer/shared/components/SelectField.test.tsx +27 -0
  394. package/src/renderer/shared/components/SelectField.tsx +38 -0
  395. package/src/renderer/shared/components/SessionSources.tsx +48 -0
  396. package/src/renderer/shared/components/SessionSourcesPopover.tsx +61 -0
  397. package/src/renderer/shared/components/Settings/AgentsTab.tsx +41 -45
  398. package/src/renderer/shared/components/Settings/AudioTab.tsx +16 -15
  399. package/src/renderer/shared/components/Settings/AutomationTab.tsx +10 -60
  400. package/src/renderer/shared/components/Settings/AvatarCropModal.tsx +368 -0
  401. package/src/renderer/shared/components/Settings/GeneralTab.tsx +368 -113
  402. package/src/renderer/shared/components/Settings/MemoryTab.test.tsx +37 -0
  403. package/src/renderer/shared/components/Settings/MemoryTab.tsx +71 -31
  404. package/src/renderer/shared/components/Settings/NotificationsTab.test.tsx +15 -0
  405. package/src/renderer/shared/components/Settings/NotificationsTab.tsx +84 -0
  406. package/src/renderer/shared/components/Settings/PluginsTab.tsx +20 -12
  407. package/src/renderer/shared/components/Settings/ProfileTab.tsx +29 -5
  408. package/src/renderer/shared/components/Settings/SearchableModelCombobox.tsx +411 -0
  409. package/src/renderer/shared/components/Settings/ThemeTab.tsx +416 -165
  410. package/src/renderer/shared/components/SkillsView.tsx +41 -16
  411. package/src/renderer/shared/components/SlashChoicePanel.tsx +88 -0
  412. package/src/renderer/shared/components/SlashSuggestions.test.tsx +33 -0
  413. package/src/renderer/shared/components/SlashSuggestions.tsx +41 -12
  414. package/src/renderer/shared/components/SourcesBlock.tsx +55 -51
  415. package/src/renderer/shared/components/StockCard.tsx +58 -24
  416. package/src/renderer/shared/components/SubagentDagView.tsx +4 -4
  417. package/src/renderer/shared/components/TerminalDock.tsx +241 -0
  418. package/src/renderer/shared/components/ThinkingBlock.tsx +14 -8
  419. package/src/renderer/shared/components/ToolSurfacePage.test.tsx +32 -0
  420. package/src/renderer/shared/components/ToolSurfacePage.tsx +568 -0
  421. package/src/renderer/shared/components/ToolsPanelToggle.tsx +13 -0
  422. package/src/renderer/shared/components/UiFeatureCard.tsx +267 -0
  423. package/src/renderer/shared/components/UiGridCard.tsx +188 -0
  424. package/src/renderer/shared/components/UiMockupWidget.tsx +149 -0
  425. package/src/renderer/shared/components/VeoStudioPanel.tsx +22 -37
  426. package/src/renderer/shared/components/ViewedImages.tsx +36 -0
  427. package/src/renderer/shared/components/VirtualChatHistory.tsx +82 -0
  428. package/src/renderer/shared/components/VoicePill.css +85 -0
  429. package/src/renderer/shared/components/VoicePill.d.ts +12 -0
  430. package/src/renderer/shared/components/VoicePill.jsx +190 -0
  431. package/src/renderer/shared/components/VoicePill.test.tsx +22 -0
  432. package/src/renderer/shared/components/WeatherCard.tsx +3 -3
  433. package/src/renderer/shared/components/WorkspaceContextPopover.tsx +138 -0
  434. package/src/renderer/shared/components/WorkspacePaneResizer.tsx +92 -0
  435. package/src/renderer/shared/components/WorkspacePreviewActions.test.tsx +44 -0
  436. package/src/renderer/shared/components/WorkspacePreviewActions.tsx +19 -0
  437. package/src/renderer/shared/components/WorkspaceSelector.tsx +154 -0
  438. package/src/renderer/shared/components/background-terminals.css +292 -0
  439. package/src/renderer/shared/components/ui/README.md +52 -0
  440. package/src/renderer/shared/components/ui/button.tsx +37 -0
  441. package/src/renderer/shared/components/ui/demo.tsx +26 -0
  442. package/src/renderer/shared/components/ui/error-recovery.css +35 -0
  443. package/src/renderer/shared/components/ui/error-recovery.tsx +35 -0
  444. package/src/renderer/shared/components/ui/voice-powered-orb.css +6 -0
  445. package/src/renderer/shared/components/ui/voice-powered-orb.tsx +374 -0
  446. package/src/renderer/shared/components/workspace-selector.css +248 -0
  447. package/src/renderer/shared/constants/config.ts +57 -3
  448. package/src/renderer/shared/constants/models.ts +189 -2
  449. package/src/renderer/shared/constants/slashCommands.ts +1 -1
  450. package/src/renderer/shared/conversation/coordinator.test.ts +27 -0
  451. package/src/renderer/shared/conversation/coordinator.ts +82 -0
  452. package/src/renderer/shared/conversation/lifecycle.test.ts +362 -0
  453. package/src/renderer/shared/conversation/lifecycle.ts +418 -0
  454. package/src/renderer/shared/conversation/projectNavigation.test.ts +105 -0
  455. package/src/renderer/shared/conversation/projectNavigation.ts +39 -0
  456. package/src/renderer/shared/conversation/sourcesTransport.ts +27 -0
  457. package/src/renderer/shared/conversation/syncView.test.ts +13 -0
  458. package/src/renderer/shared/conversation/syncView.ts +6 -0
  459. package/src/renderer/shared/conversation/transport.test.ts +163 -0
  460. package/src/renderer/shared/conversation/transport.ts +159 -0
  461. package/src/renderer/shared/conversation/useConversationCoordinator.ts +64 -0
  462. package/src/renderer/shared/css/agent-observability.css +46 -15
  463. package/src/renderer/shared/css/auth-gate.css +114 -15
  464. package/src/renderer/shared/css/chat-ui-cards.css +495 -0
  465. package/src/renderer/shared/css/code-review.css +856 -0
  466. package/src/renderer/shared/css/code-sessions.css +479 -0
  467. package/src/renderer/shared/css/collapsed-paste.css +35 -0
  468. package/src/renderer/shared/css/effects.css +15 -0
  469. package/src/renderer/shared/css/error-notice.css +60 -0
  470. package/src/renderer/shared/css/file-changes.css +132 -0
  471. package/src/renderer/shared/css/image-studio.css +16 -16
  472. package/src/renderer/shared/css/library.css +476 -0
  473. package/src/renderer/shared/css/management-views.css +415 -27
  474. package/src/renderer/shared/css/mcp-results.css +11 -0
  475. package/src/renderer/shared/css/model-selector.css +543 -85
  476. package/src/renderer/shared/css/mods.css +77 -0
  477. package/src/renderer/shared/css/notification-notice.css +28 -0
  478. package/src/renderer/shared/css/session-sources-popover.css +9 -0
  479. package/src/renderer/shared/css/session-sources.css +23 -0
  480. package/src/renderer/shared/css/settings/agents.css +1 -1
  481. package/src/renderer/shared/css/settings/automation.css +13 -13
  482. package/src/renderer/shared/css/settings/general.css +526 -5
  483. package/src/renderer/shared/css/settings/memory.css +154 -0
  484. package/src/renderer/shared/css/settings/notifications.css +11 -0
  485. package/src/renderer/shared/css/settings/plugins.css +5 -5
  486. package/src/renderer/shared/css/settings/profile.css +331 -1
  487. package/src/renderer/shared/css/settings/theme.css +656 -3
  488. package/src/renderer/shared/css/slash-choice.css +95 -0
  489. package/src/renderer/shared/css/slash-suggestions.css +68 -0
  490. package/src/renderer/shared/css/sources-block.css +91 -0
  491. package/src/renderer/shared/css/thinking-status.css +46 -0
  492. package/src/renderer/shared/css/tools-panel.css +7 -0
  493. package/src/renderer/shared/css/ui-tailwind.css +19 -0
  494. package/src/renderer/shared/css/veo-studio.css +16 -15
  495. package/src/renderer/shared/css/viewed-images.css +15 -0
  496. package/src/renderer/shared/fonts.css +46 -0
  497. package/src/renderer/shared/fonts.ts +10 -37
  498. package/src/renderer/shared/lib/utils.ts +6 -0
  499. package/src/renderer/shared/library/controller.test.ts +61 -0
  500. package/src/renderer/shared/library/controller.ts +57 -0
  501. package/src/renderer/shared/library/transport.test.ts +26 -0
  502. package/src/renderer/shared/library/transport.ts +60 -0
  503. package/src/renderer/shared/library/useLibraryFile.ts +38 -0
  504. package/src/renderer/shared/mods.ts +58 -0
  505. package/src/renderer/shared/platform.test.ts +90 -0
  506. package/src/renderer/shared/platform.ts +219 -7
  507. package/src/renderer/shared/theme/themeManager.test.ts +43 -0
  508. package/src/renderer/shared/theme/themeManager.ts +157 -0
  509. package/src/renderer/shared/theme/themes.ts +116 -0
  510. package/src/renderer/shared/theme/tokens.css +318 -0
  511. package/src/renderer/shared/types.ts +137 -2
  512. package/src/renderer/shared/utils/agentActivity.test.ts +75 -0
  513. package/src/renderer/shared/utils/agentActivity.ts +168 -8
  514. package/src/renderer/shared/utils/approval.tsx +7 -0
  515. package/src/renderer/shared/utils/artifactBrowser.test.ts +80 -0
  516. package/src/renderer/shared/utils/artifactBrowser.ts +41 -0
  517. package/src/renderer/shared/utils/cardJson.test.ts +35 -0
  518. package/src/renderer/shared/utils/cardJson.ts +30 -0
  519. package/src/renderer/shared/utils/contextCompaction.test.tsx +48 -0
  520. package/src/renderer/shared/utils/contextCompaction.ts +21 -0
  521. package/src/renderer/shared/utils/effectVisibility.ts +9 -0
  522. package/src/renderer/shared/utils/fileIcons.ts +1 -1
  523. package/src/renderer/shared/utils/markdown.tsx +330 -81
  524. package/src/renderer/shared/utils/markdown.webImages.test.tsx +40 -0
  525. package/src/renderer/shared/utils/mcpResults.test.tsx +91 -0
  526. package/src/renderer/shared/utils/modViewport.ts +7 -0
  527. package/src/renderer/shared/utils/nativeRecordingSession.test.ts +61 -0
  528. package/src/renderer/shared/utils/nativeRecordingSession.ts +46 -0
  529. package/src/renderer/shared/utils/notificationSettings.test.ts +14 -0
  530. package/src/renderer/shared/utils/notificationSettings.ts +23 -0
  531. package/src/renderer/shared/utils/notifications.test.ts +51 -0
  532. package/src/renderer/shared/utils/notifications.ts +54 -0
  533. package/src/renderer/shared/utils/pastedText.test.ts +20 -0
  534. package/src/renderer/shared/utils/pastedText.ts +13 -0
  535. package/src/renderer/shared/utils/progressCache.test.ts +32 -0
  536. package/src/renderer/shared/utils/providers.ts +8 -3
  537. package/src/renderer/shared/utils/screenCapture.ts +43 -0
  538. package/src/renderer/shared/utils/sessionSources.test.ts +31 -0
  539. package/src/renderer/shared/utils/sessionSources.ts +34 -0
  540. package/src/renderer/shared/utils/slashCommandProcessor.ts +5 -2
  541. package/src/renderer/shared/utils/sourceAttachments.ts +28 -0
  542. package/src/renderer/shared/utils/speech.ts +51 -9
  543. package/src/renderer/shared/utils/syntaxHighlight.test.tsx +22 -0
  544. package/src/renderer/shared/utils/syntaxHighlight.tsx +26 -0
  545. package/src/renderer/shared/utils/ui.ts +4 -64
  546. package/src/renderer/shared/utils/useGeminiLiveVoice.ts +49 -5
  547. package/src/renderer/shared/utils/useLatestCallback.ts +9 -0
  548. package/src/renderer/shared/utils/useNativeVoiceInput.ts +80 -72
  549. package/src/renderer/shared/utils/useSessionSources.ts +33 -0
  550. package/src/renderer/shared/utils/viewedImages.ts +26 -0
  551. package/src/renderer/shared/utils/workspacePane.test.ts +33 -0
  552. package/src/renderer/shared/utils/workspacePane.ts +20 -0
  553. package/src/renderer/shared/utils/workspacePreview.test.ts +24 -0
  554. package/src/renderer/shared/utils/workspacePreview.ts +16 -0
  555. package/src/renderer/shared/utils/workspaceSnapshot.test.ts +49 -0
  556. package/src/renderer/shared/utils/workspaceSnapshot.ts +26 -0
  557. package/src/renderer/shared/utils/workspaces.ts +10 -0
  558. package/src/renderer/shared/workspaceUndo.ts +88 -0
  559. package/src/renderer/src/App.tsx +16 -1
  560. package/src/renderer/src/components/BrowserShell.tsx +108 -0
  561. package/src/renderer/src/components/BrowserSuggestionsPopup.tsx +91 -0
  562. package/src/renderer/src/components/LiveTranslateControls.tsx +65 -0
  563. package/src/renderer/src/components/MintDashboard.tsx +4 -2
  564. package/src/renderer/src/components/PicturesLibrary.tsx +2 -287
  565. package/src/renderer/src/components/ScreenPicker.css +227 -0
  566. package/src/renderer/src/components/ScreenPicker.tsx +312 -526
  567. package/src/renderer/src/components/SettingsWindow.tsx +48 -5
  568. package/src/renderer/src/components/SpotlightWindow.tsx +1 -0
  569. package/src/renderer/src/components/WidgetWindow.tsx +27 -3
  570. package/src/renderer/src/components/WorkspacePanel.tsx +269 -61
  571. package/src/renderer/src/components/browser-shell.css +185 -0
  572. package/src/renderer/src/components/browser-suggestions-popup.css +55 -0
  573. package/src/renderer/src/components/liveTranslateFrames.test.ts +44 -0
  574. package/src/renderer/src/components/liveTranslateFrames.ts +45 -0
  575. package/src/renderer/src/components/liveTranslateLanguage.ts +6 -0
  576. package/src/renderer/src/css/app-shell.css +400 -204
  577. package/src/renderer/src/css/chat.css +1666 -594
  578. package/src/renderer/src/css/dashboard.css +11 -0
  579. package/src/renderer/src/css/desktop-tools.css +928 -0
  580. package/src/renderer/src/css/misc.css +5 -60
  581. package/src/renderer/src/css/pictures.css +2 -407
  582. package/src/renderer/src/css/settings/base.css +394 -157
  583. package/src/renderer/src/css/sidebar-workspace.css +1072 -376
  584. package/src/renderer/src/css/spotlight.css +15 -26
  585. package/src/renderer/src/css/tool-surfaces.css +784 -0
  586. package/src/renderer/src/css/widget.css +36 -8
  587. package/src/renderer/src/env.d.ts +4 -9
  588. package/src/renderer/src/hooks/useProviderModels.ts +2 -9
  589. package/src/renderer/src/index.css +53 -46
  590. package/src/renderer/src/main.tsx +12 -0
  591. package/src/renderer/src/proactiveSuggestions.ts +29 -0
  592. package/src/renderer/src/tauri.ts +302 -339
  593. package/src/renderer/src/voiceInput.ts +2 -1
  594. package/src/renderer/src-web/App.tsx +40 -0
  595. package/src/renderer/src-web/components/MintDashboard.tsx +4 -2
  596. package/src/renderer/src-web/components/PicturesLibrary.tsx +2 -284
  597. package/src/renderer/src-web/components/PullToRefresh.tsx +107 -0
  598. package/src/renderer/src-web/components/SettingsWindow.tsx +36 -5
  599. package/src/renderer/src-web/css/app-shell.css +188 -207
  600. package/src/renderer/src-web/css/chat.css +1236 -507
  601. package/src/renderer/src-web/css/dashboard.css +11 -0
  602. package/src/renderer/src-web/css/misc.css +3 -55
  603. package/src/renderer/src-web/css/mobile.css +679 -0
  604. package/src/renderer/src-web/css/pictures.css +2 -415
  605. package/src/renderer/src-web/css/pull-to-refresh.css +54 -0
  606. package/src/renderer/src-web/css/settings/base.css +353 -134
  607. package/src/renderer/src-web/css/settings/mobile.css +320 -0
  608. package/src/renderer/src-web/css/sidebar-workspace.css +546 -187
  609. package/src/renderer/src-web/css/spotlight.css +9 -26
  610. package/src/renderer/src-web/css/widget.css +1 -6
  611. package/src/renderer/src-web/env.d.ts +4 -12
  612. package/src/renderer/src-web/hooks/useProviderModels.ts +2 -9
  613. package/src/renderer/src-web/index.css +53 -96
  614. package/src/renderer/src-web/main.tsx +12 -0
  615. package/src/renderer/src-web/proactiveSuggestions.ts +3 -0
  616. package/src/renderer/src-web/tauri.ts +309 -364
  617. package/src/renderer/tests/backgroundTerminals.browser.html +81 -0
  618. package/src/renderer/tests/chatPanelFixture.ts +23 -0
  619. package/src/renderer/tests/chatPerformance.browser.html +71 -0
  620. package/src/renderer/tests/cliSessions.browser.html +82 -0
  621. package/src/renderer/tests/collapsedPaste.browser.html +70 -0
  622. package/src/renderer/tests/composerMenus.browser.html +116 -0
  623. package/src/renderer/tests/contextCompaction.browser.html +17 -0
  624. package/src/renderer/tests/conversationLifecycle.browser.html +70 -0
  625. package/src/renderer/tests/effectsPerformance.browser.html +13 -0
  626. package/src/renderer/tests/errorRecovery.browser.html +21 -0
  627. package/src/renderer/tests/glideSelect.browser.html +71 -0
  628. package/src/renderer/tests/glideSelect.preview.html +27 -0
  629. package/src/renderer/tests/library.browser.html +1 -0
  630. package/src/renderer/tests/library.browser.tsx +78 -0
  631. package/src/renderer/tests/liveOrb.browser.html +49 -0
  632. package/src/renderer/tests/liveVoice.browser.html +29 -0
  633. package/src/renderer/tests/modInput.browser.html +22 -0
  634. package/src/renderer/tests/sessionSources.browser.html +1 -0
  635. package/src/renderer/tests/sessionSources.browser.tsx +107 -0
  636. package/src/renderer/tests/skills.browser.html +24 -0
  637. package/src/renderer/tests/toolsPanel.browser.html +1 -0
  638. package/src/renderer/tests/toolsPanel.browser.tsx +113 -0
  639. package/src/renderer/tests/viewedImages.browser.html +1 -0
  640. package/src/renderer/tests/viewedImages.browser.tsx +93 -0
  641. package/src/renderer/tests/voicePill.browser.html +80 -0
  642. package/src/renderer/tests/voicePill.preview.html +34 -0
  643. package/src/renderer/tests/webSources.browser.html +1 -0
  644. package/src/renderer/tests/webSources.browser.tsx +98 -0
  645. package/src/renderer/tests/workspaceUndo.browser.html +92 -0
  646. package/src-tauri/Cargo.toml +40 -0
  647. package/src-tauri/build.rs +3 -0
  648. package/src-tauri/src/app/lifecycle.rs +277 -0
  649. package/src-tauri/src/app/mod.rs +4 -0
  650. package/src-tauri/src/app/shortcuts.rs +40 -0
  651. package/src-tauri/src/app/tray.rs +52 -0
  652. package/src-tauri/src/background/events.rs +70 -0
  653. package/src-tauri/src/background/headless.rs +230 -0
  654. package/src-tauri/src/background/mod.rs +4 -0
  655. package/src-tauri/src/background/proactive.rs +262 -0
  656. package/src-tauri/src/commands/approvals.rs +20 -0
  657. package/src-tauri/src/commands/auth.rs +127 -0
  658. package/src-tauri/src/commands/conversation.rs +642 -0
  659. package/src-tauri/src/commands/integrations.rs +157 -0
  660. package/src-tauri/src/commands/media.rs +179 -0
  661. package/src-tauri/src/commands/mod.rs +11 -0
  662. package/src-tauri/src/commands/mods.rs +6 -0
  663. package/src-tauri/src/commands/settings.rs +141 -0
  664. package/src-tauri/src/commands/voice.rs +153 -0
  665. package/src-tauri/src/commands/workspace.rs +501 -0
  666. package/src-tauri/src/lib.rs +10 -0
  667. package/src-tauri/src/main.rs +3 -0
  668. package/src-tauri/src/native/actions.rs +206 -0
  669. package/src-tauri/src/native/browser.rs +252 -0
  670. package/src-tauri/src/native/capture.rs +695 -0
  671. package/src-tauri/src/native/discord_rpc.rs +99 -0
  672. package/src-tauri/src/native/integrations.rs +126 -0
  673. package/src-tauri/src/native/mod.rs +12 -0
  674. package/src-tauri/src/native/notifications.rs +51 -0
  675. package/src-tauri/src/native/plugins.rs +14 -0
  676. package/src-tauri/src/native/system.rs +250 -0
  677. package/src-tauri/src/native/terminal.rs +201 -0
  678. package/src-tauri/src/native/updater.rs +148 -0
  679. package/src-tauri/src/native/windows.rs +143 -0
  680. package/tsconfig.json +2 -0
  681. package/vite.config.ts +4 -1
  682. package/vite.config.web.ts +5 -0
  683. package/.cargo/config.toml +0 -13
  684. package/.claude/settings.local.json +0 -182
  685. package/.codex +0 -0
  686. package/CLAUDE.md +0 -102
  687. package/out/web/Live2DCubismCore.js +0 -9
  688. package/out/web/assets/MintDashboard-DWSqucgb.js +0 -57
  689. package/out/web/assets/SettingsWindow-DFM2aj5B.js +0 -2
  690. package/out/web/assets/chunk-CKBBP62Z-nr1uKPj9.js +0 -2
  691. package/out/web/assets/chunk-DSNCTWBM-Dtj8Rqsd.js +0 -2
  692. package/out/web/assets/chunk-DU6HZSFF-2tv5K1wT.js +0 -128
  693. package/out/web/assets/classDiagram-DTDB5LWJ-BdSFArgw.js +0 -1
  694. package/out/web/assets/classDiagram-v2-JRS7N3AN-BdSFArgw.js +0 -1
  695. package/out/web/assets/core-DImejIUG.js +0 -1
  696. package/out/web/assets/dist-js-BxuKEVWM.js +0 -1
  697. package/out/web/assets/event-BNl8Zahw.js +0 -1
  698. package/out/web/assets/fira-code-cyrillic-400-normal-UC0NFL4U.woff2 +0 -0
  699. package/out/web/assets/fira-code-cyrillic-400-normal-dc1q3VD7.woff +0 -0
  700. package/out/web/assets/fira-code-cyrillic-500-normal-Bu7VCL72.woff +0 -0
  701. package/out/web/assets/fira-code-cyrillic-500-normal-CX35h3Mg.woff2 +0 -0
  702. package/out/web/assets/fira-code-cyrillic-ext-400-normal-Buh61xzB.woff +0 -0
  703. package/out/web/assets/fira-code-cyrillic-ext-400-normal-txZ9Fk_1.woff2 +0 -0
  704. package/out/web/assets/fira-code-cyrillic-ext-500-normal-CYRspHgm.woff2 +0 -0
  705. package/out/web/assets/fira-code-cyrillic-ext-500-normal-CwtLmSFD.woff +0 -0
  706. package/out/web/assets/fira-code-greek-400-normal-B2Gh_Y8s.woff2 +0 -0
  707. package/out/web/assets/fira-code-greek-400-normal-DobhaxvF.woff +0 -0
  708. package/out/web/assets/fira-code-greek-500-normal-CVO0IRNt.woff2 +0 -0
  709. package/out/web/assets/fira-code-greek-500-normal-DEXIWiey.woff +0 -0
  710. package/out/web/assets/fira-code-greek-ext-400-normal-DR7mBgIM.woff2 +0 -0
  711. package/out/web/assets/fira-code-greek-ext-400-normal-DSPUheWg.woff +0 -0
  712. package/out/web/assets/fira-code-greek-ext-500-normal-BO3iq16n.woff2 +0 -0
  713. package/out/web/assets/fira-code-greek-ext-500-normal-CMiNLXER.woff +0 -0
  714. package/out/web/assets/fira-code-latin-ext-400-normal-DG73JjOf.woff +0 -0
  715. package/out/web/assets/fira-code-latin-ext-400-normal-KSMg0QLl.woff2 +0 -0
  716. package/out/web/assets/fira-code-latin-ext-500-normal-CaANqXjI.woff +0 -0
  717. package/out/web/assets/fira-code-latin-ext-500-normal-Crd9e_oI.woff2 +0 -0
  718. package/out/web/assets/flowDiagram-A5DVABFB-BpnHUSU7.js +0 -1
  719. package/out/web/assets/index-CVRg270z.css +0 -1
  720. package/out/web/assets/index-DxZQr9yD.js +0 -10
  721. package/out/web/assets/inter-cyrillic-400-normal-HOLc17fK.woff +0 -0
  722. package/out/web/assets/inter-cyrillic-400-normal-obahsSVq.woff2 +0 -0
  723. package/out/web/assets/inter-cyrillic-500-normal-BasfLYem.woff2 +0 -0
  724. package/out/web/assets/inter-cyrillic-500-normal-CxZf_p3X.woff +0 -0
  725. package/out/web/assets/inter-cyrillic-600-normal-4D_pXhcN.woff +0 -0
  726. package/out/web/assets/inter-cyrillic-600-normal-CWCymEST.woff2 +0 -0
  727. package/out/web/assets/inter-cyrillic-ext-400-normal-BQZuk6qB.woff2 +0 -0
  728. package/out/web/assets/inter-cyrillic-ext-400-normal-DQukG94-.woff +0 -0
  729. package/out/web/assets/inter-cyrillic-ext-500-normal-B0yAr1jD.woff2 +0 -0
  730. package/out/web/assets/inter-cyrillic-ext-500-normal-BmqWE9Dz.woff +0 -0
  731. package/out/web/assets/inter-cyrillic-ext-600-normal-Bcila6Z-.woff +0 -0
  732. package/out/web/assets/inter-cyrillic-ext-600-normal-Dfes3d0z.woff2 +0 -0
  733. package/out/web/assets/inter-greek-400-normal-B4URO6DV.woff2 +0 -0
  734. package/out/web/assets/inter-greek-400-normal-q2sYcFCs.woff +0 -0
  735. package/out/web/assets/inter-greek-500-normal-BIZE56-Y.woff2 +0 -0
  736. package/out/web/assets/inter-greek-500-normal-Xzm54t5V.woff +0 -0
  737. package/out/web/assets/inter-greek-600-normal-BZpKdvQh.woff +0 -0
  738. package/out/web/assets/inter-greek-600-normal-plRanbMR.woff2 +0 -0
  739. package/out/web/assets/inter-greek-ext-400-normal-DGGRlc-M.woff2 +0 -0
  740. package/out/web/assets/inter-greek-ext-400-normal-KugGGMne.woff +0 -0
  741. package/out/web/assets/inter-greek-ext-500-normal-2j5mBUwD.woff +0 -0
  742. package/out/web/assets/inter-greek-ext-500-normal-C4iEst2y.woff2 +0 -0
  743. package/out/web/assets/inter-greek-ext-600-normal-B8X0CLgF.woff +0 -0
  744. package/out/web/assets/inter-greek-ext-600-normal-DRtmH8MT.woff2 +0 -0
  745. package/out/web/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  746. package/out/web/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
  747. package/out/web/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
  748. package/out/web/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  749. package/out/web/assets/inter-latin-600-normal-CiBQ2DWP.woff +0 -0
  750. package/out/web/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
  751. package/out/web/assets/inter-latin-ext-400-normal-77YHD8bZ.woff +0 -0
  752. package/out/web/assets/inter-latin-ext-400-normal-C1nco2VV.woff2 +0 -0
  753. package/out/web/assets/inter-latin-ext-500-normal-BxGbmqWO.woff +0 -0
  754. package/out/web/assets/inter-latin-ext-500-normal-CV4jyFjo.woff2 +0 -0
  755. package/out/web/assets/inter-latin-ext-600-normal-CIVaiw4L.woff +0 -0
  756. package/out/web/assets/inter-latin-ext-600-normal-D2bJ5OIk.woff2 +0 -0
  757. package/out/web/assets/inter-vietnamese-400-normal-Bbgyi5SW.woff +0 -0
  758. package/out/web/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
  759. package/out/web/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
  760. package/out/web/assets/inter-vietnamese-500-normal-mJboJaSs.woff +0 -0
  761. package/out/web/assets/inter-vietnamese-600-normal-BuLX-rYi.woff +0 -0
  762. package/out/web/assets/inter-vietnamese-600-normal-Cc8MFFhd.woff2 +0 -0
  763. package/out/web/assets/kanit-latin-400-normal-BUlsQXH3.woff2 +0 -0
  764. package/out/web/assets/kanit-latin-400-normal-HVZWrfev.woff +0 -0
  765. package/out/web/assets/kanit-latin-500-normal-CX_4XcKi.woff2 +0 -0
  766. package/out/web/assets/kanit-latin-500-normal-qBha86O4.woff +0 -0
  767. package/out/web/assets/kanit-latin-600-normal-0lS78yAd.woff2 +0 -0
  768. package/out/web/assets/kanit-latin-600-normal-DlacpeTg.woff +0 -0
  769. package/out/web/assets/kanit-latin-ext-400-normal-B2xPf58u.woff2 +0 -0
  770. package/out/web/assets/kanit-latin-ext-400-normal-CHvNKHHD.woff +0 -0
  771. package/out/web/assets/kanit-latin-ext-500-normal-BFdWrG22.woff +0 -0
  772. package/out/web/assets/kanit-latin-ext-500-normal-EHs3suD6.woff2 +0 -0
  773. package/out/web/assets/kanit-latin-ext-600-normal-BBDzoLaj.woff +0 -0
  774. package/out/web/assets/kanit-latin-ext-600-normal-DAX3wtuq.woff2 +0 -0
  775. package/out/web/assets/kanit-thai-400-normal-D2nliXKa.woff +0 -0
  776. package/out/web/assets/kanit-thai-400-normal-D80Pglro.woff2 +0 -0
  777. package/out/web/assets/kanit-thai-500-normal-BB8gri04.woff2 +0 -0
  778. package/out/web/assets/kanit-thai-500-normal-Iy_w0a80.woff +0 -0
  779. package/out/web/assets/kanit-thai-600-normal-Bj6oiaDc.woff2 +0 -0
  780. package/out/web/assets/kanit-thai-600-normal-wbTlPO7I.woff +0 -0
  781. package/out/web/assets/kanit-vietnamese-400-normal-DRI8YWyb.woff2 +0 -0
  782. package/out/web/assets/kanit-vietnamese-400-normal-dow6Bnto.woff +0 -0
  783. package/out/web/assets/kanit-vietnamese-500-normal-BzTrpCM3.woff2 +0 -0
  784. package/out/web/assets/kanit-vietnamese-500-normal-T1ndT7MF.woff +0 -0
  785. package/out/web/assets/kanit-vietnamese-600-normal-Bi7fw3I4.woff2 +0 -0
  786. package/out/web/assets/kanit-vietnamese-600-normal-DXCRAa_8.woff +0 -0
  787. package/out/web/assets/mali-latin-400-normal-ByPcZ8Gx.woff +0 -0
  788. package/out/web/assets/mali-latin-400-normal-Cuc6Ykl8.woff2 +0 -0
  789. package/out/web/assets/mali-latin-500-normal-B01M-LP6.woff2 +0 -0
  790. package/out/web/assets/mali-latin-500-normal-Thgqw_9f.woff +0 -0
  791. package/out/web/assets/mali-latin-600-normal-B9TiUNpT.woff2 +0 -0
  792. package/out/web/assets/mali-latin-600-normal-CycpQCwU.woff +0 -0
  793. package/out/web/assets/mali-latin-ext-400-normal-DUVdJQO4.woff +0 -0
  794. package/out/web/assets/mali-latin-ext-400-normal-iCG1ALuJ.woff2 +0 -0
  795. package/out/web/assets/mali-latin-ext-500-normal-BfJE4UMZ.woff2 +0 -0
  796. package/out/web/assets/mali-latin-ext-500-normal-FoLEyOKS.woff +0 -0
  797. package/out/web/assets/mali-latin-ext-600-normal-BTvIfiCp.woff2 +0 -0
  798. package/out/web/assets/mali-latin-ext-600-normal-DAQcLVmD.woff +0 -0
  799. package/out/web/assets/mali-thai-400-normal-BO7A3bLZ.woff2 +0 -0
  800. package/out/web/assets/mali-thai-400-normal-CX9VrjTn.woff +0 -0
  801. package/out/web/assets/mali-thai-500-normal-Cph2qha9.woff +0 -0
  802. package/out/web/assets/mali-thai-500-normal-D89rMT77.woff2 +0 -0
  803. package/out/web/assets/mali-thai-600-normal-DPgXT6rZ.woff +0 -0
  804. package/out/web/assets/mali-thai-600-normal-DlTx3OsB.woff2 +0 -0
  805. package/out/web/assets/mali-vietnamese-400-normal-DUKxzXaz.woff2 +0 -0
  806. package/out/web/assets/mali-vietnamese-400-normal-gFDLvsOK.woff +0 -0
  807. package/out/web/assets/mali-vietnamese-500-normal--OY07q2c.woff +0 -0
  808. package/out/web/assets/mali-vietnamese-500-normal-KDrNRwfW.woff2 +0 -0
  809. package/out/web/assets/mali-vietnamese-600-normal-CtTMUU7T.woff +0 -0
  810. package/out/web/assets/mali-vietnamese-600-normal-DFlJr66u.woff2 +0 -0
  811. package/out/web/assets/mermaid.core-DYGGlqOf.js +0 -11
  812. package/out/web/assets/mitr-latin-400-normal-Cb18vPmZ.woff +0 -0
  813. package/out/web/assets/mitr-latin-400-normal-CwbkLQ4a.woff2 +0 -0
  814. package/out/web/assets/mitr-latin-500-normal-B4JOhzAi.woff +0 -0
  815. package/out/web/assets/mitr-latin-500-normal-BmClOow2.woff2 +0 -0
  816. package/out/web/assets/mitr-latin-ext-400-normal-B3CPG7Yo.woff2 +0 -0
  817. package/out/web/assets/mitr-latin-ext-400-normal-DTx65hiC.woff +0 -0
  818. package/out/web/assets/mitr-latin-ext-500-normal-B_Diajz1.woff2 +0 -0
  819. package/out/web/assets/mitr-latin-ext-500-normal-DYOsVaVT.woff +0 -0
  820. package/out/web/assets/mitr-thai-400-normal-CS4Do6aM.woff +0 -0
  821. package/out/web/assets/mitr-thai-400-normal-CXWaAdVj.woff2 +0 -0
  822. package/out/web/assets/mitr-thai-500-normal-CVdBrEVH.woff2 +0 -0
  823. package/out/web/assets/mitr-thai-500-normal-CW_B5D-i.woff +0 -0
  824. package/out/web/assets/mitr-vietnamese-400-normal-CPMGWyoC.woff2 +0 -0
  825. package/out/web/assets/mitr-vietnamese-400-normal-Z6XhIpdY.woff +0 -0
  826. package/out/web/assets/mitr-vietnamese-500-normal-CDrv0585.woff2 +0 -0
  827. package/out/web/assets/mitr-vietnamese-500-normal-CMQWyq-Z.woff +0 -0
  828. package/out/web/assets/noto-sans-thai-latin-400-normal-BaWBrqFP.woff2 +0 -0
  829. package/out/web/assets/noto-sans-thai-latin-400-normal-Dh_FJjOB.woff +0 -0
  830. package/out/web/assets/noto-sans-thai-latin-500-normal-BC04jsmm.woff +0 -0
  831. package/out/web/assets/noto-sans-thai-latin-500-normal-fyBKClF1.woff2 +0 -0
  832. package/out/web/assets/noto-sans-thai-latin-600-normal-CemcjnVR.woff2 +0 -0
  833. package/out/web/assets/noto-sans-thai-latin-600-normal-Dbc-dNO6.woff +0 -0
  834. package/out/web/assets/noto-sans-thai-latin-ext-400-normal-B-1H0YkH.woff +0 -0
  835. package/out/web/assets/noto-sans-thai-latin-ext-400-normal-nBP59pVw.woff2 +0 -0
  836. package/out/web/assets/noto-sans-thai-latin-ext-500-normal-B-ZWb8SZ.woff2 +0 -0
  837. package/out/web/assets/noto-sans-thai-latin-ext-500-normal-CrEHO7C8.woff +0 -0
  838. package/out/web/assets/noto-sans-thai-latin-ext-600-normal-PkMZo0xa.woff +0 -0
  839. package/out/web/assets/noto-sans-thai-latin-ext-600-normal-maHHBsez.woff2 +0 -0
  840. package/out/web/assets/noto-sans-thai-thai-400-normal-BEOmKAI1.woff2 +0 -0
  841. package/out/web/assets/noto-sans-thai-thai-400-normal-Dxb_unuU.woff +0 -0
  842. package/out/web/assets/noto-sans-thai-thai-500-normal-BOGXO2tw.woff +0 -0
  843. package/out/web/assets/noto-sans-thai-thai-500-normal-CU_X86GQ.woff2 +0 -0
  844. package/out/web/assets/noto-sans-thai-thai-600-normal-CmgB8_JK.woff +0 -0
  845. package/out/web/assets/noto-sans-thai-thai-600-normal-Cs73sVjl.woff2 +0 -0
  846. package/out/web/assets/oauthManager-DNiwM8Rn.js +0 -2
  847. package/out/web/assets/oauthManager-DuamS1Av.css +0 -1
  848. package/out/web/assets/outfit-latin-300-normal-AWLfuCom.woff +0 -0
  849. package/out/web/assets/outfit-latin-300-normal-CRYTwY6m.woff2 +0 -0
  850. package/out/web/assets/outfit-latin-400-normal-BGsTXAXT.woff2 +0 -0
  851. package/out/web/assets/outfit-latin-400-normal-DMwTpYkH.woff +0 -0
  852. package/out/web/assets/outfit-latin-500-normal-ClnHRwRh.woff +0 -0
  853. package/out/web/assets/outfit-latin-500-normal-DKnIMDSk.woff2 +0 -0
  854. package/out/web/assets/outfit-latin-600-normal-B7SfZ07L.woff2 +0 -0
  855. package/out/web/assets/outfit-latin-600-normal-BEfTtDA7.woff +0 -0
  856. package/out/web/assets/outfit-latin-ext-300-normal-BYS6Dpvq.woff2 +0 -0
  857. package/out/web/assets/outfit-latin-ext-300-normal-CMIMshEd.woff +0 -0
  858. package/out/web/assets/outfit-latin-ext-400-normal-5tcqmc2S.woff2 +0 -0
  859. package/out/web/assets/outfit-latin-ext-400-normal-DHm7mdGe.woff +0 -0
  860. package/out/web/assets/outfit-latin-ext-500-normal-DrCvqoFD.woff +0 -0
  861. package/out/web/assets/outfit-latin-ext-500-normal-zeox_O30.woff2 +0 -0
  862. package/out/web/assets/outfit-latin-ext-600-normal-B85nYjL1.woff2 +0 -0
  863. package/out/web/assets/outfit-latin-ext-600-normal-CWJcPgd7.woff +0 -0
  864. package/out/web/assets/preload-helper-D0uHx7FM.js +0 -1
  865. package/out/web/assets/prompt-latin-400-normal-BQ9zjSN8.woff2 +0 -0
  866. package/out/web/assets/prompt-latin-400-normal-CxU4ec_r.woff +0 -0
  867. package/out/web/assets/prompt-latin-500-normal-B1edBDQ9.woff +0 -0
  868. package/out/web/assets/prompt-latin-500-normal-CxzxEHZc.woff2 +0 -0
  869. package/out/web/assets/prompt-latin-600-normal-CSDDLorv.woff +0 -0
  870. package/out/web/assets/prompt-latin-600-normal-hKZWXsc1.woff2 +0 -0
  871. package/out/web/assets/prompt-latin-ext-400-normal-1pHbN9uy.woff +0 -0
  872. package/out/web/assets/prompt-latin-ext-400-normal-DdSafGZ9.woff2 +0 -0
  873. package/out/web/assets/prompt-latin-ext-500-normal--EZ1um7s.woff2 +0 -0
  874. package/out/web/assets/prompt-latin-ext-500-normal-D-lI1EVT.woff +0 -0
  875. package/out/web/assets/prompt-latin-ext-600-normal-C8b50x67.woff +0 -0
  876. package/out/web/assets/prompt-latin-ext-600-normal-Cg9L7iJU.woff2 +0 -0
  877. package/out/web/assets/prompt-thai-400-normal-BrkKv8cO.woff2 +0 -0
  878. package/out/web/assets/prompt-thai-400-normal-DJypnfr3.woff +0 -0
  879. package/out/web/assets/prompt-thai-500-normal-C18pDUoL.woff2 +0 -0
  880. package/out/web/assets/prompt-thai-500-normal-D7YNqUJD.woff +0 -0
  881. package/out/web/assets/prompt-thai-600-normal-CYPViXds.woff +0 -0
  882. package/out/web/assets/prompt-thai-600-normal-MrdfU7zR.woff2 +0 -0
  883. package/out/web/assets/prompt-vietnamese-400-normal-BCPzsgPT.woff2 +0 -0
  884. package/out/web/assets/prompt-vietnamese-400-normal-D4pLyeNK.woff +0 -0
  885. package/out/web/assets/prompt-vietnamese-500-normal-DmzxmPwa.woff2 +0 -0
  886. package/out/web/assets/prompt-vietnamese-500-normal-w_sS_j2F.woff +0 -0
  887. package/out/web/assets/prompt-vietnamese-600-normal-1dyohtNh.woff +0 -0
  888. package/out/web/assets/prompt-vietnamese-600-normal-7QWjJBsF.woff2 +0 -0
  889. package/out/web/assets/sarabun-latin-400-normal-DmguIS-7.woff +0 -0
  890. package/out/web/assets/sarabun-latin-400-normal-URPBxl-K.woff2 +0 -0
  891. package/out/web/assets/sarabun-latin-500-normal-BjUTcdxu.woff2 +0 -0
  892. package/out/web/assets/sarabun-latin-500-normal-CJexTAnl.woff +0 -0
  893. package/out/web/assets/sarabun-latin-600-normal-9FonlkKx.woff +0 -0
  894. package/out/web/assets/sarabun-latin-600-normal-DMD3TROr.woff2 +0 -0
  895. package/out/web/assets/sarabun-latin-ext-400-normal-BbP7GpLL.woff2 +0 -0
  896. package/out/web/assets/sarabun-latin-ext-400-normal-BsmTn0SS.woff +0 -0
  897. package/out/web/assets/sarabun-latin-ext-500-normal-Cot16Bd2.woff +0 -0
  898. package/out/web/assets/sarabun-latin-ext-500-normal-DE1LysqI.woff2 +0 -0
  899. package/out/web/assets/sarabun-latin-ext-600-normal-0tXu9x_i.woff +0 -0
  900. package/out/web/assets/sarabun-latin-ext-600-normal-BRxjKUQ6.woff2 +0 -0
  901. package/out/web/assets/sarabun-thai-400-normal-C2DaJlKK.woff2 +0 -0
  902. package/out/web/assets/sarabun-thai-400-normal-CH-UbWgg.woff +0 -0
  903. package/out/web/assets/sarabun-thai-500-normal-BVssjame.woff2 +0 -0
  904. package/out/web/assets/sarabun-thai-500-normal-C3iDLEzi.woff +0 -0
  905. package/out/web/assets/sarabun-thai-600-normal-3dIAQ-_s.woff2 +0 -0
  906. package/out/web/assets/sarabun-thai-600-normal-DWKeTe6a.woff +0 -0
  907. package/out/web/assets/sarabun-vietnamese-400-normal-DPfkSCMy.woff +0 -0
  908. package/out/web/assets/sarabun-vietnamese-400-normal-igdrzAGY.woff2 +0 -0
  909. package/out/web/assets/sarabun-vietnamese-500-normal-CpRVvGRU.woff +0 -0
  910. package/out/web/assets/sarabun-vietnamese-500-normal-Dpe7Br9m.woff2 +0 -0
  911. package/out/web/assets/sarabun-vietnamese-600-normal-BMbOgAW-.woff +0 -0
  912. package/out/web/assets/sarabun-vietnamese-600-normal-DkxrOlLB.woff2 +0 -0
  913. package/out/web/assets/stateDiagram-v2-4QOOHH4V-s6P9g2_b.js +0 -1
  914. package/out/web/assets/swimlanesDiagram-VK2B7HYN-CV9fOLrV.js +0 -8
  915. package/out/web/assets/tauri-CNrHQ2Gb.js +0 -3
  916. package/out/web/assets/window-DkIhgI7B.js +0 -1
  917. package/skills-lock.json +0 -41
  918. package/src/renderer/public/Live2DCubismCore.js +0 -9
  919. package/src/renderer/src/companionWidget.ts +0 -95
  920. package/src/renderer/src/components/Live2DStage.tsx +0 -389
  921. package/src/renderer/src/components/ModelPanel.tsx +0 -154
  922. package/src/renderer/src/css/model.css +0 -627
  923. package/src/renderer/src-web/companionWidget.ts +0 -37
  924. package/src/renderer/src-web/components/ModelPanel.tsx +0 -12
  925. package/src/renderer/src-web/css/model.css +0 -628
@@ -2,7 +2,7 @@ use std::io::{self, Write};
2
2
  use std::path::Path;
3
3
  use std::sync::{
4
4
  Arc, Mutex,
5
- atomic::{AtomicBool, Ordering},
5
+ atomic::{AtomicBool, AtomicUsize, Ordering},
6
6
  };
7
7
  use std::time::{Duration, Instant};
8
8
 
@@ -27,19 +27,21 @@ mod markdown_render;
27
27
  use approval_prompts::*;
28
28
  use diff_render::*;
29
29
  pub(crate) use live_status::*;
30
- use markdown_render::*;
31
-
32
- const RESET: &str = "\x1b[0m";
33
- const MINT: &str = "\x1b[32m";
34
- const GREEN: &str = "\x1b[32m";
35
- const RED: &str = "\x1b[31m";
36
- const BLUE: &str = "\x1b[38;2;78;201;216m";
37
- const CYAN: &str = "\x1b[38;2;56;189;248m";
38
- const DIM: &str = "\x1b[90m";
39
- const BRIGHT: &str = "\x1b[1;97m";
40
- const BOLD: &str = "\x1b[1m";
41
- const BG_ADD: &str = "\x1b[48;2;20;53;32m\x1b[38;2;166;226;46m";
42
- const BG_DEL: &str = "\x1b[48;2;61;23;23m\x1b[38;2;255;121;121m";
30
+ pub(crate) use markdown_render::*;
31
+
32
+ const RESET: &str = crate::terminal_theme::ANSI_RESET;
33
+ const MINT: &str = crate::terminal_theme::ANSI_ACCENT;
34
+ const GREEN: &str = crate::terminal_theme::ANSI_ACCENT;
35
+ const RED: &str = crate::terminal_theme::ANSI_ERROR;
36
+ const YELLOW: &str = crate::terminal_theme::ANSI_WARNING;
37
+ const BLUE: &str = crate::terminal_theme::ANSI_BLUE;
38
+ const CYAN: &str = crate::terminal_theme::ANSI_BLUE;
39
+ const DIM: &str = crate::terminal_theme::ANSI_MUTED;
40
+ const BRIGHT: &str = crate::terminal_theme::ANSI_BRIGHT_TEXT;
41
+ const WHITE: &str = crate::terminal_theme::ANSI_TEXT;
42
+ const BOLD: &str = crate::terminal_theme::ANSI_BOLD;
43
+ const BG_ADD: &str = crate::terminal_theme::ANSI_ADD;
44
+ const BG_DEL: &str = crate::terminal_theme::ANSI_DELETE;
43
45
 
44
46
  #[derive(Debug, Clone, Default)]
45
47
  pub struct AgentOptions {
@@ -58,6 +60,12 @@ pub struct AgentOptions {
58
60
  /// configured MCP server — set by an `@servername` mention in the typed
59
61
  /// query, mirroring the GUI composer's `@` mention picker.
60
62
  pub pinned_mcp_server: Option<String>,
63
+ /// Chat ID / session ID for this turn. Defaults to `CHAT_CLI_ID` if omitted.
64
+ pub chat_id: Option<String>,
65
+ pub image_name: Option<String>,
66
+ /// Full-screen UI event sink. When present, agent output never writes
67
+ /// directly to stdout and stdin remains owned by the TUI controller.
68
+ pub tui: Option<crate::interactive::TuiHandle>,
61
69
  }
62
70
 
63
71
  pub async fn run_code_agent(task: &str, root: &Path, config: &MintConfig) -> Result<AgentResult> {
@@ -327,6 +335,326 @@ fn save_plan_file(root: &Path, plan: &str) -> io::Result<std::path::PathBuf> {
327
335
  Ok(path)
328
336
  }
329
337
 
338
+ fn tui_persistable_approval(
339
+ tui: &crate::interactive::TuiHandle,
340
+ tool: &str,
341
+ subject: &str,
342
+ title: &str,
343
+ body: String,
344
+ root: &Path,
345
+ permission_rules: &mut Vec<PermissionRule>,
346
+ ) -> ApprovalOutcome {
347
+ if let Some(decision) = permission_decision_for(permission_rules, tool, subject, root) {
348
+ return match decision {
349
+ PermissionDecision::Allow => ApprovalOutcome::Approved,
350
+ PermissionDecision::Deny => ApprovalOutcome::Denied,
351
+ };
352
+ }
353
+ match tui.choose(
354
+ title,
355
+ body,
356
+ vec![
357
+ "Yes".into(),
358
+ "Yes, allow for this session".into(),
359
+ "No".into(),
360
+ ],
361
+ ) {
362
+ Some(0) => ApprovalOutcome::Approved,
363
+ Some(1) => {
364
+ permission_rules.push(PermissionRule {
365
+ tool: tool.to_owned(),
366
+ pattern: subject.to_owned(),
367
+ decision: PermissionDecision::Allow,
368
+ project_root: None,
369
+ });
370
+ ApprovalOutcome::Approved
371
+ }
372
+ _ => ApprovalOutcome::Denied,
373
+ }
374
+ }
375
+
376
+ fn tui_approval(
377
+ tui: &crate::interactive::TuiHandle,
378
+ approval: &AgentApproval,
379
+ root: &Path,
380
+ permission_rules: &mut Vec<PermissionRule>,
381
+ ) -> Result<ApprovalOutcome, String> {
382
+ let yes_no = |title: &str, body: String| match tui.choose(
383
+ title,
384
+ body,
385
+ vec!["Approve".into(), "Deny".into()],
386
+ ) {
387
+ Some(0) => ApprovalOutcome::Approved,
388
+ _ => ApprovalOutcome::Denied,
389
+ };
390
+ Ok(match approval {
391
+ AgentApproval::SkillWrite { path, diff, .. } => yes_no(
392
+ "Save skill?",
393
+ format!("Changes instructions used in future tasks.\nPath: {path}\n\n{diff}"),
394
+ ),
395
+ AgentApproval::WriteFile { path, diff, .. } => tui_persistable_approval(
396
+ tui,
397
+ "write_file",
398
+ path,
399
+ "Create file",
400
+ format!("Path: {path}\n\n{diff}"),
401
+ root,
402
+ permission_rules,
403
+ ),
404
+ AgentApproval::ApplyPatch { path, diff, .. } => tui_persistable_approval(
405
+ tui,
406
+ "apply_patch",
407
+ path,
408
+ "Update file",
409
+ format!("Path: {path}\n\n{diff}"),
410
+ root,
411
+ permission_rules,
412
+ ),
413
+ AgentApproval::RunShell {
414
+ command,
415
+ mode,
416
+ background,
417
+ } => tui_persistable_approval(
418
+ tui,
419
+ "run_shell",
420
+ command,
421
+ "Local shell command",
422
+ format!(
423
+ "Command: {command}\nMode: {mode}\nBackground: {}",
424
+ if *background { "yes" } else { "no" }
425
+ ),
426
+ root,
427
+ permission_rules,
428
+ ),
429
+ AgentApproval::NoteWrite { path, .. } => tui_persistable_approval(
430
+ tui,
431
+ "note_write",
432
+ path,
433
+ "Create note",
434
+ format!("Path: {path}"),
435
+ root,
436
+ permission_rules,
437
+ ),
438
+ AgentApproval::RunPlugin { name, instruction } => {
439
+ let subject = format!("{name}: {instruction}");
440
+ tui_persistable_approval(
441
+ tui,
442
+ "run_plugin",
443
+ &subject,
444
+ "Run plugin",
445
+ format!("Plugin: {name}\n\n{instruction}"),
446
+ root,
447
+ permission_rules,
448
+ )
449
+ }
450
+ AgentApproval::McpTool {
451
+ server,
452
+ tool,
453
+ arguments,
454
+ } => {
455
+ let body = format!("Server: {server}\nTool: {tool}\nArguments: {arguments}");
456
+ if tui.choose(
457
+ "MCP tool call",
458
+ body,
459
+ vec![format!("Allow all tools on {server}"), "No".into()],
460
+ ) == Some(0)
461
+ {
462
+ ApprovalOutcome::Intercepted(mint_core::MCP_ALLOW_ALL_SENTINEL.to_owned())
463
+ } else {
464
+ ApprovalOutcome::Denied
465
+ }
466
+ }
467
+ AgentApproval::UserApproval { title, prompt } => yes_no(title, prompt.to_owned()),
468
+ AgentApproval::EnterPlanMode { reason } => yes_no("Enter plan mode?", reason.to_owned()),
469
+ AgentApproval::ExitPlanMode { plan } => {
470
+ let outcome = yes_no("Review plan", plan.to_owned());
471
+ if outcome == ApprovalOutcome::Approved {
472
+ match save_plan_file(root, plan) {
473
+ Ok(path) => tui.push_notice(format!("Plan saved to {}", path.display())),
474
+ Err(error) => tui.push_notice(format!("Could not save plan: {error}")),
475
+ }
476
+ }
477
+ outcome
478
+ }
479
+ AgentApproval::AskUser {
480
+ question,
481
+ options,
482
+ header,
483
+ multi_select,
484
+ } => {
485
+ let title = header.as_deref().unwrap_or("Mint needs your input");
486
+ if options.is_empty() {
487
+ tui.prompt_text(title, question)
488
+ .map(ApprovalOutcome::Intercepted)
489
+ .unwrap_or(ApprovalOutcome::Denied)
490
+ } else {
491
+ let labels = options
492
+ .iter()
493
+ .map(|option| match &option.description {
494
+ Some(description) => format!("{} — {description}", option.label),
495
+ None => option.label.clone(),
496
+ })
497
+ .collect::<Vec<_>>();
498
+ if *multi_select {
499
+ let selected = tui.choose_many(title, question, labels);
500
+ let answer = selected
501
+ .into_iter()
502
+ .filter_map(|index| options.get(index))
503
+ .map(|option| option.label.as_str())
504
+ .collect::<Vec<_>>()
505
+ .join(", ");
506
+ if answer.is_empty() {
507
+ ApprovalOutcome::Denied
508
+ } else {
509
+ ApprovalOutcome::Intercepted(answer)
510
+ }
511
+ } else {
512
+ let choice = tui.choose(title, question, labels);
513
+ choice
514
+ .and_then(|choice| options.get(choice))
515
+ .map(|option| ApprovalOutcome::Intercepted(option.label.clone()))
516
+ .unwrap_or(ApprovalOutcome::Denied)
517
+ }
518
+ }
519
+ }
520
+ })
521
+ }
522
+
523
+ pub(crate) fn mcp_progress_notes(event: &AgentProgress) -> Option<Vec<String>> {
524
+ Some(match event {
525
+ AgentProgress::ToolDiscovery {
526
+ server,
527
+ tool,
528
+ message,
529
+ } => vec![format!("[MCP discovery {server}/{tool}] {message}")],
530
+ AgentProgress::DeviceState {
531
+ server,
532
+ tool,
533
+ update,
534
+ ..
535
+ } => vec![format!(
536
+ "[Device {server}/{tool}] {:?}: {} (target {}, actual {})",
537
+ update.state, update.message, update.target, update.actual
538
+ )],
539
+ AgentProgress::ToolProgress {
540
+ server,
541
+ tool,
542
+ update,
543
+ ..
544
+ } => {
545
+ let detail = update
546
+ .total
547
+ .map(|total| format!("{:.0}%", update.progress / total * 100.0))
548
+ .unwrap_or_else(|| format!("{}s", update.elapsed_secs));
549
+ vec![format!(
550
+ "[MCP {server}/{tool}] {detail} {}",
551
+ update.message.as_deref().unwrap_or_default()
552
+ )]
553
+ }
554
+ AgentProgress::ToolArtifacts {
555
+ artifacts,
556
+ warnings,
557
+ ..
558
+ } => {
559
+ let mut notes = artifacts
560
+ .iter()
561
+ .map(|artifact| {
562
+ let location = artifact.uri.clone().unwrap_or_else(|| {
563
+ mint_core::integrations::mcp_result::artifact_directory()
564
+ .unwrap_or_default()
565
+ .join(&artifact.id)
566
+ .display()
567
+ .to_string()
568
+ });
569
+ format!("[MCP {}] {}: {location}", artifact.kind, artifact.name)
570
+ })
571
+ .collect::<Vec<_>>();
572
+ notes.extend(
573
+ warnings
574
+ .iter()
575
+ .map(|warning| format!("[MCP warning] {warning}")),
576
+ );
577
+ notes
578
+ }
579
+ _ => return None,
580
+ })
581
+ }
582
+
583
+ pub(crate) fn publish_mcp_progress(
584
+ tui: Option<&crate::interactive::TuiHandle>,
585
+ event: &AgentProgress,
586
+ ) -> bool {
587
+ let Some(notes) = mcp_progress_notes(event) else {
588
+ return false;
589
+ };
590
+ for note in notes {
591
+ if let Some(tui) = tui {
592
+ tui.push_notice(note);
593
+ } else {
594
+ println!("{note}");
595
+ }
596
+ }
597
+ true
598
+ }
599
+
600
+ pub(crate) fn run_summary_lines(
601
+ summary: &mint_core::orchestration::RunTelemetrySummary,
602
+ ) -> Vec<String> {
603
+ let failed_tools: Vec<_> = summary
604
+ .tool_timeline
605
+ .iter()
606
+ .filter(|record| !record.success)
607
+ .collect();
608
+ let outcome = if !failed_tools.is_empty() {
609
+ format!(
610
+ "{YELLOW}⚠ Completed with {} failure{}{RESET}",
611
+ failed_tools.len(),
612
+ if failed_tools.len() == 1 { "" } else { "s" }
613
+ )
614
+ } else if summary.outcome == "ROLLED_BACK" {
615
+ format!("{YELLOW}↺ Rolled back{RESET}")
616
+ } else if summary.outcome == "FAILED" {
617
+ format!("{RED}✗ Failed{RESET}")
618
+ } else {
619
+ format!("{GREEN}✓ Completed{RESET}")
620
+ };
621
+ let file_count = summary.files_changed.len();
622
+ let mut lines = vec![format!(
623
+ " {outcome} {DIM}in {:.1}s · {} tool{} · {} file{} changed{RESET}",
624
+ summary.duration_secs,
625
+ summary.tool_calls_count,
626
+ if summary.tool_calls_count == 1 {
627
+ ""
628
+ } else {
629
+ "s"
630
+ },
631
+ file_count,
632
+ if file_count == 1 { "" } else { "s" },
633
+ )];
634
+
635
+ if file_count > 0 {
636
+ let mut names: Vec<String> = summary
637
+ .files_changed
638
+ .iter()
639
+ .take(6)
640
+ .map(|path| display_tool_target(path))
641
+ .collect();
642
+ if file_count > names.len() {
643
+ names.push(format!("+{} more", file_count - names.len()));
644
+ }
645
+ lines.push(format!(" {DIM}└ {}{RESET}", names.join(", ")));
646
+ }
647
+ for record in failed_tools.into_iter().take(3) {
648
+ let target = if record.target.is_empty() {
649
+ record.action.clone()
650
+ } else {
651
+ format!("{} [{}]", record.action, truncate_line(&record.target, 72))
652
+ };
653
+ lines.push(format!(" {RED}└ {target} failed{RESET}"));
654
+ }
655
+ lines
656
+ }
657
+
330
658
  pub async fn run_code_agent_with_options(
331
659
  task: &str,
332
660
  root: &Path,
@@ -337,20 +665,42 @@ pub async fn run_code_agent_with_options(
337
665
  queued_out: Arc<Mutex<Vec<String>>>,
338
666
  draft_out: Arc<Mutex<Option<String>>>,
339
667
  ) -> Result<AgentResult> {
668
+ let target_chat_id = options.chat_id.as_deref().unwrap_or(CHAT_CLI_ID);
669
+ let receipt = crate::image::prepare_attachments(
670
+ config,
671
+ target_chat_id,
672
+ task,
673
+ image_data_uri.as_deref(),
674
+ video_data_uri.as_deref(),
675
+ options.image_name.as_deref(),
676
+ )
677
+ .await?;
678
+ if receipt.is_some()
679
+ && let Some(tui) = &options.tui
680
+ {
681
+ tui.set_notice("Attachments saved to Library");
682
+ }
340
683
  let started_at = Instant::now();
684
+ crate::interactive::clear_last_thought();
685
+ if let Some(tui) = &options.tui {
686
+ tui.reset_thoughts();
687
+ }
341
688
  let thinking_verb = random_thinking_verb();
342
689
  let approval_active = Arc::new(AtomicBool::new(false));
343
690
  let agent_done = Arc::new(AtomicBool::new(false));
344
- // True between a tool starting and finishing — tells the periodic timer
691
+ // Number of tools between start and finish — tells the periodic timer
345
692
  // below not to overwrite the live status with "Thinking (Xs)…" text
346
- // while a tool (e.g. a shell command) is actually the thing in flight,
347
- // without stopping it from still re-rendering (so the bullets keep
348
- // pulsing) while that's happening.
349
- let tool_running = Arc::new(AtomicBool::new(false));
693
+ // while any tool (e.g. a shell command) is still in flight. A count is
694
+ // needed because parallel tools may finish at different times.
695
+ let tool_running = Arc::new(AtomicUsize::new(0));
350
696
  let live_status = Arc::new(Mutex::new(LiveStatus::default()));
351
697
  {
352
698
  use crossterm::tty::IsTty;
699
+ if let Ok(mut status) = live_status.lock() {
700
+ status.tui = options.tui.clone();
701
+ }
353
702
  if options.queueing
703
+ && options.tui.is_none()
354
704
  && !options.fast_mode
355
705
  && io::stdout().is_tty()
356
706
  && io::stdin().is_tty()
@@ -372,6 +722,11 @@ pub async fn run_code_agent_with_options(
372
722
 
373
723
  let approve_cb = |approval: &AgentApproval| -> Result<ApprovalOutcome, String> {
374
724
  approve_approval_active.store(true, Ordering::Relaxed);
725
+ if let Some(tui) = &options.tui {
726
+ let result = tui_approval(tui, approval, root, &mut permission_rules);
727
+ approve_approval_active.store(false, Ordering::Relaxed);
728
+ return result;
729
+ }
375
730
  // Synchronous, not polled: `wait_for_escape_interrupt` holds raw
376
731
  // mode continuously while the queueing box is live (see its docs),
377
732
  // and only reacts to `approval_active` on its next ~15ms tick. Every
@@ -393,6 +748,21 @@ pub async fn run_code_agent_with_options(
393
748
  let _guard = ApprovalGuard(Arc::clone(&approve_approval_active));
394
749
 
395
750
  match approval {
751
+ AgentApproval::SkillWrite { path, diff, .. } => {
752
+ let (additions, deletions) = diff_stats(diff);
753
+ print_diff_header("Save skill", path, additions, deletions);
754
+ print_colored_diff(diff);
755
+ Ok(
756
+ if confirm_pausing_interrupt(
757
+ "Save these instructions for future tasks?",
758
+ &approve_approval_active,
759
+ ) {
760
+ ApprovalOutcome::Approved
761
+ } else {
762
+ ApprovalOutcome::Denied
763
+ },
764
+ )
765
+ }
396
766
  AgentApproval::WriteFile { path, diff, .. } => confirm_with_persistence(
397
767
  "write_file",
398
768
  path,
@@ -600,19 +970,19 @@ pub async fn run_code_agent_with_options(
600
970
  if timer_agent_done.load(Ordering::Relaxed) {
601
971
  break;
602
972
  }
603
- if !timer_tool_running.load(Ordering::Relaxed) {
604
- status.thinking = Some(
605
- if let Some((attempt, max_attempts)) = status.waiting_for_network {
606
- waiting_for_network_label(attempt, max_attempts)
607
- } else {
608
- let context_suffix = context_pct_suffix(status.context_pct);
609
- let tokens_suffix = live_tokens_suffix(&status);
610
- format!(
611
- "{thinking_verb} ({}{tokens_suffix}{context_suffix} • Esc to interrupt)",
612
- format_elapsed(timer_started_at.elapsed())
613
- )
614
- },
615
- );
973
+ if timer_tool_running.load(Ordering::Relaxed) == 0 {
974
+ status.thinking = Some(if let Some(started) = status.compaction_started {
975
+ compaction_label(started.elapsed())
976
+ } else if let Some((attempt, max_attempts)) = status.waiting_for_network {
977
+ waiting_for_network_label(attempt, max_attempts)
978
+ } else {
979
+ let context_suffix = context_pct_suffix(status.context_pct);
980
+ let tokens_suffix = live_tokens_suffix(&status);
981
+ format!(
982
+ "{thinking_verb} ({}{tokens_suffix}{context_suffix} • Esc to interrupt)",
983
+ format_elapsed(timer_started_at.elapsed())
984
+ )
985
+ });
616
986
  }
617
987
  render_live_status(&mut status);
618
988
  }
@@ -634,7 +1004,15 @@ pub async fn run_code_agent_with_options(
634
1004
  mint_core::avatar_bridge::AvatarBridgeConfig::from_mint_config(config),
635
1005
  );
636
1006
  let progress_cb = |progress: AgentProgress| {
1007
+ if !options.fast_mode
1008
+ && let Some(tui) = &options.tui
1009
+ {
1010
+ tui.tool_progress(&progress);
1011
+ }
637
1012
  avatar_bridge.on_agent_progress(&progress);
1013
+ if publish_mcp_progress(options.tui.as_ref(), &progress) {
1014
+ return;
1015
+ }
638
1016
  match progress {
639
1017
  AgentProgress::Thinking {
640
1018
  elapsed_secs,
@@ -648,6 +1026,7 @@ pub async fn run_code_agent_with_options(
648
1026
  } => {
649
1027
  if !options.fast_mode
650
1028
  && !progress_approval_active.load(Ordering::Relaxed)
1029
+ && progress_tool_running.load(Ordering::Relaxed) == 0
651
1030
  && let Ok(mut status) = progress_live_status.lock()
652
1031
  {
653
1032
  status.context_pct = context_pct;
@@ -655,6 +1034,7 @@ pub async fn run_code_agent_with_options(
655
1034
  status.input_tokens = input_tokens;
656
1035
  status.generated_tokens = generated_tokens;
657
1036
  status.estimated_tokens = estimated_tokens;
1037
+ status.active_tool_started = None;
658
1038
  // Re-derive the animation rate from this real data point
659
1039
  // every time one arrives (cumulative generated tokens /
660
1040
  // elapsed turn time so far) — see
@@ -689,12 +1069,44 @@ pub async fn run_code_agent_with_options(
689
1069
  render_live_status(&mut status);
690
1070
  }
691
1071
  }
1072
+ AgentProgress::ContextCompaction {
1073
+ subagent,
1074
+ status: phase,
1075
+ message,
1076
+ } => {
1077
+ if !options.fast_mode
1078
+ && let Ok(mut status) = progress_live_status.lock()
1079
+ {
1080
+ update_context_compaction(
1081
+ &mut status,
1082
+ &phase,
1083
+ subagent.as_deref(),
1084
+ Instant::now(),
1085
+ );
1086
+ if phase == "started" {
1087
+ status.thinking = Some(compaction_label(Duration::ZERO));
1088
+ } else {
1089
+ print_timeline_note(&mut status, &message, started_at.elapsed(), None);
1090
+ status.context_pct = None;
1091
+ status.thinking = Some(if let Some(started) = status.compaction_started {
1092
+ compaction_label(started.elapsed())
1093
+ } else {
1094
+ format!(
1095
+ "{thinking_verb} ({} • Esc to interrupt)",
1096
+ format_elapsed(started_at.elapsed())
1097
+ )
1098
+ });
1099
+ }
1100
+ render_live_status(&mut status);
1101
+ }
1102
+ }
692
1103
  AgentProgress::WaitingForNetwork {
693
1104
  attempt,
694
1105
  max_attempts,
695
1106
  } => {
696
1107
  if !options.fast_mode
697
1108
  && !progress_approval_active.load(Ordering::Relaxed)
1109
+ && progress_tool_running.load(Ordering::Relaxed) == 0
698
1110
  && let Ok(mut status) = progress_live_status.lock()
699
1111
  {
700
1112
  status.waiting_for_network = Some((attempt, max_attempts));
@@ -707,8 +1119,48 @@ pub async fn run_code_agent_with_options(
707
1119
  && !progress_approval_active.load(Ordering::Relaxed)
708
1120
  && let Ok(mut status) = progress_live_status.lock()
709
1121
  {
710
- commit_activity_snapshot(&mut status);
711
- print_timeline_note(&mut status, &thought);
1122
+ commit_activity_snapshot_if_idle(
1123
+ &mut status,
1124
+ progress_tool_running.load(Ordering::Relaxed),
1125
+ );
1126
+ let elapsed = started_at.elapsed();
1127
+ print_timeline_note(&mut status, &thought, elapsed, None);
1128
+ status.thinking = None;
1129
+ status.waiting_for_network = None;
1130
+ render_live_status(&mut status);
1131
+ }
1132
+ }
1133
+ AgentProgress::ThinkingDelta {
1134
+ id,
1135
+ delta,
1136
+ elapsed_ms,
1137
+ } => {
1138
+ if !options.fast_mode {
1139
+ let elapsed = Duration::from_millis(elapsed_ms);
1140
+ let elapsed_str = crate::interactive::format_thought_elapsed(elapsed);
1141
+ crate::interactive::append_thought_delta(&id, &delta, &elapsed_str);
1142
+ if let Some(tui) = &options.tui {
1143
+ tui.append_thought_delta(&id, &delta, elapsed);
1144
+ }
1145
+ }
1146
+ }
1147
+ AgentProgress::ExtendedThinking {
1148
+ id,
1149
+ thought,
1150
+ elapsed_ms,
1151
+ } => {
1152
+ if !options.fast_mode
1153
+ && !progress_approval_active.load(Ordering::Relaxed)
1154
+ && let Ok(mut status) = progress_live_status.lock()
1155
+ {
1156
+ commit_activity_snapshot_if_idle(
1157
+ &mut status,
1158
+ progress_tool_running.load(Ordering::Relaxed),
1159
+ );
1160
+ let elapsed = elapsed_ms
1161
+ .map(Duration::from_millis)
1162
+ .unwrap_or_else(|| started_at.elapsed());
1163
+ print_extended_thinking(&mut status, &thought, elapsed, id.as_deref());
712
1164
  status.thinking = None;
713
1165
  status.waiting_for_network = None;
714
1166
  render_live_status(&mut status);
@@ -718,9 +1170,15 @@ pub async fn run_code_agent_with_options(
718
1170
  action,
719
1171
  input,
720
1172
  subagent,
1173
+ ..
721
1174
  } => {
722
- progress_tool_running.store(true, Ordering::Relaxed);
723
- if !options.fast_mode && !progress_approval_active.load(Ordering::Relaxed) {
1175
+ progress_tool_running.fetch_add(1, Ordering::Relaxed);
1176
+ if !options.fast_mode
1177
+ && (options.tui.is_some() || !progress_approval_active.load(Ordering::Relaxed))
1178
+ {
1179
+ if let Ok(mut status) = progress_live_status.lock() {
1180
+ status.active_tool_started = Some(std::time::Instant::now());
1181
+ }
724
1182
  if let Some(subagent_name) = subagent {
725
1183
  // A tool call happening *inside* a running subagent's own
726
1184
  // nested loop (tagged by `dispatch_one_subagent`) — render
@@ -755,13 +1213,26 @@ pub async fn run_code_agent_with_options(
755
1213
  return;
756
1214
  }
757
1215
  if action == "read_file"
758
- && let Some(path) = input.get("path").and_then(|v| v.as_str())
759
- && skill_name_for_read_path(path).is_some()
1216
+ && let Some(skill_name) = input
1217
+ .get("skill_name")
1218
+ .and_then(|v| v.as_str())
1219
+ .map(str::to_owned)
1220
+ .or_else(|| {
1221
+ input
1222
+ .get("path")
1223
+ .and_then(|v| v.as_str())
1224
+ .and_then(skill_name_for_read_path)
1225
+ })
760
1226
  {
761
- // The agent chose to read a skill file on its own initiative
762
- // (as opposed to the human typing `$skillname`). Skip the
763
- // generic explored-files grouping — ToolEnd below renders a
764
- // dedicated Skill(...) card for this instead.
1227
+ if let Ok(mut status) = progress_live_status.lock() {
1228
+ status.thinking = None;
1229
+ status.waiting_for_network = None;
1230
+ status.tasks.push(TaskEntry {
1231
+ label: format!("Reading skill: {skill_name}"),
1232
+ output: Vec::new(),
1233
+ });
1234
+ render_live_status(&mut status);
1235
+ }
765
1236
  return;
766
1237
  }
767
1238
  if let Some(label) = explored_action_label(&action, &input) {
@@ -793,9 +1264,22 @@ pub async fn run_code_agent_with_options(
793
1264
  input,
794
1265
  result,
795
1266
  subagent,
1267
+ ..
796
1268
  } => {
797
- progress_tool_running.store(false, Ordering::Relaxed);
798
- if !options.fast_mode && !progress_approval_active.load(Ordering::Relaxed) {
1269
+ let remaining = progress_tool_running
1270
+ .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |running| {
1271
+ Some(running.saturating_sub(1))
1272
+ })
1273
+ .unwrap_or(0)
1274
+ .saturating_sub(1);
1275
+ if !options.fast_mode
1276
+ && (options.tui.is_some() || !progress_approval_active.load(Ordering::Relaxed))
1277
+ {
1278
+ if remaining == 0
1279
+ && let Ok(mut status) = progress_live_status.lock()
1280
+ {
1281
+ status.active_tool_started = None;
1282
+ }
799
1283
  if subagent.is_some() {
800
1284
  // Nested call inside a subagent finished — the ToolStart
801
1285
  // line already shown covers it; only the command-output
@@ -854,13 +1338,29 @@ pub async fn run_code_agent_with_options(
854
1338
  }
855
1339
  render_live_status(&mut status);
856
1340
  } else if action == "read_file"
857
- && let Some(path) = input.get("path").and_then(|v| v.as_str())
858
- && let Some(skill_name) = skill_name_for_read_path(path)
1341
+ && let Some(skill_name) = input
1342
+ .get("skill_name")
1343
+ .and_then(|v| v.as_str())
1344
+ .map(str::to_owned)
1345
+ .or_else(|| {
1346
+ input
1347
+ .get("path")
1348
+ .and_then(|v| v.as_str())
1349
+ .and_then(skill_name_for_read_path)
1350
+ })
859
1351
  && let Ok(mut status) = progress_live_status.lock()
860
1352
  {
861
1353
  status.thinking = None;
862
1354
  status.waiting_for_network = None;
863
- status.tasks.push(skill_card(&skill_name));
1355
+ if let Some(task) = status
1356
+ .tasks
1357
+ .iter_mut()
1358
+ .rev()
1359
+ .find(|task| task.label == format!("Reading skill: {skill_name}"))
1360
+ {
1361
+ task.label = skill_read_label(&skill_name, &result);
1362
+ task.output = command_output_preview(&result);
1363
+ }
864
1364
  render_live_status(&mut status);
865
1365
  } else if action == "memory_recall" {
866
1366
  let skill_names = skill_names_from_memory_recall(&result);
@@ -870,7 +1370,10 @@ pub async fn run_code_agent_with_options(
870
1370
  status.thinking = None;
871
1371
  status.waiting_for_network = None;
872
1372
  for name in skill_names {
873
- status.tasks.push(skill_card(&name));
1373
+ status.tasks.push(TaskEntry {
1374
+ label: format!("Found skill: {name}"),
1375
+ output: Vec::new(),
1376
+ });
874
1377
  }
875
1378
  render_live_status(&mut status);
876
1379
  }
@@ -886,11 +1389,20 @@ pub async fn run_code_agent_with_options(
886
1389
  status.web_sources.extend(sources);
887
1390
  }
888
1391
  }
1392
+ AgentProgress::ToolDiscovery { .. }
1393
+ | AgentProgress::DeviceState { .. }
1394
+ | AgentProgress::ToolProgress { .. }
1395
+ | AgentProgress::ToolArtifacts { .. } => {}
889
1396
  AgentProgress::PlanUpdated { plan } => {
890
1397
  if let Ok(mut status) = progress_live_status.lock() {
891
1398
  status.thinking = None;
892
1399
  status.waiting_for_network = None;
893
- let mut card = format!("\x1b[1;36m┌─ Plan: {} \x1b[0m\n", plan.objective);
1400
+ let mut card = format!(
1401
+ "{}┌─ Plan: {} {}\n",
1402
+ crate::terminal_theme::ANSI_ACCENT_BOLD,
1403
+ plan.objective,
1404
+ crate::terminal_theme::ANSI_RESET
1405
+ );
894
1406
  for task in &plan.tasks {
895
1407
  let mark = match task.status.as_str() {
896
1408
  "completed" => "\x1b[32m[✓]\x1b[0m",
@@ -900,7 +1412,11 @@ pub async fn run_code_agent_with_options(
900
1412
  };
901
1413
  card.push_str(&format!("│ {} {}\n", mark, task.title));
902
1414
  }
903
- card.push_str("\x1b[1;36m└────────────────────────────────────────\x1b[0m");
1415
+ card.push_str(&format!(
1416
+ "{}└────────────────────────────────────────{}",
1417
+ crate::terminal_theme::ANSI_ACCENT_BOLD,
1418
+ crate::terminal_theme::ANSI_RESET
1419
+ ));
904
1420
  status.tasks.push(card.into());
905
1421
  render_live_status(&mut status);
906
1422
  }
@@ -909,190 +1425,51 @@ pub async fn run_code_agent_with_options(
909
1425
  if let Ok(mut status) = progress_live_status.lock() {
910
1426
  status.thinking = None;
911
1427
  status.waiting_for_network = None;
912
- let outcome_str = match summary.outcome.as_str() {
913
- "SUCCESS" => "\x1b[32m✓ Success\x1b[0m",
914
- "FAILED" => "\x1b[31m✗ Failure\x1b[0m",
915
- "ROLLED_BACK" => "\x1b[33m↺ Rolled Back\x1b[0m",
916
- _ => &summary.outcome,
917
- };
918
- let tokens_k = if summary.total_tokens >= 1000 {
919
- format!("{:.1}k", summary.total_tokens as f64 / 1000.0)
920
- } else {
921
- summary.total_tokens.to_string()
922
- };
923
- let created_count = summary.files_created.len();
924
- let modified_count = summary.files_changed.len().saturating_sub(created_count);
925
- let files_str = if created_count > 0 && modified_count > 0 {
926
- format!("{} created, {} modified", created_count, modified_count)
927
- } else if created_count > 0 {
928
- format!("{} created", created_count)
929
- } else {
930
- format!("{} modified", summary.files_changed.len())
931
- };
932
- let mut card = format!(
933
- "\x1b[1;36m┌─ Agent Run #{} ────────────────────────────\x1b[0m\n\
934
- │ Status: {}\n\
935
- │ Duration: {:.1}s\n\
936
- │ Tokens: {}\n\
937
- │ Tools: {} calls ({} retries)\n\
938
- │ Files: {}\n",
939
- summary.run_id,
940
- outcome_str,
941
- summary.duration_secs,
942
- tokens_k,
943
- summary.tool_calls_count,
944
- summary.retries_count,
945
- files_str,
946
- );
947
- if !summary.tool_timeline.is_empty() {
948
- card.push_str("│\n│ Tool calls timeline:\n");
949
- for rec in &summary.tool_timeline {
950
- let status_icon = if !rec.success {
951
- "\x1b[31m✗\x1b[0m"
952
- } else if rec.retried {
953
- "\x1b[33m↺\x1b[0m"
954
- } else {
955
- "\x1b[32m✓\x1b[0m"
956
- };
957
- let note = if !rec.success {
958
- " (failed)"
959
- } else if rec.retried {
960
- " (self-corrected)"
961
- } else {
962
- ""
963
- };
964
- let target_desc = if rec.target.is_empty() {
965
- String::new()
966
- } else {
967
- format!(" [{}]", rec.target)
968
- };
969
- card.push_str(&format!(
970
- "│ {:02}s {} {}{}{}\n",
971
- rec.step, status_icon, rec.action, target_desc, note
972
- ));
973
- }
974
- }
975
- card.push_str("\x1b[1;36m└────────────────────────────────────────\x1b[0m");
976
- status.tasks.push(card.into());
977
- render_live_status(&mut status);
978
- }
979
- }
980
- }
981
- };
982
-
983
- let chunk_live_status = Arc::clone(&live_status);
984
- let chunk_agent_done = Arc::clone(&agent_done);
985
- let on_chunk = |summary: String| {
986
- // Flip this *before* touching anything else — `agent_loop` still has
987
- // async work left (memory writes, etc.) after calling `on_chunk`, so
988
- // the real "done" store below (after `agent_loop.await`) fires too
989
- // late: the periodic status ticker keeps polling every 150ms in the
990
- // meantime and, seeing `agent_done` still false, unconditionally
991
- // resurrects `status.thinking` and re-renders — reconstructing a
992
- // fresh inline TUI viewport mid-print if that lands while the plain
993
- // `print!`s below are still spooling out a long answer (e.g. a big
994
- // markdown table), corrupting the terminal. Setting it here closes
995
- // that window instead of only the (much narrower) one the
996
- // `accepting_input` flag below covers.
997
- chunk_agent_done.store(true, Ordering::Relaxed);
998
- let mut committed_activity = false;
999
- if !options.fast_mode
1000
- && let Ok(mut status) = chunk_live_status.lock()
1001
- {
1002
- status.thinking = None;
1003
- status.waiting_for_network = None;
1004
- // Stop accepting keystrokes for the queueing box before it's torn
1005
- // down below — otherwise a keypress landing between this
1006
- // `clear_live_status` and the final answer's plain `println!`
1007
- // would resurrect the box (via `render_live_status`'s lazy
1008
- // `InlineTui::ensure`) at whatever the cursor's current position
1009
- // happens to be, underneath the answer that just printed.
1010
- status.accepting_input = false;
1011
- committed_activity = commit_activity_snapshot(&mut status);
1012
- clear_live_status(&mut status);
1013
- }
1014
- // Same reasoning as `approve_cb`: drop raw mode synchronously,
1015
- // right here, rather than leaving `wait_for_escape_interrupt` to
1016
- // notice `accepting_input` went false on its next tick — the prints
1017
- // below need cooked mode's `\n` → `\r\n` translation immediately.
1018
- let _ = crossterm::terminal::disable_raw_mode();
1019
- let formatted_summary = format_markdown_bold(&sanitize_latex(&summary));
1020
- // `commit_activity_snapshot` above already ended on a blank line when
1021
- // it committed anything (e.g. a tool-use activity block) — printing
1022
- // this leading "\n" unconditionally on top of that stacked two blank
1023
- // lines before every answer that followed tool use.
1024
- if committed_activity {
1025
- print!(" {MINT}Mint:{RESET} ");
1026
- } else {
1027
- print!("\n {MINT}Mint:{RESET} ");
1028
- }
1029
- avatar_bridge.on_talking(true);
1030
- render_live_summary(&formatted_summary);
1031
- avatar_bridge.on_talking(false);
1032
-
1033
- // Print web search sources if any were collected (grouped by domain)
1034
- if let Ok(mut status) = chunk_live_status.lock()
1035
- && !status.web_sources.is_empty()
1036
- {
1037
- println!();
1038
- println!(" {DIM}Sources:{RESET}");
1039
-
1040
- let mut domain_groups: Vec<(String, Vec<(String, String)>)> = Vec::new();
1041
- for (title, url) in status.web_sources.drain(..) {
1042
- let domain = extract_domain(&url);
1043
- if let Some(group) = domain_groups.iter_mut().find(|(d, _)| d == &domain) {
1044
- group.1.push((title, url));
1045
- } else {
1046
- domain_groups.push((domain, vec![(title, url)]));
1047
- }
1048
- }
1428
+ commit_activity_snapshot(&mut status);
1049
1429
 
1050
- for (i, (domain, items)) in domain_groups.iter().enumerate() {
1051
- let (first_title, first_url) = &items[0];
1052
- let extra_count = items.len() - 1;
1053
- if extra_count > 0 {
1054
- println!(
1055
- " {DIM}{}.{RESET} {BLUE}{}{RESET} {DIM}({}){RESET} {CYAN}[+{} extra]{RESET}",
1056
- i + 1,
1057
- first_title,
1058
- domain,
1059
- extra_count
1060
- );
1061
- } else {
1062
- println!(
1063
- " {DIM}{}.{RESET} {BLUE}{}{RESET} {DIM}({}){RESET}",
1064
- i + 1,
1065
- first_title,
1066
- domain
1067
- );
1430
+ let lines = run_summary_lines(&summary);
1431
+ insert_permanent_lines(&mut status, &lines);
1068
1432
  }
1069
- println!(" {DIM}{}{RESET}", first_url);
1070
1433
  }
1071
1434
  }
1072
-
1073
- println!();
1074
1435
  };
1075
1436
 
1437
+ // Providers may still stream internally, but the CLI deliberately waits
1438
+ // for AgentResult.summary so it can render one complete Markdown document.
1439
+ let on_chunk = |_summary: String| {};
1440
+
1076
1441
  let user_name = MemoryStore::open_default()
1077
1442
  .ok()
1078
1443
  .and_then(|memory| memory.get_profile("name").ok().flatten());
1079
1444
 
1080
- let agent_loop = orchestrate_agent_loop(
1081
- config,
1082
- task,
1083
- root,
1084
- image_data_uri,
1085
- None,
1086
- video_data_uri,
1087
- Some(CHAT_CLI_ID),
1088
- None,
1089
- user_name.as_deref(),
1090
- options.pinned_mcp_server.as_deref(),
1091
- options.fast_mode,
1092
- options.plan_mode,
1093
- approve_cb,
1094
- progress_cb,
1095
- on_chunk,
1445
+ let target_chat_id = options.chat_id.as_deref().unwrap_or(CHAT_CLI_ID);
1446
+
1447
+ let agent_loop = mint_core::with_turn_start_listener(
1448
+ target_chat_id.to_owned(),
1449
+ move |id| {
1450
+ if let Some(receipt) = &receipt
1451
+ && let Err(error) = receipt.bind(id)
1452
+ {
1453
+ eprintln!("Library reference: {error}")
1454
+ }
1455
+ },
1456
+ orchestrate_agent_loop(
1457
+ config,
1458
+ task,
1459
+ root,
1460
+ image_data_uri,
1461
+ None,
1462
+ video_data_uri,
1463
+ Some(target_chat_id),
1464
+ None,
1465
+ user_name.as_deref(),
1466
+ options.pinned_mcp_server.as_deref(),
1467
+ options.fast_mode,
1468
+ options.plan_mode,
1469
+ approve_cb,
1470
+ progress_cb,
1471
+ on_chunk,
1472
+ ),
1096
1473
  );
1097
1474
  let res = tokio::select! {
1098
1475
  res = agent_loop => res,
@@ -1111,51 +1488,53 @@ pub async fn run_code_agent_with_options(
1111
1488
  status.thinking = None;
1112
1489
  status.waiting_for_network = None;
1113
1490
  status.accepting_input = false;
1491
+ commit_activity_snapshot(&mut status);
1114
1492
  if let Ok(mut out) = queued_out.lock() {
1115
- *out = status.queued.clone();
1493
+ *out = options
1494
+ .tui
1495
+ .as_ref()
1496
+ .map(|tui| tui.take_queued())
1497
+ .unwrap_or_else(|| status.queued.clone());
1116
1498
  }
1117
1499
  if let Ok(mut out) = draft_out.lock() {
1118
- *out = if status.draft.is_empty() {
1119
- None
1120
- } else {
1121
- Some(status.draft.iter().collect())
1122
- };
1123
- }
1124
- if res.is_err() {
1125
- commit_activity_snapshot(&mut status);
1500
+ *out = options
1501
+ .tui
1502
+ .as_ref()
1503
+ .and_then(|tui| tui.draft())
1504
+ .or_else(|| (!status.draft.is_empty()).then(|| status.draft.iter().collect()));
1126
1505
  }
1127
1506
  clear_live_status(&mut status);
1128
1507
  }
1129
- let res = res.map_err(|e| anyhow!("{}", e))?;
1130
-
1131
- if should_show_verification(&res.verification) {
1132
- println!(" Verification: {}", res.verification);
1508
+ let mut res = res.map_err(|e| anyhow!("{}", e))?;
1509
+ if let Ok(status) = live_status.lock() {
1510
+ if res.input_tokens == 0 && status.input_tokens > 0 {
1511
+ res.input_tokens = status.input_tokens;
1512
+ }
1513
+ if res.generated_tokens == 0 && status.generated_tokens > 0 {
1514
+ res.generated_tokens = status.generated_tokens;
1515
+ }
1133
1516
  }
1134
- let badge_plain = if let Some(fb_provider) = &res.fallback {
1517
+
1518
+ let badge_plain = if let Some(orig_provider) = &res.fallback {
1519
+ let reason_suffix = if let Some(reason) = &res.fallback_reason {
1520
+ format!(" ({reason})")
1521
+ } else {
1522
+ String::new()
1523
+ };
1135
1524
  format!(
1136
- "{} • {} → fallback: {} • {}",
1137
- config.ai_provider,
1138
- crate::active_model(&config.ai_provider, config),
1139
- fb_provider,
1525
+ "{} • {}{} → fallback: {} • {}",
1526
+ orig_provider,
1527
+ crate::active_model(orig_provider, config),
1528
+ reason_suffix,
1529
+ res.provider,
1140
1530
  res.model
1141
1531
  )
1142
1532
  } else {
1143
1533
  format!("{} • {}", res.provider, res.model)
1144
1534
  };
1145
1535
 
1146
- // "─ Worked for {elapsed} • {provider} • {model}" as one *labeled*
1147
- // divider — filled out with more "─" to the same width the box's own
1148
- // two divider lines use — rather than the provider/model badge and the
1149
- // elapsed-time label as two separate short lines followed by a third,
1150
- // unlabeled full-width divider directly under them. The three used to
1151
- // look like unrelated elements stacked on top of each other; folding
1152
- // both labels into one rule reads as a single line doing all three
1153
- // jobs, matching the box below it.
1154
1536
  let (tw, _) = markdown::terminal_size_or_default();
1155
- let width = tw as usize;
1156
- // `↑` context stays dim with the rest of the footer; `↓` generated drops
1157
- // out of DIM for its segment so the "what the model actually produced"
1158
- // number reads a touch stronger than the divider around it.
1537
+ let width = (tw as usize).saturating_sub(6).max(40);
1159
1538
  let tokens_suffix = if res.input_tokens > 0 || res.generated_tokens > 0 {
1160
1539
  format!(
1161
1540
  " • ↑ {} · {RESET}↓ {}{DIM}",
@@ -1169,11 +1548,77 @@ pub async fn run_code_agent_with_options(
1169
1548
  "─ Worked for {}{tokens_suffix} • {badge_plain}",
1170
1549
  format_elapsed(started_at.elapsed())
1171
1550
  );
1172
- // Count only visible columns for the fill — `tokens_suffix` carries ANSI
1173
- // codes that don't occupy screen width.
1174
1551
  let label_width = strip_ansi_escapes(&label).chars().count();
1175
- let fill_len = width.saturating_sub(2).saturating_sub(label_width + 1);
1176
- println!(" {DIM}{label} {}{RESET}", "─".repeat(fill_len));
1552
+ let fill_len = width.saturating_sub(label_width + 1);
1553
+ let worked_line = format!("{DIM}{label} {}{RESET}", "─".repeat(fill_len));
1554
+
1555
+ if let Some(tui) = &options.tui {
1556
+ tui.push_assistant(res.summary.clone());
1557
+ if let Ok(mut status) = live_status.lock()
1558
+ && !status.web_sources.is_empty()
1559
+ {
1560
+ let sources = status
1561
+ .web_sources
1562
+ .drain(..)
1563
+ .enumerate()
1564
+ .map(|(index, (title, url))| format!("{}. {title}\n {url}", index + 1))
1565
+ .collect::<Vec<_>>()
1566
+ .join("\n");
1567
+ tui.push_notice(format!("Sources:\n{sources}"));
1568
+ }
1569
+ tui.push_notice(worked_line);
1570
+ avatar_bridge.on_talking(false);
1571
+ return Ok(res);
1572
+ }
1573
+
1574
+ let formatted_summary = format_markdown_bold(&sanitize_latex(&res.summary));
1575
+ print!("\n {MINT}Mint:{RESET} ");
1576
+ avatar_bridge.on_talking(true);
1577
+ render_live_summary(&formatted_summary);
1578
+ avatar_bridge.on_talking(false);
1579
+ println!();
1580
+
1581
+ // Print web search sources once after the streamed answer is complete.
1582
+ if let Ok(mut status) = live_status.lock()
1583
+ && !status.web_sources.is_empty()
1584
+ {
1585
+ println!(" {DIM}Sources:{RESET}");
1586
+
1587
+ let mut domain_groups: Vec<(String, Vec<(String, String)>)> = Vec::new();
1588
+ for (title, url) in status.web_sources.drain(..) {
1589
+ let domain = extract_domain(&url);
1590
+ if let Some(group) = domain_groups.iter_mut().find(|(d, _)| d == &domain) {
1591
+ group.1.push((title, url));
1592
+ } else {
1593
+ domain_groups.push((domain, vec![(title, url)]));
1594
+ }
1595
+ }
1596
+
1597
+ for (i, (domain, items)) in domain_groups.iter().enumerate() {
1598
+ let (first_title, first_url) = &items[0];
1599
+ let extra_count = items.len() - 1;
1600
+ if extra_count > 0 {
1601
+ println!(
1602
+ " {DIM}{}.{RESET} {BLUE}{}{RESET} {DIM}({}){RESET} {CYAN}[+{} extra]{RESET}",
1603
+ i + 1,
1604
+ first_title,
1605
+ domain,
1606
+ extra_count
1607
+ );
1608
+ } else {
1609
+ println!(
1610
+ " {DIM}{}.{RESET} {BLUE}{}{RESET} {DIM}({}){RESET}",
1611
+ i + 1,
1612
+ first_title,
1613
+ domain
1614
+ );
1615
+ }
1616
+ println!(" {DIM}{}{RESET}", first_url);
1617
+ }
1618
+ println!();
1619
+ }
1620
+
1621
+ println!(" {worked_line}");
1177
1622
 
1178
1623
  Ok(res)
1179
1624
  }
@@ -1364,6 +1809,26 @@ mod command_output_preview_tests {
1364
1809
  mod skill_card_tests {
1365
1810
  use super::*;
1366
1811
 
1812
+ #[test]
1813
+ fn skill_labels_distinguish_full_load_failure_and_preview() {
1814
+ assert_eq!(
1815
+ skill_read_label("review", "[Loaded skill: review]\nbody"),
1816
+ "Loaded skill: review"
1817
+ );
1818
+ assert_eq!(
1819
+ skill_read_label("review", "Error: denied"),
1820
+ "Failed to read skill: review"
1821
+ );
1822
+ assert_eq!(
1823
+ skill_read_label("review", "Blocked by hook: denied"),
1824
+ "Failed to read skill: review"
1825
+ );
1826
+ assert_eq!(
1827
+ skill_read_label("review", "1 | header"),
1828
+ "Read skill preview: review"
1829
+ );
1830
+ }
1831
+
1367
1832
  #[test]
1368
1833
  fn recognizes_workspace_skill_paths() {
1369
1834
  assert_eq!(