@pheem49/mint 1.14.0 → 1.15.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 (585) hide show
  1. package/CLAUDE.md +1 -1
  2. package/Cargo.lock +291 -11
  3. package/Cargo.toml +1 -1
  4. package/README.md +71 -9
  5. package/ROADMAP.md +30 -0
  6. package/Release_Note.md +579 -465
  7. package/crates/mint-cli/Cargo.toml +3 -1
  8. package/crates/mint-cli/src/agent/approval_prompts.rs +16 -3
  9. package/crates/mint-cli/src/agent/live_status.rs +367 -118
  10. package/crates/mint-cli/src/agent/markdown_render.rs +601 -61
  11. package/crates/mint-cli/src/agent.rs +452 -215
  12. package/crates/mint-cli/src/commands/agent.rs +16 -21
  13. package/crates/mint-cli/src/commands/eval.rs +9 -5
  14. package/crates/mint-cli/src/commands/git.rs +204 -0
  15. package/crates/mint-cli/src/commands/integrations.rs +28 -0
  16. package/crates/mint-cli/src/commands/knowledge.rs +1 -0
  17. package/crates/mint-cli/src/commands/mod.rs +37 -2
  18. package/crates/mint-cli/src/commands/tailnet_web.rs +235 -0
  19. package/crates/mint-cli/src/image.rs +26 -3
  20. package/crates/mint-cli/src/interactive/chat_tui.rs +4742 -0
  21. package/crates/mint-cli/src/interactive/command_ui.rs +477 -0
  22. package/crates/mint-cli/src/interactive/format.rs +8 -0
  23. package/crates/mint-cli/src/interactive/input_box.rs +38 -2
  24. package/crates/mint-cli/src/interactive/picker.rs +180 -37
  25. package/crates/mint-cli/src/interactive/resume_picker.rs +686 -0
  26. package/crates/mint-cli/src/interactive/slash_commands.rs +868 -450
  27. package/crates/mint-cli/src/interactive/thought_viewer.rs +286 -0
  28. package/crates/mint-cli/src/interactive.rs +400 -136
  29. package/crates/mint-cli/src/main.rs +84 -23
  30. package/crates/mint-cli/src/markdown.rs +12 -5
  31. package/crates/mint-cli/src/onboard.rs +32 -30
  32. package/crates/mint-cli/src/plugins_cli.rs +8 -5
  33. package/crates/mint-cli/src/setup.rs +10 -8
  34. package/crates/mint-cli/src/terminal_theme.rs +187 -0
  35. package/crates/mint-cli/src/updater.rs +56 -21
  36. package/crates/mint-core/src/agent/agent_loop.rs +1 -0
  37. package/crates/mint-core/src/agent/chat.rs +843 -177
  38. package/crates/mint-core/src/agent/code_tools.rs +83 -2
  39. package/crates/mint-core/src/agent/memory.rs +658 -20
  40. package/crates/mint-core/src/agent/skills.rs +1 -1
  41. package/crates/mint-core/src/api_server/routes/chat.rs +31 -5
  42. package/crates/mint-core/src/api_server/routes/linked_folders.rs +118 -3
  43. package/crates/mint-core/src/api_server/routes/misc.rs +10 -14
  44. package/crates/mint-core/src/api_server/routes/sessions.rs +44 -0
  45. package/crates/mint-core/src/api_server.rs +22 -3
  46. package/crates/mint-core/src/avatar_bridge.rs +2 -0
  47. package/crates/mint-core/src/browser/cdp.rs +74 -83
  48. package/crates/mint-core/src/browser/evidence.rs +260 -0
  49. package/crates/mint-core/src/browser/input.rs +1 -1
  50. package/crates/mint-core/src/browser/interact.rs +98 -124
  51. package/crates/mint-core/src/browser/lifecycle.rs +75 -4
  52. package/crates/mint-core/src/browser/mod.rs +16 -2
  53. package/crates/mint-core/src/browser/navigate.rs +27 -19
  54. package/crates/mint-core/src/browser/observe.js +40 -0
  55. package/crates/mint-core/src/browser/session.rs +1558 -0
  56. package/crates/mint-core/src/git/branches.rs +348 -0
  57. package/crates/mint-core/src/git/checkpoint.rs +40 -0
  58. package/crates/mint-core/src/git/diff.rs +206 -0
  59. package/crates/mint-core/src/git/mod.rs +10 -2
  60. package/crates/mint-core/src/integrations/channels.rs +1 -0
  61. package/crates/mint-core/src/lib.rs +22 -14
  62. package/crates/mint-core/src/live_sync.rs +28 -9
  63. package/crates/mint-core/src/media/auto_shorts.rs +1 -0
  64. package/crates/mint-core/src/media/gemini_live.rs +12 -1
  65. package/crates/mint-core/src/media/mic_transcribe.rs +1 -0
  66. package/crates/mint-core/src/media/subtitle.rs +1 -0
  67. package/crates/mint-core/src/orchestration/context_render.rs +1 -0
  68. package/crates/mint-core/src/orchestration/memory_skill.rs +6 -1
  69. package/crates/mint-core/src/orchestration/mod.rs +1024 -271
  70. package/crates/mint-core/src/orchestration/tools/browser.rs +16 -139
  71. package/crates/mint-core/src/orchestration/tools/misc.rs +2 -1
  72. package/crates/mint-core/src/orchestration/tools/web.rs +1 -1
  73. package/crates/mint-core/src/prompts/agent.rs +58 -29
  74. package/crates/mint-core/src/prompts/chat.rs +1 -1
  75. package/crates/mint-core/src/prompts/persona.rs +1 -1
  76. package/crates/mint-core/src/prompts/tool_catalog.rs +93 -25
  77. package/crates/mint-core/src/search/linked_folders/index.rs +732 -0
  78. package/crates/mint-core/src/search/linked_folders.rs +391 -130
  79. package/crates/mint-core/src/slash/mod.rs +470 -22
  80. package/crates/mint-core/src/slash/model_fetcher.rs +12 -3
  81. package/crates/mint-core/src/slash/models.rs +66 -10
  82. package/crates/mint-core/src/system/config.rs +230 -0
  83. package/crates/mint-core/src/system/workspace.rs +228 -0
  84. package/crates/mint-core/src/system.rs +1 -0
  85. package/crates/mint-core/tests/memory_persistence.rs +39 -0
  86. package/mint-presentation-demo.mp4 +0 -0
  87. package/out/web/assets/CliSessionsView-BxUVWEEL.js +1 -0
  88. package/out/web/assets/CliSessionsView-CBDTXuQv.css +1 -0
  89. package/out/web/assets/CodeReviewPage-DkMgfcos.css +1 -0
  90. package/out/web/assets/CodeReviewPage-jKlmLJwT.js +3 -0
  91. package/out/web/assets/CommandPalette-DnwPA5hy.js +1 -0
  92. package/out/web/assets/ImageStudioPanel-BR1XFwhR.js +1 -0
  93. package/out/web/assets/ImageStudioPanel-D0lnhQV5.css +1 -0
  94. package/out/web/assets/LinkedFoldersView-bi-CWQ-I.js +1 -0
  95. package/out/web/assets/McpRegistryPicker-D5tEFnyq.js +1 -0
  96. package/out/web/assets/McpServersView-BGG1dhFM.js +1 -0
  97. package/out/web/assets/MintDashboard-BIglDEWX.js +20 -0
  98. package/out/web/assets/MintDashboard-DSMywSgs.css +1 -0
  99. package/out/web/assets/ModelPanel-CbJ1PFoZ.js +1 -0
  100. package/out/web/assets/PicturesLibrary-CQP0fLP1.css +1 -0
  101. package/out/web/assets/PicturesLibrary-DoYN7T1p.js +1 -0
  102. package/out/web/assets/PluginsView-CU1HWXGk.js +1 -0
  103. package/out/web/assets/ScheduledTasksView-Bnl36y2N.js +1 -0
  104. package/out/web/assets/SettingsWindow-DhWLAn9T.css +1 -0
  105. package/out/web/assets/SettingsWindow-Dw8L01pw.js +2 -0
  106. package/out/web/assets/SkillsView-cnl8aY5p.js +2 -0
  107. package/out/web/assets/ToolSurfacePage-CgsQw6l5.css +1 -0
  108. package/out/web/assets/ToolSurfacePage-Cz2VJAPZ.js +37 -0
  109. package/out/web/assets/VeoStudioPanel-D4JnERWR.js +4 -0
  110. package/out/web/assets/VeoStudioPanel-DOj7_WR3.css +1 -0
  111. package/out/web/assets/WorkspacePanel-CbJ1PFoZ.js +1 -0
  112. package/out/web/assets/{abnfDiagram-VCTEODGH-DAOBA7ZG.js → abnfDiagram-VCTEODGH-ByMyfanq.js} +1 -1
  113. package/out/web/assets/{architecture-7GRP2DOG-CgSwQOPQ.js → architecture-7GRP2DOG-CLq2kEOB.js} +1 -1
  114. package/out/web/assets/{architectureDiagram-5GKGNRK7-CYp3yupP.js → architectureDiagram-5GKGNRK7-6PoVSmNG.js} +1 -1
  115. package/out/web/assets/{blockDiagram-NRAW4CY4-CyWybDWr.js → blockDiagram-NRAW4CY4-cKw9mAKi.js} +1 -1
  116. package/out/web/assets/{c4Diagram-UCG6FXSJ-BvY3U709.js → c4Diagram-UCG6FXSJ-Cqy8N5Ge.js} +1 -1
  117. package/out/web/assets/{chunk-75Z2AOVW-TLXCoZYv.js → chunk-75Z2AOVW-3qybijF5.js} +1 -1
  118. package/out/web/assets/chunk-CKBBP62Z-cIrXq6jN.js +2 -0
  119. package/out/web/assets/{chunk-CLGD4ZFX-xjsKtNS7.js → chunk-CLGD4ZFX-CndDQkww.js} +1 -1
  120. package/out/web/assets/chunk-DSNCTWBM-Cc4NxvgD.js +2 -0
  121. package/out/web/assets/chunk-DU6HZSFF-drzh6GsU.js +128 -0
  122. package/out/web/assets/{chunk-F27PBJKO-BFpgF55A.js → chunk-F27PBJKO-FiY35l4v.js} +1 -1
  123. package/out/web/assets/{chunk-G27WJ6UU-DfF7qW-C.js → chunk-G27WJ6UU-Bjt9Il4A.js} +1 -1
  124. package/out/web/assets/{chunk-GMAD6QVW-C-558kh_.js → chunk-GMAD6QVW-Bppi3Ctd.js} +1 -1
  125. package/out/web/assets/{chunk-JQ64N6SF-wJmeGKAw.js → chunk-JQ64N6SF-DGg5kcEV.js} +1 -1
  126. package/out/web/assets/{chunk-LCL6LL3I-C1wHD8Ie.js → chunk-LCL6LL3I-CCYcjd7p.js} +1 -1
  127. package/out/web/assets/{chunk-OBVCFTLP-BsRTPBqs.js → chunk-OBVCFTLP-DJeNil5M.js} +1 -1
  128. package/out/web/assets/{chunk-P2QGCYS3-HZIiM7Ni.js → chunk-P2QGCYS3-lRzkRjBB.js} +1 -1
  129. package/out/web/assets/{chunk-POPQ4Y6H-Dk9wvVb0.js → chunk-POPQ4Y6H-DouASMBW.js} +1 -1
  130. package/out/web/assets/{chunk-PWAF6VOD-BmjYLNbq.js → chunk-PWAF6VOD-DMmD1vVf.js} +1 -1
  131. package/out/web/assets/{chunk-R7TYR2AO-CaHIf-lK.js → chunk-R7TYR2AO-CYLA5UC5.js} +1 -1
  132. package/out/web/assets/{chunk-RHFEMEQ7-_T561hOU.js → chunk-RHFEMEQ7-BiXwEcUT.js} +1 -1
  133. package/out/web/assets/{chunk-SVP7TREG-CM-GGYoY.js → chunk-SVP7TREG-BV-zPslF.js} +1 -1
  134. package/out/web/assets/{chunk-TEH6E4GO-K2A8Vg2C.js → chunk-TEH6E4GO-B2RGEohZ.js} +1 -1
  135. package/out/web/assets/classDiagram-DTDB5LWJ-Dq0smRWk.js +1 -0
  136. package/out/web/assets/classDiagram-v2-JRS7N3AN-Dq0smRWk.js +1 -0
  137. package/out/web/assets/config-C-ZFtipU.css +1 -0
  138. package/out/web/assets/config-eEDngJXO.js +1 -0
  139. package/out/web/assets/core-hQ2VA9Ti.js +1 -0
  140. package/out/web/assets/{cynefin-OW5HDTMX-ClzaB6cc.js → cynefin-OW5HDTMX-Cas4csHM.js} +1 -1
  141. package/out/web/assets/{cynefinDiagram-5FMLGOSQ-D_JzZBzf.js → cynefinDiagram-5FMLGOSQ-Bbpj66Y3.js} +1 -1
  142. package/out/web/assets/{dagre-3AP2YEHR-BDuUeMHj.js → dagre-3AP2YEHR-B0-2RDEd.js} +1 -1
  143. package/out/web/assets/{diagram-S7CK7UJ4-DgtcfE8P.js → diagram-S7CK7UJ4-BdzEjUyH.js} +1 -1
  144. package/out/web/assets/{diagram-UQ7AKVKN-DTLoEYti.js → diagram-UQ7AKVKN-CJDwyPxF.js} +1 -1
  145. package/out/web/assets/{diagram-VSXAHHWV-ChGl9pXz.js → diagram-VSXAHHWV-BxaG1r_B.js} +1 -1
  146. package/out/web/assets/{diagram-VX7I27RA-Be8DWz0S.js → diagram-VX7I27RA-BMmUqm8f.js} +1 -1
  147. package/out/web/assets/{diagram-Z3DM3KII-BMXjRTOF.js → diagram-Z3DM3KII-CFtd03eE.js} +1 -1
  148. package/out/web/assets/dist-js-Bf2bhoku.js +1 -0
  149. package/out/web/assets/{ebnfDiagram-PWID7BFC-8Q9pl1CJ.js → ebnfDiagram-PWID7BFC-DwAen1hO.js} +1 -1
  150. package/out/web/assets/{erDiagram-SSCWMZ5O-DjH8Lnkn.js → erDiagram-SSCWMZ5O-BCZSHACj.js} +1 -1
  151. package/out/web/assets/event-ChBVpRy0.js +1 -0
  152. package/out/web/assets/{eventmodeling-NTZA5JFV-BKUH_DOp.js → eventmodeling-NTZA5JFV-XHStE4E_.js} +1 -1
  153. package/out/web/assets/fira-code-latin-600-normal-BmSSHshu.woff +0 -0
  154. package/out/web/assets/fira-code-latin-600-normal-CvYZpPHg.woff2 +0 -0
  155. package/out/web/assets/fira-code-symbols2-600-normal-Dvq6IQE5.woff +0 -0
  156. package/out/web/assets/flowDiagram-A5DVABFB-BLg7nEcd.js +1 -0
  157. package/out/web/assets/{ganttDiagram-EL5Y4UJY-D7fZKJNM.js → ganttDiagram-EL5Y4UJY-BAEu1Cql.js} +1 -1
  158. package/out/web/assets/{gitGraph-4MIJSDKK-BypWaaBU.js → gitGraph-4MIJSDKK-r32Vyper.js} +1 -1
  159. package/out/web/assets/{gitGraphDiagram-WWUBYQGX-DWiw_3bq.js → gitGraphDiagram-WWUBYQGX-z9o9qt6V.js} +1 -1
  160. package/out/web/assets/index-Btsf4L8M.css +1 -0
  161. package/out/web/assets/index-D8D9MeRA.js +11 -0
  162. package/out/web/assets/{info-A6RAGUB7-KkAUxT4j.js → info-A6RAGUB7-BvLaC2cw.js} +1 -1
  163. package/out/web/assets/{infoDiagram-RXCK75RN-BNb6E48y.js → infoDiagram-RXCK75RN-Be6WAXXw.js} +1 -1
  164. package/out/web/assets/{ishikawaDiagram-5VMMS53U-Caa-JoAK.js → ishikawaDiagram-5VMMS53U-DZjoHJHC.js} +1 -1
  165. package/out/web/assets/{journeyDiagram-EYS64GPL-DOrmFGz6.js → journeyDiagram-EYS64GPL-CtVkjkGm.js} +1 -1
  166. package/out/web/assets/{kanban-definition-3QL26DDD-BOWCYcK0.js → kanban-definition-3QL26DDD-CW5FMv1w.js} +1 -1
  167. package/out/web/assets/lucide-react-Ip3L6Jtn.js +1 -0
  168. package/out/web/assets/markdown-BSeeUbJH.js +38 -0
  169. package/out/web/assets/{mermaid-parser.core-BQqjCkS_.js → mermaid-parser.core-aUgCqsZ5.js} +3 -3
  170. package/out/web/assets/mermaid.core-D57sEiSL.js +11 -0
  171. package/out/web/assets/{mindmap-definition-FBJOCRG2-jTceWpr0.js → mindmap-definition-FBJOCRG2-DAmSpM3a.js} +1 -1
  172. package/out/web/assets/modelManager-tMVmJVAW.js +2 -0
  173. package/out/web/assets/oauthManager-9jxicDWJ.js +1 -0
  174. package/out/web/assets/{packet-AYTQ26CC-CJ5RXgol.js → packet-AYTQ26CC-DJ27iIoJ.js} +1 -1
  175. package/out/web/assets/{pegDiagram-XKGWAZYB-y8wMtd0y.js → pegDiagram-XKGWAZYB-Bj3ii-gS.js} +1 -1
  176. package/out/web/assets/{pie-WAS4IAKB-72fTBbl4.js → pie-WAS4IAKB-DG5mCUbc.js} +1 -1
  177. package/out/web/assets/{pieDiagram-E7YTZNPT-e0O02qWq.js → pieDiagram-E7YTZNPT-BrJLPnDA.js} +1 -1
  178. package/out/web/assets/prompt-latin-700-normal-BfbftDSq.woff +0 -0
  179. package/out/web/assets/prompt-latin-700-normal-I2gc831J.woff2 +0 -0
  180. package/out/web/assets/prompt-thai-700-normal-Cb5ilR-c.woff +0 -0
  181. package/out/web/assets/prompt-thai-700-normal-Cg4aQ0Nn.woff2 +0 -0
  182. package/out/web/assets/{quadrantDiagram-AXDQQJYC-C9phYLom.js → quadrantDiagram-AXDQQJYC-3x_TmF3j.js} +1 -1
  183. package/out/web/assets/{radar-RG4KPBEZ-BAU2hzUT.js → radar-RG4KPBEZ-CrXaTTuV.js} +1 -1
  184. package/out/web/assets/{railroad-74A4TZTK-B0bCAVHC.js → railroad-74A4TZTK-BpqMH9BE.js} +1 -1
  185. package/out/web/assets/{railroad-abnf-HS5TGJTU-WhxO7ndE.js → railroad-abnf-HS5TGJTU-DHI0uLlV.js} +1 -1
  186. package/out/web/assets/{railroad-ebnf-LZEXJU2U-BkA0m7-F.js → railroad-ebnf-LZEXJU2U-CQCb316y.js} +1 -1
  187. package/out/web/assets/{railroad-peg-WCYAUIDC-BsVpHIaj.js → railroad-peg-WCYAUIDC-Ph1giKkH.js} +1 -1
  188. package/out/web/assets/{railroadDiagram-O6MQD6OU-CyOLN65Q.js → railroadDiagram-O6MQD6OU-BRq6wIxx.js} +1 -1
  189. package/out/web/assets/{requirementDiagram-EFPCY7ZU-DQXJ7Dud.js → requirementDiagram-EFPCY7ZU-DIJj6G1g.js} +1 -1
  190. package/out/web/assets/{sankeyDiagram-P5KCCOFB-B2XLyIIc.js → sankeyDiagram-P5KCCOFB-DZajSryq.js} +1 -1
  191. package/out/web/assets/{sequenceDiagram-WJ2MYXX4-DGQY4wwm.js → sequenceDiagram-WJ2MYXX4-DxJCWyZS.js} +1 -1
  192. package/out/web/assets/{stateDiagram-HBIQ2CUA-DHZpDwNy.js → stateDiagram-HBIQ2CUA-k6voi8Vf.js} +1 -1
  193. package/out/web/assets/stateDiagram-v2-4QOOHH4V-DeEc0lGZ.js +1 -0
  194. package/out/web/assets/studio-B1mk40wD.js +1 -0
  195. package/out/web/assets/{swimlanes-XN3QIQJK-Bn_jcZz-.js → swimlanes-XN3QIQJK-igYhTjXB.js} +1 -1
  196. package/out/web/assets/swimlanesDiagram-VK2B7HYN-DpVik9v7.js +8 -0
  197. package/out/web/assets/{timeline-definition-24CTP7MA-CdTERuJZ.js → timeline-definition-24CTP7MA-Dke2p93p.js} +1 -1
  198. package/out/web/assets/{treeView-Q6P3EWNA-TKBKQG6R.js → treeView-Q6P3EWNA-hNELnXUs.js} +1 -1
  199. package/out/web/assets/{treemap-WGGIJYW6-BP7gQoiC.js → treemap-WGGIJYW6-D2B6wDsx.js} +1 -1
  200. package/out/web/assets/{vennDiagram-4TSXK5OY-BHUmxDuK.js → vennDiagram-4TSXK5OY-CDkW7rUP.js} +1 -1
  201. package/out/web/assets/{wardley-WFR3VGLG-9bct5AAN.js → wardley-WFR3VGLG-BECdXETi.js} +1 -1
  202. package/out/web/assets/{wardleyDiagram-VM6X3IG4-BfJwDDso.js → wardleyDiagram-VM6X3IG4-B5BycpQ4.js} +1 -1
  203. package/out/web/assets/window-5qYXKoW7.js +1 -0
  204. package/out/web/assets/{xychartDiagram-S5SC5T6Z-Dqd9Mvpo.js → xychartDiagram-S5SC5T6Z-CtJS3b--.js} +1 -1
  205. package/out/web/index-web.html +3 -4
  206. package/out/web/index.html +3 -4
  207. package/package.json +17 -6
  208. package/skills-lock.json +36 -0
  209. package/slash-commands.json +9 -0
  210. package/src/renderer/index-web.html +1 -0
  211. package/src/renderer/index.html +1 -0
  212. package/src/renderer/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  213. package/src/renderer/shared/agentProgress.ts +168 -3
  214. package/src/renderer/shared/components/AgentActivityDrawer.tsx +6 -6
  215. package/src/renderer/shared/components/AgentActivityTable.tsx +192 -132
  216. package/src/renderer/shared/components/ArtifactPreviewPanel.tsx +4 -4
  217. package/src/renderer/shared/components/AuthGate.tsx +4 -9
  218. package/src/renderer/shared/components/CalculationCard.tsx +41 -15
  219. package/src/renderer/shared/components/ChatMessageItem.tsx +20 -21
  220. package/src/renderer/shared/components/ChatPanel.tsx +432 -193
  221. package/src/renderer/shared/components/ChunkErrorBoundary.tsx +198 -49
  222. package/src/renderer/shared/components/CliSessionsView.tsx +495 -0
  223. package/src/renderer/shared/components/CodeReviewPage.tsx +565 -0
  224. package/src/renderer/shared/components/CommandPalette.tsx +8 -8
  225. package/src/renderer/shared/components/DashboardSidebar.tsx +862 -125
  226. package/src/renderer/shared/components/DesktopTitlebar.tsx +345 -0
  227. package/src/renderer/shared/components/DiffReviewModal.tsx +3 -3
  228. package/src/renderer/shared/components/GitBranchSelector.tsx +442 -0
  229. package/src/renderer/shared/components/ImageGenCard.tsx +31 -12
  230. package/src/renderer/shared/components/ImageSearchCard.tsx +59 -38
  231. package/src/renderer/shared/components/ImageStudioPanel.tsx +40 -41
  232. package/src/renderer/shared/components/InlineThoughtNote.tsx +27 -0
  233. package/src/renderer/shared/components/LinkedFoldersView.tsx +365 -46
  234. package/src/renderer/shared/components/McpRegistryPicker.tsx +1 -1
  235. package/src/renderer/shared/components/McpServersView.tsx +24 -22
  236. package/src/renderer/shared/components/MermaidCard.tsx +14 -8
  237. package/src/renderer/shared/components/MintDashboard.tsx +1141 -508
  238. package/src/renderer/shared/components/ModelSelectorPopover.tsx +535 -214
  239. package/src/renderer/shared/components/PlanChecklistWidget.tsx +1 -1
  240. package/src/renderer/shared/components/PluginsView.tsx +1 -1
  241. package/src/renderer/shared/components/RewindModal.tsx +6 -6
  242. package/src/renderer/shared/components/RunSummaryDashboard.tsx +3 -3
  243. package/src/renderer/shared/components/ScheduledTasksView.tsx +4 -4
  244. package/src/renderer/shared/components/ScreenCaptureDialog.css +221 -0
  245. package/src/renderer/shared/components/ScreenCaptureDialog.tsx +199 -0
  246. package/src/renderer/shared/components/Settings/AgentsTab.tsx +34 -39
  247. package/src/renderer/shared/components/Settings/AudioTab.tsx +8 -8
  248. package/src/renderer/shared/components/Settings/AutomationTab.tsx +8 -58
  249. package/src/renderer/shared/components/Settings/AvatarCropModal.tsx +368 -0
  250. package/src/renderer/shared/components/Settings/GeneralTab.tsx +335 -81
  251. package/src/renderer/shared/components/Settings/MemoryTab.tsx +3 -3
  252. package/src/renderer/shared/components/Settings/PluginsTab.tsx +20 -12
  253. package/src/renderer/shared/components/Settings/ProfileTab.tsx +29 -5
  254. package/src/renderer/shared/components/Settings/SearchableModelCombobox.tsx +411 -0
  255. package/src/renderer/shared/components/Settings/ThemeTab.tsx +401 -158
  256. package/src/renderer/shared/components/SkillsView.tsx +41 -16
  257. package/src/renderer/shared/components/SlashSuggestions.tsx +3 -2
  258. package/src/renderer/shared/components/SourcesBlock.tsx +44 -32
  259. package/src/renderer/shared/components/StockCard.tsx +58 -24
  260. package/src/renderer/shared/components/SubagentDagView.tsx +4 -4
  261. package/src/renderer/shared/components/TerminalDock.tsx +241 -0
  262. package/src/renderer/shared/components/ThinkingBlock.tsx +14 -8
  263. package/src/renderer/shared/components/ToolSurfacePage.tsx +520 -0
  264. package/src/renderer/shared/components/UiFeatureCard.tsx +267 -0
  265. package/src/renderer/shared/components/UiGridCard.tsx +188 -0
  266. package/src/renderer/shared/components/UiMockupWidget.tsx +149 -0
  267. package/src/renderer/shared/components/VeoStudioPanel.tsx +13 -29
  268. package/src/renderer/shared/components/WeatherCard.tsx +3 -3
  269. package/src/renderer/shared/components/WorkspaceContextPopover.tsx +133 -0
  270. package/src/renderer/shared/components/WorkspaceSelector.tsx +149 -0
  271. package/src/renderer/shared/constants/config.ts +28 -3
  272. package/src/renderer/shared/constants/models.ts +189 -2
  273. package/src/renderer/shared/conversation/coordinator.test.ts +27 -0
  274. package/src/renderer/shared/conversation/coordinator.ts +82 -0
  275. package/src/renderer/shared/conversation/syncView.test.ts +46 -0
  276. package/src/renderer/shared/conversation/syncView.ts +43 -0
  277. package/src/renderer/shared/conversation/useConversationCoordinator.ts +106 -0
  278. package/src/renderer/shared/css/agent-observability.css +35 -3
  279. package/src/renderer/shared/css/auth-gate.css +2 -2
  280. package/src/renderer/shared/css/chat-ui-cards.css +495 -0
  281. package/src/renderer/shared/css/code-review.css +823 -0
  282. package/src/renderer/shared/css/code-sessions.css +452 -0
  283. package/src/renderer/shared/css/file-changes.css +132 -0
  284. package/src/renderer/shared/css/image-studio.css +16 -16
  285. package/src/renderer/shared/css/management-views.css +277 -27
  286. package/src/renderer/shared/css/model-selector.css +442 -42
  287. package/src/renderer/shared/css/settings/agents.css +1 -1
  288. package/src/renderer/shared/css/settings/automation.css +13 -13
  289. package/src/renderer/shared/css/settings/general.css +526 -5
  290. package/src/renderer/shared/css/settings/plugins.css +5 -5
  291. package/src/renderer/shared/css/settings/profile.css +331 -1
  292. package/src/renderer/shared/css/settings/theme.css +651 -3
  293. package/src/renderer/shared/css/veo-studio.css +16 -15
  294. package/src/renderer/shared/fonts.ts +19 -37
  295. package/src/renderer/shared/platform.test.ts +34 -0
  296. package/src/renderer/shared/platform.ts +173 -6
  297. package/src/renderer/shared/theme/themeManager.ts +144 -0
  298. package/src/renderer/shared/theme/themes.ts +116 -0
  299. package/src/renderer/shared/theme/tokens.css +318 -0
  300. package/src/renderer/shared/types.ts +82 -1
  301. package/src/renderer/shared/utils/agentActivity.ts +126 -5
  302. package/src/renderer/shared/utils/cardJson.test.ts +35 -0
  303. package/src/renderer/shared/utils/cardJson.ts +30 -0
  304. package/src/renderer/shared/utils/fileIcons.ts +1 -1
  305. package/src/renderer/shared/utils/markdown.tsx +329 -80
  306. package/src/renderer/shared/utils/markdown.webImages.test.tsx +40 -0
  307. package/src/renderer/shared/utils/providers.ts +8 -3
  308. package/src/renderer/shared/utils/screenCapture.ts +43 -0
  309. package/src/renderer/shared/utils/slashCommandProcessor.ts +4 -1
  310. package/src/renderer/shared/utils/ui.ts +4 -64
  311. package/src/renderer/src/App.tsx +7 -0
  312. package/src/renderer/src/components/BrowserShell.tsx +108 -0
  313. package/src/renderer/src/components/BrowserSuggestionsPopup.tsx +91 -0
  314. package/src/renderer/src/components/Live2DStage.tsx +32 -9
  315. package/src/renderer/src/components/MintDashboard.tsx +4 -2
  316. package/src/renderer/src/components/ModelPanel.tsx +2 -1
  317. package/src/renderer/src/components/PicturesLibrary.tsx +3 -2
  318. package/src/renderer/src/components/ScreenPicker.css +190 -0
  319. package/src/renderer/src/components/ScreenPicker.tsx +185 -540
  320. package/src/renderer/src/components/SettingsWindow.tsx +40 -2
  321. package/src/renderer/src/components/SpotlightWindow.tsx +1 -0
  322. package/src/renderer/src/components/WidgetWindow.tsx +27 -3
  323. package/src/renderer/src/components/WorkspacePanel.tsx +61 -43
  324. package/src/renderer/src/components/browser-shell.css +185 -0
  325. package/src/renderer/src/components/browser-suggestions-popup.css +55 -0
  326. package/src/renderer/src/components/liveTranslateFrames.test.ts +23 -0
  327. package/src/renderer/src/components/liveTranslateFrames.ts +34 -0
  328. package/src/renderer/src/css/app-shell.css +394 -113
  329. package/src/renderer/src/css/chat.css +1926 -380
  330. package/src/renderer/src/css/dashboard.css +11 -0
  331. package/src/renderer/src/css/desktop-tools.css +730 -0
  332. package/src/renderer/src/css/misc.css +19 -22
  333. package/src/renderer/src/css/model.css +49 -48
  334. package/src/renderer/src/css/pictures.css +144 -136
  335. package/src/renderer/src/css/settings/base.css +357 -123
  336. package/src/renderer/src/css/sidebar-workspace.css +930 -291
  337. package/src/renderer/src/css/spotlight.css +15 -26
  338. package/src/renderer/src/css/tool-surfaces.css +728 -0
  339. package/src/renderer/src/css/widget.css +35 -7
  340. package/src/renderer/src/env.d.ts +3 -0
  341. package/src/renderer/src/hooks/useProviderModels.ts +2 -9
  342. package/src/renderer/src/index.css +53 -46
  343. package/src/renderer/src/main.tsx +11 -0
  344. package/src/renderer/src/tauri.ts +201 -30
  345. package/src/renderer/src-web/App.tsx +40 -0
  346. package/src/renderer/src-web/components/MintDashboard.tsx +4 -2
  347. package/src/renderer/src-web/components/PicturesLibrary.tsx +3 -2
  348. package/src/renderer/src-web/components/PullToRefresh.tsx +107 -0
  349. package/src/renderer/src-web/components/SettingsWindow.tsx +28 -2
  350. package/src/renderer/src-web/css/app-shell.css +174 -96
  351. package/src/renderer/src-web/css/chat.css +1519 -316
  352. package/src/renderer/src-web/css/dashboard.css +11 -0
  353. package/src/renderer/src-web/css/misc.css +17 -17
  354. package/src/renderer/src-web/css/mobile.css +678 -0
  355. package/src/renderer/src-web/css/model.css +46 -46
  356. package/src/renderer/src-web/css/pictures.css +81 -34
  357. package/src/renderer/src-web/css/pull-to-refresh.css +54 -0
  358. package/src/renderer/src-web/css/settings/base.css +316 -100
  359. package/src/renderer/src-web/css/settings/mobile.css +320 -0
  360. package/src/renderer/src-web/css/sidebar-workspace.css +545 -100
  361. package/src/renderer/src-web/css/spotlight.css +9 -26
  362. package/src/renderer/src-web/css/widget.css +0 -5
  363. package/src/renderer/src-web/env.d.ts +3 -0
  364. package/src/renderer/src-web/hooks/useProviderModels.ts +2 -9
  365. package/src/renderer/src-web/index.css +53 -96
  366. package/src/renderer/src-web/main.tsx +11 -0
  367. package/src/renderer/src-web/tauri.ts +200 -30
  368. package/vite.config.web.ts +1 -0
  369. package/out/web/assets/MintDashboard-DWSqucgb.js +0 -57
  370. package/out/web/assets/SettingsWindow-DFM2aj5B.js +0 -2
  371. package/out/web/assets/chunk-CKBBP62Z-nr1uKPj9.js +0 -2
  372. package/out/web/assets/chunk-DSNCTWBM-Dtj8Rqsd.js +0 -2
  373. package/out/web/assets/chunk-DU6HZSFF-2tv5K1wT.js +0 -128
  374. package/out/web/assets/classDiagram-DTDB5LWJ-BdSFArgw.js +0 -1
  375. package/out/web/assets/classDiagram-v2-JRS7N3AN-BdSFArgw.js +0 -1
  376. package/out/web/assets/core-DImejIUG.js +0 -1
  377. package/out/web/assets/dist-js-BxuKEVWM.js +0 -1
  378. package/out/web/assets/event-BNl8Zahw.js +0 -1
  379. package/out/web/assets/fira-code-cyrillic-400-normal-UC0NFL4U.woff2 +0 -0
  380. package/out/web/assets/fira-code-cyrillic-400-normal-dc1q3VD7.woff +0 -0
  381. package/out/web/assets/fira-code-cyrillic-500-normal-Bu7VCL72.woff +0 -0
  382. package/out/web/assets/fira-code-cyrillic-500-normal-CX35h3Mg.woff2 +0 -0
  383. package/out/web/assets/fira-code-cyrillic-ext-400-normal-Buh61xzB.woff +0 -0
  384. package/out/web/assets/fira-code-cyrillic-ext-400-normal-txZ9Fk_1.woff2 +0 -0
  385. package/out/web/assets/fira-code-cyrillic-ext-500-normal-CYRspHgm.woff2 +0 -0
  386. package/out/web/assets/fira-code-cyrillic-ext-500-normal-CwtLmSFD.woff +0 -0
  387. package/out/web/assets/fira-code-greek-400-normal-B2Gh_Y8s.woff2 +0 -0
  388. package/out/web/assets/fira-code-greek-400-normal-DobhaxvF.woff +0 -0
  389. package/out/web/assets/fira-code-greek-500-normal-CVO0IRNt.woff2 +0 -0
  390. package/out/web/assets/fira-code-greek-500-normal-DEXIWiey.woff +0 -0
  391. package/out/web/assets/fira-code-greek-ext-400-normal-DR7mBgIM.woff2 +0 -0
  392. package/out/web/assets/fira-code-greek-ext-400-normal-DSPUheWg.woff +0 -0
  393. package/out/web/assets/fira-code-greek-ext-500-normal-BO3iq16n.woff2 +0 -0
  394. package/out/web/assets/fira-code-greek-ext-500-normal-CMiNLXER.woff +0 -0
  395. package/out/web/assets/fira-code-latin-ext-400-normal-DG73JjOf.woff +0 -0
  396. package/out/web/assets/fira-code-latin-ext-400-normal-KSMg0QLl.woff2 +0 -0
  397. package/out/web/assets/fira-code-latin-ext-500-normal-CaANqXjI.woff +0 -0
  398. package/out/web/assets/fira-code-latin-ext-500-normal-Crd9e_oI.woff2 +0 -0
  399. package/out/web/assets/flowDiagram-A5DVABFB-BpnHUSU7.js +0 -1
  400. package/out/web/assets/index-CVRg270z.css +0 -1
  401. package/out/web/assets/index-DxZQr9yD.js +0 -10
  402. package/out/web/assets/inter-cyrillic-400-normal-HOLc17fK.woff +0 -0
  403. package/out/web/assets/inter-cyrillic-400-normal-obahsSVq.woff2 +0 -0
  404. package/out/web/assets/inter-cyrillic-500-normal-BasfLYem.woff2 +0 -0
  405. package/out/web/assets/inter-cyrillic-500-normal-CxZf_p3X.woff +0 -0
  406. package/out/web/assets/inter-cyrillic-600-normal-4D_pXhcN.woff +0 -0
  407. package/out/web/assets/inter-cyrillic-600-normal-CWCymEST.woff2 +0 -0
  408. package/out/web/assets/inter-cyrillic-ext-400-normal-BQZuk6qB.woff2 +0 -0
  409. package/out/web/assets/inter-cyrillic-ext-400-normal-DQukG94-.woff +0 -0
  410. package/out/web/assets/inter-cyrillic-ext-500-normal-B0yAr1jD.woff2 +0 -0
  411. package/out/web/assets/inter-cyrillic-ext-500-normal-BmqWE9Dz.woff +0 -0
  412. package/out/web/assets/inter-cyrillic-ext-600-normal-Bcila6Z-.woff +0 -0
  413. package/out/web/assets/inter-cyrillic-ext-600-normal-Dfes3d0z.woff2 +0 -0
  414. package/out/web/assets/inter-greek-400-normal-B4URO6DV.woff2 +0 -0
  415. package/out/web/assets/inter-greek-400-normal-q2sYcFCs.woff +0 -0
  416. package/out/web/assets/inter-greek-500-normal-BIZE56-Y.woff2 +0 -0
  417. package/out/web/assets/inter-greek-500-normal-Xzm54t5V.woff +0 -0
  418. package/out/web/assets/inter-greek-600-normal-BZpKdvQh.woff +0 -0
  419. package/out/web/assets/inter-greek-600-normal-plRanbMR.woff2 +0 -0
  420. package/out/web/assets/inter-greek-ext-400-normal-DGGRlc-M.woff2 +0 -0
  421. package/out/web/assets/inter-greek-ext-400-normal-KugGGMne.woff +0 -0
  422. package/out/web/assets/inter-greek-ext-500-normal-2j5mBUwD.woff +0 -0
  423. package/out/web/assets/inter-greek-ext-500-normal-C4iEst2y.woff2 +0 -0
  424. package/out/web/assets/inter-greek-ext-600-normal-B8X0CLgF.woff +0 -0
  425. package/out/web/assets/inter-greek-ext-600-normal-DRtmH8MT.woff2 +0 -0
  426. package/out/web/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  427. package/out/web/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
  428. package/out/web/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
  429. package/out/web/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  430. package/out/web/assets/inter-latin-600-normal-CiBQ2DWP.woff +0 -0
  431. package/out/web/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
  432. package/out/web/assets/inter-latin-ext-400-normal-77YHD8bZ.woff +0 -0
  433. package/out/web/assets/inter-latin-ext-400-normal-C1nco2VV.woff2 +0 -0
  434. package/out/web/assets/inter-latin-ext-500-normal-BxGbmqWO.woff +0 -0
  435. package/out/web/assets/inter-latin-ext-500-normal-CV4jyFjo.woff2 +0 -0
  436. package/out/web/assets/inter-latin-ext-600-normal-CIVaiw4L.woff +0 -0
  437. package/out/web/assets/inter-latin-ext-600-normal-D2bJ5OIk.woff2 +0 -0
  438. package/out/web/assets/inter-vietnamese-400-normal-Bbgyi5SW.woff +0 -0
  439. package/out/web/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
  440. package/out/web/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
  441. package/out/web/assets/inter-vietnamese-500-normal-mJboJaSs.woff +0 -0
  442. package/out/web/assets/inter-vietnamese-600-normal-BuLX-rYi.woff +0 -0
  443. package/out/web/assets/inter-vietnamese-600-normal-Cc8MFFhd.woff2 +0 -0
  444. package/out/web/assets/kanit-latin-400-normal-BUlsQXH3.woff2 +0 -0
  445. package/out/web/assets/kanit-latin-400-normal-HVZWrfev.woff +0 -0
  446. package/out/web/assets/kanit-latin-500-normal-CX_4XcKi.woff2 +0 -0
  447. package/out/web/assets/kanit-latin-500-normal-qBha86O4.woff +0 -0
  448. package/out/web/assets/kanit-latin-600-normal-0lS78yAd.woff2 +0 -0
  449. package/out/web/assets/kanit-latin-600-normal-DlacpeTg.woff +0 -0
  450. package/out/web/assets/kanit-latin-ext-400-normal-B2xPf58u.woff2 +0 -0
  451. package/out/web/assets/kanit-latin-ext-400-normal-CHvNKHHD.woff +0 -0
  452. package/out/web/assets/kanit-latin-ext-500-normal-BFdWrG22.woff +0 -0
  453. package/out/web/assets/kanit-latin-ext-500-normal-EHs3suD6.woff2 +0 -0
  454. package/out/web/assets/kanit-latin-ext-600-normal-BBDzoLaj.woff +0 -0
  455. package/out/web/assets/kanit-latin-ext-600-normal-DAX3wtuq.woff2 +0 -0
  456. package/out/web/assets/kanit-thai-400-normal-D2nliXKa.woff +0 -0
  457. package/out/web/assets/kanit-thai-400-normal-D80Pglro.woff2 +0 -0
  458. package/out/web/assets/kanit-thai-500-normal-BB8gri04.woff2 +0 -0
  459. package/out/web/assets/kanit-thai-500-normal-Iy_w0a80.woff +0 -0
  460. package/out/web/assets/kanit-thai-600-normal-Bj6oiaDc.woff2 +0 -0
  461. package/out/web/assets/kanit-thai-600-normal-wbTlPO7I.woff +0 -0
  462. package/out/web/assets/kanit-vietnamese-400-normal-DRI8YWyb.woff2 +0 -0
  463. package/out/web/assets/kanit-vietnamese-400-normal-dow6Bnto.woff +0 -0
  464. package/out/web/assets/kanit-vietnamese-500-normal-BzTrpCM3.woff2 +0 -0
  465. package/out/web/assets/kanit-vietnamese-500-normal-T1ndT7MF.woff +0 -0
  466. package/out/web/assets/kanit-vietnamese-600-normal-Bi7fw3I4.woff2 +0 -0
  467. package/out/web/assets/kanit-vietnamese-600-normal-DXCRAa_8.woff +0 -0
  468. package/out/web/assets/mali-latin-400-normal-ByPcZ8Gx.woff +0 -0
  469. package/out/web/assets/mali-latin-400-normal-Cuc6Ykl8.woff2 +0 -0
  470. package/out/web/assets/mali-latin-500-normal-B01M-LP6.woff2 +0 -0
  471. package/out/web/assets/mali-latin-500-normal-Thgqw_9f.woff +0 -0
  472. package/out/web/assets/mali-latin-600-normal-B9TiUNpT.woff2 +0 -0
  473. package/out/web/assets/mali-latin-600-normal-CycpQCwU.woff +0 -0
  474. package/out/web/assets/mali-latin-ext-400-normal-DUVdJQO4.woff +0 -0
  475. package/out/web/assets/mali-latin-ext-400-normal-iCG1ALuJ.woff2 +0 -0
  476. package/out/web/assets/mali-latin-ext-500-normal-BfJE4UMZ.woff2 +0 -0
  477. package/out/web/assets/mali-latin-ext-500-normal-FoLEyOKS.woff +0 -0
  478. package/out/web/assets/mali-latin-ext-600-normal-BTvIfiCp.woff2 +0 -0
  479. package/out/web/assets/mali-latin-ext-600-normal-DAQcLVmD.woff +0 -0
  480. package/out/web/assets/mali-thai-400-normal-BO7A3bLZ.woff2 +0 -0
  481. package/out/web/assets/mali-thai-400-normal-CX9VrjTn.woff +0 -0
  482. package/out/web/assets/mali-thai-500-normal-Cph2qha9.woff +0 -0
  483. package/out/web/assets/mali-thai-500-normal-D89rMT77.woff2 +0 -0
  484. package/out/web/assets/mali-thai-600-normal-DPgXT6rZ.woff +0 -0
  485. package/out/web/assets/mali-thai-600-normal-DlTx3OsB.woff2 +0 -0
  486. package/out/web/assets/mali-vietnamese-400-normal-DUKxzXaz.woff2 +0 -0
  487. package/out/web/assets/mali-vietnamese-400-normal-gFDLvsOK.woff +0 -0
  488. package/out/web/assets/mali-vietnamese-500-normal--OY07q2c.woff +0 -0
  489. package/out/web/assets/mali-vietnamese-500-normal-KDrNRwfW.woff2 +0 -0
  490. package/out/web/assets/mali-vietnamese-600-normal-CtTMUU7T.woff +0 -0
  491. package/out/web/assets/mali-vietnamese-600-normal-DFlJr66u.woff2 +0 -0
  492. package/out/web/assets/mermaid.core-DYGGlqOf.js +0 -11
  493. package/out/web/assets/mitr-latin-400-normal-Cb18vPmZ.woff +0 -0
  494. package/out/web/assets/mitr-latin-400-normal-CwbkLQ4a.woff2 +0 -0
  495. package/out/web/assets/mitr-latin-500-normal-B4JOhzAi.woff +0 -0
  496. package/out/web/assets/mitr-latin-500-normal-BmClOow2.woff2 +0 -0
  497. package/out/web/assets/mitr-latin-ext-400-normal-B3CPG7Yo.woff2 +0 -0
  498. package/out/web/assets/mitr-latin-ext-400-normal-DTx65hiC.woff +0 -0
  499. package/out/web/assets/mitr-latin-ext-500-normal-B_Diajz1.woff2 +0 -0
  500. package/out/web/assets/mitr-latin-ext-500-normal-DYOsVaVT.woff +0 -0
  501. package/out/web/assets/mitr-thai-400-normal-CS4Do6aM.woff +0 -0
  502. package/out/web/assets/mitr-thai-400-normal-CXWaAdVj.woff2 +0 -0
  503. package/out/web/assets/mitr-thai-500-normal-CVdBrEVH.woff2 +0 -0
  504. package/out/web/assets/mitr-thai-500-normal-CW_B5D-i.woff +0 -0
  505. package/out/web/assets/mitr-vietnamese-400-normal-CPMGWyoC.woff2 +0 -0
  506. package/out/web/assets/mitr-vietnamese-400-normal-Z6XhIpdY.woff +0 -0
  507. package/out/web/assets/mitr-vietnamese-500-normal-CDrv0585.woff2 +0 -0
  508. package/out/web/assets/mitr-vietnamese-500-normal-CMQWyq-Z.woff +0 -0
  509. package/out/web/assets/noto-sans-thai-latin-400-normal-BaWBrqFP.woff2 +0 -0
  510. package/out/web/assets/noto-sans-thai-latin-400-normal-Dh_FJjOB.woff +0 -0
  511. package/out/web/assets/noto-sans-thai-latin-500-normal-BC04jsmm.woff +0 -0
  512. package/out/web/assets/noto-sans-thai-latin-500-normal-fyBKClF1.woff2 +0 -0
  513. package/out/web/assets/noto-sans-thai-latin-600-normal-CemcjnVR.woff2 +0 -0
  514. package/out/web/assets/noto-sans-thai-latin-600-normal-Dbc-dNO6.woff +0 -0
  515. package/out/web/assets/noto-sans-thai-latin-ext-400-normal-B-1H0YkH.woff +0 -0
  516. package/out/web/assets/noto-sans-thai-latin-ext-400-normal-nBP59pVw.woff2 +0 -0
  517. package/out/web/assets/noto-sans-thai-latin-ext-500-normal-B-ZWb8SZ.woff2 +0 -0
  518. package/out/web/assets/noto-sans-thai-latin-ext-500-normal-CrEHO7C8.woff +0 -0
  519. package/out/web/assets/noto-sans-thai-latin-ext-600-normal-PkMZo0xa.woff +0 -0
  520. package/out/web/assets/noto-sans-thai-latin-ext-600-normal-maHHBsez.woff2 +0 -0
  521. package/out/web/assets/noto-sans-thai-thai-400-normal-BEOmKAI1.woff2 +0 -0
  522. package/out/web/assets/noto-sans-thai-thai-400-normal-Dxb_unuU.woff +0 -0
  523. package/out/web/assets/noto-sans-thai-thai-500-normal-BOGXO2tw.woff +0 -0
  524. package/out/web/assets/noto-sans-thai-thai-500-normal-CU_X86GQ.woff2 +0 -0
  525. package/out/web/assets/noto-sans-thai-thai-600-normal-CmgB8_JK.woff +0 -0
  526. package/out/web/assets/noto-sans-thai-thai-600-normal-Cs73sVjl.woff2 +0 -0
  527. package/out/web/assets/oauthManager-DNiwM8Rn.js +0 -2
  528. package/out/web/assets/oauthManager-DuamS1Av.css +0 -1
  529. package/out/web/assets/outfit-latin-300-normal-AWLfuCom.woff +0 -0
  530. package/out/web/assets/outfit-latin-300-normal-CRYTwY6m.woff2 +0 -0
  531. package/out/web/assets/outfit-latin-400-normal-BGsTXAXT.woff2 +0 -0
  532. package/out/web/assets/outfit-latin-400-normal-DMwTpYkH.woff +0 -0
  533. package/out/web/assets/outfit-latin-500-normal-ClnHRwRh.woff +0 -0
  534. package/out/web/assets/outfit-latin-500-normal-DKnIMDSk.woff2 +0 -0
  535. package/out/web/assets/outfit-latin-600-normal-B7SfZ07L.woff2 +0 -0
  536. package/out/web/assets/outfit-latin-600-normal-BEfTtDA7.woff +0 -0
  537. package/out/web/assets/outfit-latin-ext-300-normal-BYS6Dpvq.woff2 +0 -0
  538. package/out/web/assets/outfit-latin-ext-300-normal-CMIMshEd.woff +0 -0
  539. package/out/web/assets/outfit-latin-ext-400-normal-5tcqmc2S.woff2 +0 -0
  540. package/out/web/assets/outfit-latin-ext-400-normal-DHm7mdGe.woff +0 -0
  541. package/out/web/assets/outfit-latin-ext-500-normal-DrCvqoFD.woff +0 -0
  542. package/out/web/assets/outfit-latin-ext-500-normal-zeox_O30.woff2 +0 -0
  543. package/out/web/assets/outfit-latin-ext-600-normal-B85nYjL1.woff2 +0 -0
  544. package/out/web/assets/outfit-latin-ext-600-normal-CWJcPgd7.woff +0 -0
  545. package/out/web/assets/preload-helper-D0uHx7FM.js +0 -1
  546. package/out/web/assets/prompt-latin-ext-400-normal-1pHbN9uy.woff +0 -0
  547. package/out/web/assets/prompt-latin-ext-400-normal-DdSafGZ9.woff2 +0 -0
  548. package/out/web/assets/prompt-latin-ext-500-normal--EZ1um7s.woff2 +0 -0
  549. package/out/web/assets/prompt-latin-ext-500-normal-D-lI1EVT.woff +0 -0
  550. package/out/web/assets/prompt-latin-ext-600-normal-C8b50x67.woff +0 -0
  551. package/out/web/assets/prompt-latin-ext-600-normal-Cg9L7iJU.woff2 +0 -0
  552. package/out/web/assets/prompt-vietnamese-400-normal-BCPzsgPT.woff2 +0 -0
  553. package/out/web/assets/prompt-vietnamese-400-normal-D4pLyeNK.woff +0 -0
  554. package/out/web/assets/prompt-vietnamese-500-normal-DmzxmPwa.woff2 +0 -0
  555. package/out/web/assets/prompt-vietnamese-500-normal-w_sS_j2F.woff +0 -0
  556. package/out/web/assets/prompt-vietnamese-600-normal-1dyohtNh.woff +0 -0
  557. package/out/web/assets/prompt-vietnamese-600-normal-7QWjJBsF.woff2 +0 -0
  558. package/out/web/assets/sarabun-latin-400-normal-DmguIS-7.woff +0 -0
  559. package/out/web/assets/sarabun-latin-400-normal-URPBxl-K.woff2 +0 -0
  560. package/out/web/assets/sarabun-latin-500-normal-BjUTcdxu.woff2 +0 -0
  561. package/out/web/assets/sarabun-latin-500-normal-CJexTAnl.woff +0 -0
  562. package/out/web/assets/sarabun-latin-600-normal-9FonlkKx.woff +0 -0
  563. package/out/web/assets/sarabun-latin-600-normal-DMD3TROr.woff2 +0 -0
  564. package/out/web/assets/sarabun-latin-ext-400-normal-BbP7GpLL.woff2 +0 -0
  565. package/out/web/assets/sarabun-latin-ext-400-normal-BsmTn0SS.woff +0 -0
  566. package/out/web/assets/sarabun-latin-ext-500-normal-Cot16Bd2.woff +0 -0
  567. package/out/web/assets/sarabun-latin-ext-500-normal-DE1LysqI.woff2 +0 -0
  568. package/out/web/assets/sarabun-latin-ext-600-normal-0tXu9x_i.woff +0 -0
  569. package/out/web/assets/sarabun-latin-ext-600-normal-BRxjKUQ6.woff2 +0 -0
  570. package/out/web/assets/sarabun-thai-400-normal-C2DaJlKK.woff2 +0 -0
  571. package/out/web/assets/sarabun-thai-400-normal-CH-UbWgg.woff +0 -0
  572. package/out/web/assets/sarabun-thai-500-normal-BVssjame.woff2 +0 -0
  573. package/out/web/assets/sarabun-thai-500-normal-C3iDLEzi.woff +0 -0
  574. package/out/web/assets/sarabun-thai-600-normal-3dIAQ-_s.woff2 +0 -0
  575. package/out/web/assets/sarabun-thai-600-normal-DWKeTe6a.woff +0 -0
  576. package/out/web/assets/sarabun-vietnamese-400-normal-DPfkSCMy.woff +0 -0
  577. package/out/web/assets/sarabun-vietnamese-400-normal-igdrzAGY.woff2 +0 -0
  578. package/out/web/assets/sarabun-vietnamese-500-normal-CpRVvGRU.woff +0 -0
  579. package/out/web/assets/sarabun-vietnamese-500-normal-Dpe7Br9m.woff2 +0 -0
  580. package/out/web/assets/sarabun-vietnamese-600-normal-BMbOgAW-.woff +0 -0
  581. package/out/web/assets/sarabun-vietnamese-600-normal-DkxrOlLB.woff2 +0 -0
  582. package/out/web/assets/stateDiagram-v2-4QOOHH4V-s6P9g2_b.js +0 -1
  583. package/out/web/assets/swimlanesDiagram-VK2B7HYN-CV9fOLrV.js +0 -8
  584. package/out/web/assets/tauri-CNrHQ2Gb.js +0 -3
  585. package/out/web/assets/window-DkIhgI7B.js +0 -1
@@ -1,25 +1,44 @@
1
1
  use crate::background::{BackgroundJobs, JobStatus};
2
- use crate::{BLUE, DIM, ERROR, MINT, RESET, WARN};
2
+ use crate::{BLUE, BOLD, DIM, ERROR, MINT, RESET, WARN};
3
3
  use crate::{agent, image};
4
4
  use anyhow::Result;
5
5
  use mint_core::{CHAT_CLI_ID, MemoryStore, MintConfig};
6
6
  use std::fs;
7
7
  use std::io::{self, Write};
8
8
  use std::path::{Path, PathBuf};
9
+ use std::sync::{Arc, Mutex};
9
10
 
11
+ mod chat_tui;
12
+ pub mod command_ui;
10
13
  mod commands;
11
14
  mod confirm;
12
15
  mod format;
13
16
  mod input_box;
14
17
  mod picker;
18
+ mod resume_picker;
15
19
  mod slash_commands;
20
+ mod thought_viewer;
16
21
 
22
+ pub(crate) use chat_tui::TuiHandle;
23
+ pub(crate) use chat_tui::restore_terminal;
24
+ pub use command_ui::*;
17
25
  pub use commands::*;
18
26
  pub use confirm::*;
19
27
  pub use format::*;
20
28
  pub use input_box::*;
21
29
  pub use picker::*;
30
+ pub use resume_picker::*;
22
31
  pub use slash_commands::*;
32
+ pub use thought_viewer::*;
33
+
34
+ pub fn truncate_utf8(text: &str, max_chars: usize) -> String {
35
+ if text.chars().count() <= max_chars {
36
+ return text.to_string();
37
+ }
38
+ let take_count = max_chars.saturating_sub(3).max(1);
39
+ let prefix: String = text.chars().take(take_count).collect();
40
+ format!("{prefix}...")
41
+ }
23
42
 
24
43
  pub static SESSION_APPROVED: std::sync::atomic::AtomicBool =
25
44
  std::sync::atomic::AtomicBool::new(false);
@@ -32,6 +51,7 @@ pub static SECURITY_SESSION_APPROVED: std::sync::atomic::AtomicBool =
32
51
  std::sync::atomic::AtomicBool::new(false);
33
52
 
34
53
  pub struct InteractiveSession {
54
+ pub chat_id: String,
35
55
  pub config: MintConfig,
36
56
  pub current_dir: PathBuf,
37
57
  pub fast_mode: bool,
@@ -44,6 +64,7 @@ pub struct InteractiveSession {
44
64
  pub struct InteractiveInput {
45
65
  pub text: String,
46
66
  pub pasted_image: Option<String>,
67
+ pub switch_mode: bool,
47
68
  }
48
69
 
49
70
  /// What the slash-command router wants the loop to do next.
@@ -56,52 +77,82 @@ pub enum SlashResult {
56
77
  Exit,
57
78
  }
58
79
 
59
- fn apply_welcome_gradient(text: &str) -> String {
60
- let chars: Vec<char> = text.chars().collect();
61
- let count = chars.len();
62
- if count == 0 {
63
- return String::new();
80
+ type FullScreenUi = (
81
+ chat_tui::ChatTui,
82
+ Arc<Mutex<chat_tui::ChatViewState>>,
83
+ TuiHandle,
84
+ );
85
+
86
+ async fn run_interactive_agent_turn(
87
+ task: String,
88
+ session: &mut InteractiveSession,
89
+ pinned_mcp_server: Option<String>,
90
+ tui: &mut Option<FullScreenUi>,
91
+ ) -> Result<(Vec<String>, Option<String>)> {
92
+ let mut options = agent::AgentOptions {
93
+ fast_mode: session.fast_mode,
94
+ plan_mode: session.plan_mode,
95
+ queueing: true,
96
+ pinned_mcp_server,
97
+ chat_id: Some(session.chat_id.clone()),
98
+ tui: None,
99
+ };
100
+ let image = session.pending_image.take();
101
+ if let Some((terminal, state, handle)) = tui.as_mut() {
102
+ terminal.resume()?;
103
+ options.tui = Some(handle.clone());
104
+ let current_dir = session.current_dir.clone();
105
+ let config = session.config.clone();
106
+ let task = tokio::spawn(async move {
107
+ crate::run_code_agent_with_saved_image(
108
+ &task,
109
+ &current_dir,
110
+ &config,
111
+ image,
112
+ None,
113
+ options,
114
+ )
115
+ .await
116
+ });
117
+ let result = terminal.drive_agent(handle, task).await;
118
+ if let Ok(mut state) = state.lock() {
119
+ state.advance_sync_cursor();
120
+ }
121
+ result?
122
+ } else {
123
+ crate::run_code_agent_with_saved_image(
124
+ &task,
125
+ &session.current_dir,
126
+ &session.config,
127
+ image,
128
+ None,
129
+ options,
130
+ )
131
+ .await
64
132
  }
133
+ }
65
134
 
66
- // Gradient stops: Mint (105, 230, 166) -> Sky Blue (72, 202, 228) -> Deep Blue (0, 119, 182)
67
- let stops = [
68
- (105.0, 230.0, 166.0), // Mint Green
69
- (72.0, 202.0, 228.0), // Sky Blue
70
- (0.0, 119.0, 182.0), // Deep Blue
71
- ];
135
+ fn report_interactive_turn_error(tui: &Option<FullScreenUi>, error: &anyhow::Error) {
136
+ if let Some((_, _, handle)) = tui {
137
+ handle.push_notice(format!("Turn failed: {error}"));
138
+ } else {
139
+ print_turn_error(error);
140
+ }
141
+ }
72
142
 
143
+ fn apply_welcome_gradient(text: &str) -> String {
144
+ let chars: Vec<char> = text.chars().collect();
73
145
  let mut result = String::new();
74
- for (i, &c) in chars.iter().enumerate() {
146
+ for &c in &chars {
75
147
  if c == ' ' {
76
148
  result.push(c);
77
149
  continue;
78
150
  }
79
- let t = if count > 1 {
80
- i as f32 / (count - 1) as f32
81
- } else {
82
- 0.0
83
- };
84
-
85
- let (r, g, b) = if t <= 0.5 {
86
- let local_t = t * 2.0;
87
- let r = stops[0].0 + (stops[1].0 - stops[0].0) * local_t;
88
- let g = stops[0].1 + (stops[1].1 - stops[0].1) * local_t;
89
- let b = stops[0].2 + (stops[1].2 - stops[0].2) * local_t;
90
- (r, g, b)
91
- } else {
92
- let local_t = (t - 0.5) * 2.0;
93
- let r = stops[1].0 + (stops[2].0 - stops[1].0) * local_t;
94
- let g = stops[1].1 + (stops[2].1 - stops[1].1) * local_t;
95
- let b = stops[1].2 + (stops[2].2 - stops[1].2) * local_t;
96
- (r, g, b)
97
- };
98
-
99
151
  result.push_str(&format!(
100
- "\x1b[38;2;{};{};{}m{}\x1b[0m",
101
- r.round() as u8,
102
- g.round() as u8,
103
- b.round() as u8,
104
- c
152
+ "{}{}{}",
153
+ crate::terminal_theme::ANSI_ACCENT,
154
+ c,
155
+ crate::terminal_theme::ANSI_RESET
105
156
  ));
106
157
  }
107
158
  result
@@ -263,6 +314,16 @@ pub async fn run_interactive_chat_with_options(
263
314
  model_override: Option<String>,
264
315
  fast_mode: bool,
265
316
  plan_mode: bool,
317
+ ) -> Result<()> {
318
+ run_interactive_chat_with_session(model_override, fast_mode, plan_mode, None, true).await
319
+ }
320
+
321
+ pub async fn run_interactive_chat_with_session(
322
+ model_override: Option<String>,
323
+ fast_mode: bool,
324
+ plan_mode: bool,
325
+ resume_id: Option<String>,
326
+ use_tui: bool,
266
327
  ) -> Result<()> {
267
328
  let mut config = mint_core::load_config()?;
268
329
  if let Some(ref m) = model_override {
@@ -271,20 +332,32 @@ pub async fn run_interactive_chat_with_options(
271
332
 
272
333
  let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
273
334
 
274
- // Notifies this prompt loop when web/desktop writes a message into the
275
- // same, workspace-scoped "cli" conversation while this terminal is open
276
- // — see live_sync's module docs for why this is DB polling rather than
277
- // a server push.
278
- mint_core::live_sync::start_live_sync_poller(mint_core::scoped_chat_id(
279
- mint_core::CHAT_CLI_ID,
280
- Some(&current_dir.to_string_lossy()),
281
- ));
282
-
283
- print_welcome_banner(&config);
284
- println!("Type naturally or /help for commands. Ctrl+V pastes images. Ctrl+D exits.\n");
335
+ let (chat_id, prompt_resume_at_start) = if let Some(rid) = resume_id {
336
+ if rid == "__prompt__" {
337
+ (mint_core::generate_cli_session_id(), true)
338
+ } else {
339
+ let trimmed = rid.trim().to_string();
340
+ let candidate = if !trimmed.starts_with("cli::") && trimmed != mint_core::CHAT_CLI_ID {
341
+ format!("cli::{trimmed}")
342
+ } else {
343
+ trimmed.clone()
344
+ };
345
+ if let Ok(memory) = mint_core::MemoryStore::open_default()
346
+ && let Ok(sessions) = memory.list_chat_sessions()
347
+ && sessions.iter().any(|s| s.id == candidate)
348
+ {
349
+ (candidate, false)
350
+ } else {
351
+ (trimmed, false)
352
+ }
353
+ }
354
+ } else {
355
+ (mint_core::generate_cli_session_id(), false)
356
+ };
285
357
 
286
358
  let mut session = InteractiveSession {
287
- config,
359
+ chat_id,
360
+ config: config.clone(),
288
361
  current_dir: current_dir.clone(),
289
362
  fast_mode,
290
363
  plan_mode,
@@ -293,9 +366,90 @@ pub async fn run_interactive_chat_with_options(
293
366
  jobs: BackgroundJobs::new(),
294
367
  };
295
368
 
369
+ let mut tui = if use_tui {
370
+ match chat_tui::ChatTui::enter(&session.current_dir) {
371
+ Ok(terminal) => {
372
+ let state = chat_tui::ChatViewState::from_session(&session);
373
+ let state = Arc::new(Mutex::new(state));
374
+ let handle = chat_tui::ChatTui::handle(Arc::clone(&state));
375
+ Some((terminal, state, handle))
376
+ }
377
+ Err(error) => {
378
+ println!(
379
+ "{WARN}Could not start full-screen TUI: {error}. Using classic mode.{RESET}\n"
380
+ );
381
+ None
382
+ }
383
+ }
384
+ } else {
385
+ None
386
+ };
387
+
388
+ // Classic CLI prints short sync notices; the TUI consumes persisted turns
389
+ // directly and must not accumulate an undrained notice queue.
390
+ let mut classic_sync_started = false;
391
+ if tui.is_none() {
392
+ mint_core::live_sync::start_live_sync_poller(session.chat_id.clone());
393
+ classic_sync_started = true;
394
+ }
395
+
396
+ if tui.is_none() {
397
+ print_welcome_banner(&session.config);
398
+
399
+ if let Ok(memory) = mint_core::MemoryStore::open_default() {
400
+ let sessions = memory.list_chat_sessions().unwrap_or_default();
401
+ if let Some(target) = sessions.iter().find(|s| s.id == session.chat_id) {
402
+ println!(
403
+ "{MINT}●{RESET} Resumed session: {BOLD}{}{RESET} {DIM}({}){RESET}",
404
+ target.title, target.id
405
+ );
406
+ if let Ok(recent) = memory.get_session_preview(&session.chat_id, 2)
407
+ && let Some(last) = recent.first()
408
+ {
409
+ let snippet = truncate_utf8(&last.user_text, 60);
410
+ println!(" {DIM}Last turn: {snippet}{RESET}");
411
+ }
412
+ println!();
413
+ }
414
+ }
415
+
416
+ println!("Type naturally or /help for commands. F6: TUI. Ctrl+D exits.\n");
417
+ }
418
+
419
+ if prompt_resume_at_start {
420
+ let mut ui: Box<dyn CommandUi> = match tui.as_mut() {
421
+ Some((terminal, state, handle)) => {
422
+ Box::new(FullScreenCommandUi::new(terminal, state, handle))
423
+ }
424
+ None => Box::new(ClassicCommandUi::new()),
425
+ };
426
+ match prompt_resume_session_picker_with_ui(
427
+ ui.as_mut(),
428
+ &session.current_dir,
429
+ &session.chat_id,
430
+ ) {
431
+ Ok(Some(target_id)) => {
432
+ session.chat_id = target_id.clone();
433
+ mint_core::live_sync::update_live_sync_chat_id(&session.chat_id);
434
+ ui.reload_transcript(&session.chat_id, &session.current_dir);
435
+ ui.push_notice(format!("Switched to session: {target_id}"));
436
+ }
437
+ Ok(None) => {
438
+ ui.push_notice("Resume cancelled. Continuing with new session.");
439
+ }
440
+ Err(err) => {
441
+ ui.push_notice(format!("Failed to load sessions: {err}"));
442
+ }
443
+ }
444
+ }
445
+
296
446
  let mut printed_update = false;
297
447
  if let Some((current, latest)) = crate::updater::get_cached_update_notice() {
298
- crate::updater::print_update_notice(&current, &latest);
448
+ if let Some((_, _, handle)) = tui.as_mut() {
449
+ handle.push_notice(crate::updater::format_tui_update_notice(&current, &latest));
450
+ } else {
451
+ crate::updater::print_update_notice(&current, &latest);
452
+ }
299
453
  printed_update = true;
300
454
  }
301
455
 
@@ -326,37 +480,55 @@ pub async fn run_interactive_chat_with_options(
326
480
  if let Ok(Some((current, latest))) = handle.await
327
481
  && !printed_update
328
482
  {
329
- crate::updater::print_update_notice(&current, &latest);
483
+ if let Some((_, _, handle)) = tui.as_mut() {
484
+ handle.push_notice(crate::updater::format_tui_update_notice(
485
+ &current, &latest,
486
+ ));
487
+ } else {
488
+ crate::updater::print_update_notice(&current, &latest);
489
+ }
330
490
  printed_update = true;
331
491
  }
332
492
  } else {
333
493
  update_handle = Some(handle);
334
494
  }
335
495
  }
496
+ if let Some((terminal, state, _)) = tui.as_mut() {
497
+ if let Ok(mut state) = state.lock() {
498
+ state.sync_session(&session);
499
+ }
500
+ terminal.resume()?;
501
+ }
336
502
 
337
- let path_str = format_path_with_tilde(&session.current_dir);
503
+ let path_str = format_workspace_with_branch(&session.current_dir);
338
504
  let model_str = active_model(&session.config.ai_provider, &session.config).to_owned();
339
505
 
340
506
  let query_str = if let Some(queued) = pending_inputs.pop_front() {
341
- let (term_width, _) = crate::markdown::terminal_size_or_default();
342
- let echo_divider = format!(
343
- "{DIM}{}{RESET}",
344
- "─".repeat((term_width as usize).saturating_sub(2))
345
- );
346
- println!("{echo_divider}");
347
- println!(" {BLUE}You ›{RESET} {}", queued);
348
- println!("{echo_divider}");
507
+ if tui.is_none() {
508
+ let (term_width, _) = crate::markdown::terminal_size_or_default();
509
+ let echo_divider = format!(
510
+ "{DIM}{}{RESET}",
511
+ "─".repeat((term_width as usize).saturating_sub(2))
512
+ );
513
+ println!("{echo_divider}");
514
+ println!(" {BLUE}You ›{RESET} {}", queued);
515
+ println!("{echo_divider}");
516
+ }
349
517
  queued
350
- } else if let Some(input) = read_line_interactive(
351
- &session.config.ai_provider,
352
- &model_str,
353
- &path_str,
354
- &session.current_dir,
355
- &session.history,
356
- &session.jobs,
357
- session.plan_mode,
358
- pending_draft.take().unwrap_or_default().as_str(),
359
- )? {
518
+ } else if let Some(input) = if let Some((terminal, state, _)) = tui.as_mut() {
519
+ terminal.read_input(state)?
520
+ } else {
521
+ read_line_interactive(
522
+ &session.config.ai_provider,
523
+ &model_str,
524
+ &path_str,
525
+ &session.current_dir,
526
+ &session.history,
527
+ &session.jobs,
528
+ session.plan_mode,
529
+ pending_draft.take().unwrap_or_default().as_str(),
530
+ )?
531
+ } {
360
532
  if let Some(uri) = input.pasted_image {
361
533
  if let Some(ref mut current) = session.pending_image {
362
534
  current.push(' ');
@@ -365,16 +537,72 @@ pub async fn run_interactive_chat_with_options(
365
537
  session.pending_image = Some(uri);
366
538
  }
367
539
  }
540
+ if input.switch_mode {
541
+ let target = if tui.is_some() { "Classic CLI" } else { "TUI" };
542
+ let choices = [
543
+ ChoiceItem::new("Stay in current mode", "stay"),
544
+ ChoiceItem::new(format!("Switch to {target}"), "switch"),
545
+ ];
546
+ let mut ui: Box<dyn CommandUi> = match tui.as_mut() {
547
+ Some((terminal, state, handle)) => {
548
+ Box::new(FullScreenCommandUi::new(terminal, state, handle))
549
+ }
550
+ None => Box::new(ClassicCommandUi::new()),
551
+ };
552
+ let confirmed = ui.prompt_choice(
553
+ "Switch CLI interface?",
554
+ &format!("Change to {target}?"),
555
+ &choices,
556
+ )? == Some(1);
557
+ drop(ui);
558
+ if !confirmed {
559
+ if tui.is_none() {
560
+ pending_draft = Some(input.text);
561
+ }
562
+ continue;
563
+ }
564
+ pending_draft = Some(input.text);
565
+ if let Some((mut terminal, _, _)) = tui.take() {
566
+ terminal.suspend();
567
+ let _ = mint_core::live_sync::take_live_sync_notices();
568
+ if !classic_sync_started {
569
+ mint_core::live_sync::start_live_sync_poller(session.chat_id.clone());
570
+ classic_sync_started = true;
571
+ }
572
+ println!("{MINT}Switched to Classic CLI. Press F6 for TUI.{RESET}");
573
+ } else {
574
+ match chat_tui::ChatTui::enter(&session.current_dir) {
575
+ Ok(terminal) => {
576
+ let mut state = chat_tui::ChatViewState::from_session(&session);
577
+ state.set_draft(pending_draft.take().unwrap_or_default());
578
+ let state = Arc::new(Mutex::new(state));
579
+ let handle = chat_tui::ChatTui::handle(Arc::clone(&state));
580
+ tui = Some((terminal, state, handle));
581
+ }
582
+ Err(error) => println!("{WARN}Could not start TUI: {error}.{RESET}"),
583
+ }
584
+ }
585
+ continue;
586
+ }
368
587
  let text = input.text.trim().to_owned();
369
588
  if text.is_empty() {
370
589
  continue;
371
590
  }
372
591
  text
373
592
  } else {
593
+ if let Some((terminal, _, _)) = tui.as_mut() {
594
+ terminal.suspend();
595
+ }
374
596
  print_exit_message(&session);
375
597
  break;
376
598
  };
377
599
 
600
+ if let Some((_, state, _)) = tui.as_mut()
601
+ && let Ok(mut state) = state.lock()
602
+ {
603
+ state.push_user(query_str.clone());
604
+ }
605
+
378
606
  record_prompt(&mut session.history, &query_str);
379
607
 
380
608
  // An `@servername` mention anywhere in the query (picked from the
@@ -397,26 +625,42 @@ pub async fn run_interactive_chat_with_options(
397
625
 
398
626
  let skill_name = skill_word.trim_start_matches('$').to_lowercase();
399
627
  let skills = load_all_available_skills(&session.current_dir);
400
- let skill_opt = skills.iter().find(|s| s.name.to_lowercase() == skill_name);
628
+ let skill_opt = skills
629
+ .iter()
630
+ .find(|s| s.name.to_lowercase() == skill_name)
631
+ .cloned();
401
632
 
402
633
  if let Some(skill) = skill_opt {
403
- println!("\n{BLUE}Skill: {}{RESET}", skill.name);
404
- if let Some(ref desc) = skill.description {
405
- println!("{DIM}{}{RESET}", desc);
406
- }
407
- println!("{DIM}────────────────────────────────────────────{RESET}");
408
- println!("{}", skill.content);
409
- println!("{DIM}────────────────────────────────────────────{RESET}\n");
410
-
411
- if confirm(&format!("Activate skill '{}'? [y/N] ", skill.name))? {
634
+ let mut ui: Box<dyn CommandUi> = match tui.as_mut() {
635
+ Some((terminal, state, handle)) => {
636
+ Box::new(FullScreenCommandUi::new(terminal, state, handle))
637
+ }
638
+ None => Box::new(ClassicCommandUi::new()),
639
+ };
640
+
641
+ let description = skill.description.as_deref().unwrap_or("");
642
+ ui.push_command_output(format!(
643
+ "Skill: {}\n{}\n\n{}",
644
+ skill.name, description, skill.content
645
+ ));
646
+ let approved = ui
647
+ .prompt_confirm(&format!("Activate skill '{}'?", skill.name), true)
648
+ .unwrap_or(false);
649
+
650
+ if approved {
412
651
  let final_task = if task_part.is_empty() {
413
- print!("Enter task for this skill: ");
414
- let _ = io::stdout().flush();
415
- let mut input = String::new();
416
- io::stdin().read_line(&mut input)?;
652
+ let input = ui
653
+ .prompt_text(
654
+ &format!("Task for {}", skill.name),
655
+ "Describe what this skill should do",
656
+ None,
657
+ )
658
+ .ok()
659
+ .flatten()
660
+ .unwrap_or_default();
417
661
  let input = input.trim().to_owned();
418
662
  if input.is_empty() {
419
- println!("{WARN}Cancelled: Task cannot be empty.{RESET}\n");
663
+ ui.push_notice("Cancelled: task cannot be empty");
420
664
  continue;
421
665
  }
422
666
  input
@@ -432,22 +676,14 @@ pub async fn run_interactive_chat_with_options(
432
676
  skill.name, skill.content, final_task
433
677
  );
434
678
 
435
- println!();
436
- println!("{MINT}●{RESET} \x1b[1mSkill({}){RESET}", skill.name);
437
- println!(" {DIM}└ Successfully loaded skill{RESET}");
438
- println!();
439
- match crate::run_code_agent_with_saved_image(
440
- &task_with_skill,
441
- &session.current_dir,
442
- &session.config,
443
- session.pending_image.take(),
444
- None,
445
- agent::AgentOptions {
446
- fast_mode: session.fast_mode,
447
- plan_mode: session.plan_mode,
448
- queueing: true,
449
- pinned_mcp_server: pinned_mcp_server.clone(),
450
- },
679
+ ui.push_notice(format!("Skill({}) loaded", skill.name));
680
+ drop(ui);
681
+
682
+ match run_interactive_agent_turn(
683
+ task_with_skill,
684
+ &mut session,
685
+ pinned_mcp_server.clone(),
686
+ &mut tui,
451
687
  )
452
688
  .await
453
689
  {
@@ -455,40 +691,46 @@ pub async fn run_interactive_chat_with_options(
455
691
  pending_inputs.extend(queued);
456
692
  pending_draft = draft;
457
693
  }
458
- Err(error) => print_turn_error(&error),
694
+ Err(error) => report_interactive_turn_error(&tui, &error),
459
695
  }
460
696
  } else {
461
- println!("{DIM}Cancelled.{RESET}\n");
697
+ ui.push_notice("Skill activation cancelled");
462
698
  }
463
699
  } else {
464
- println!("{ERROR}Skill '{}' not found.{RESET}\n", skill_name);
700
+ let mut ui: Box<dyn CommandUi> = match tui.as_mut() {
701
+ Some((terminal, state, handle)) => {
702
+ Box::new(FullScreenCommandUi::new(terminal, state, handle))
703
+ }
704
+ None => Box::new(ClassicCommandUi::new()),
705
+ };
706
+ ui.push_notice(format!("Skill '{skill_name}' not found"));
465
707
  }
466
708
  continue;
467
709
  }
468
710
 
469
- // Run slash-command router
470
- match handle_slash_command(&mut session, &query_str).await {
711
+ // Run slash-command router via unified CommandUi abstraction.
712
+ let mut ui: Box<dyn CommandUi> = match tui.as_mut() {
713
+ Some((terminal, state, handle)) => {
714
+ Box::new(FullScreenCommandUi::new(terminal, state, handle))
715
+ }
716
+ None => Box::new(ClassicCommandUi::new()),
717
+ };
718
+ let slash_result = handle_slash_command(&mut session, ui.as_mut(), &query_str).await;
719
+ drop(ui);
720
+
721
+ match slash_result {
471
722
  Some(SlashResult::Handled) => continue,
472
723
  Some(SlashResult::Exit) => {
473
724
  print_exit_message(&session);
474
725
  break;
475
726
  }
476
-
477
727
  Some(SlashResult::ForwardToAgent(task)) => {
478
- // Force code agent for /code forwarded tasks
479
728
  println!();
480
- match crate::run_code_agent_with_saved_image(
481
- &task,
482
- &session.current_dir,
483
- &session.config,
484
- session.pending_image.take(),
485
- None,
486
- agent::AgentOptions {
487
- fast_mode: session.fast_mode,
488
- plan_mode: session.plan_mode,
489
- queueing: true,
490
- pinned_mcp_server: pinned_mcp_server.clone(),
491
- },
729
+ match run_interactive_agent_turn(
730
+ task,
731
+ &mut session,
732
+ pinned_mcp_server.clone(),
733
+ &mut tui,
492
734
  )
493
735
  .await
494
736
  {
@@ -496,7 +738,7 @@ pub async fn run_interactive_chat_with_options(
496
738
  pending_inputs.extend(queued);
497
739
  pending_draft = draft;
498
740
  }
499
- Err(error) => print_turn_error(&error),
741
+ Err(error) => report_interactive_turn_error(&tui, &error),
500
742
  }
501
743
  continue;
502
744
  }
@@ -507,18 +749,11 @@ pub async fn run_interactive_chat_with_options(
507
749
  // Note: /code is fully handled by handle_slash_command above
508
750
  // (its "/code" arm always returns Some(...)), so no separate
509
751
  // "/code " fallback is needed here.
510
- match crate::run_code_agent_with_saved_image(
511
- &query_str,
512
- &session.current_dir,
513
- &session.config,
514
- session.pending_image.take(),
515
- None,
516
- agent::AgentOptions {
517
- fast_mode: session.fast_mode,
518
- plan_mode: session.plan_mode,
519
- queueing: true,
520
- pinned_mcp_server: pinned_mcp_server.clone(),
521
- },
752
+ match run_interactive_agent_turn(
753
+ query_str,
754
+ &mut session,
755
+ pinned_mcp_server.clone(),
756
+ &mut tui,
522
757
  )
523
758
  .await
524
759
  {
@@ -526,7 +761,7 @@ pub async fn run_interactive_chat_with_options(
526
761
  pending_inputs.extend(queued);
527
762
  pending_draft = draft;
528
763
  }
529
- Err(error) => print_turn_error(&error),
764
+ Err(error) => report_interactive_turn_error(&tui, &error),
530
765
  }
531
766
  }
532
767
 
@@ -542,8 +777,23 @@ pub fn print_exit_message(session: &InteractiveSession) {
542
777
  );
543
778
  println!(
544
779
  "{DIM}Workspace:{RESET} {}",
545
- format_path_with_tilde(&session.current_dir)
780
+ format_workspace_with_branch(&session.current_dir)
546
781
  );
782
+ let has_history = if let Ok(memory) = MemoryStore::open_default() {
783
+ memory
784
+ .recent_interactions_for_chat(&session.chat_id, 1)
785
+ .map(|rows| !rows.is_empty())
786
+ .unwrap_or(false)
787
+ } else {
788
+ false
789
+ };
790
+
791
+ if has_history {
792
+ println!("\n{DIM}Resume this session with:{RESET}");
793
+ println!("{BOLD}mint --resume {}{RESET}\n", session.chat_id);
794
+ } else {
795
+ println!();
796
+ }
547
797
  println!("{DIM}Saved config stays available for the next Mint run.{RESET}");
548
798
  println!("{MINT}See you next time.{RESET}\n");
549
799
  }
@@ -589,3 +839,17 @@ pub fn load_all_available_skills(current_dir: &Path) -> Vec<mint_core::LearnedSk
589
839
  }
590
840
  unique_skills.into_values().collect()
591
841
  }
842
+
843
+ #[cfg(test)]
844
+ mod tests {
845
+ use super::*;
846
+
847
+ #[test]
848
+ fn test_truncate_utf8_multibyte_safety() {
849
+ let thai_input = "'/home/pheem49/vscode/Project/Mint-CLI/Release_Note.md'สรุปไฟล์นี้ให้หน่อย";
850
+ for len in 1..=thai_input.chars().count() + 5 {
851
+ let truncated = truncate_utf8(thai_input, len);
852
+ assert!(!truncated.is_empty());
853
+ }
854
+ }
855
+ }