@pheem49/mint 1.17.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (421) hide show
  1. package/Cargo.lock +6 -6
  2. package/Cargo.toml +2 -2
  3. package/README.md +8 -2
  4. package/Release_Note.md +222 -71
  5. package/crates/mint-cli/src/agent/diff_render.rs +66 -44
  6. package/crates/mint-cli/src/agent/live_status.rs +21 -4
  7. package/crates/mint-cli/src/agent/markdown_render.rs +342 -5
  8. package/crates/mint-cli/src/agent.rs +25 -10
  9. package/crates/mint-cli/src/commands/agent.rs +4 -92
  10. package/crates/mint-cli/src/commands/browser.rs +2 -15
  11. package/crates/mint-cli/src/commands/integrations.rs +3 -3
  12. package/crates/mint-cli/src/commands/mod.rs +0 -3
  13. package/crates/mint-cli/src/commands/tailnet_web.rs +1 -0
  14. package/crates/mint-cli/src/interactive/chat_tui/dialog.rs +572 -0
  15. package/crates/mint-cli/src/interactive/chat_tui/mod.rs +1427 -0
  16. package/crates/mint-cli/src/interactive/chat_tui/render.rs +1524 -0
  17. package/crates/mint-cli/src/interactive/chat_tui/selection.rs +401 -0
  18. package/crates/mint-cli/src/interactive/chat_tui/state.rs +1833 -0
  19. package/crates/mint-cli/src/interactive/chat_tui/tests.rs +3414 -0
  20. package/crates/mint-cli/src/interactive/chat_tui/thought.rs +202 -0
  21. package/crates/mint-cli/src/interactive/chat_tui/transcript.rs +728 -0
  22. package/crates/mint-cli/src/interactive/chat_tui/watermark.rs +148 -0
  23. package/crates/mint-cli/src/interactive/command_ui.rs +53 -5
  24. package/crates/mint-cli/src/interactive/composer.rs +186 -0
  25. package/crates/mint-cli/src/interactive/format.rs +78 -3
  26. package/crates/mint-cli/src/interactive/input_box.rs +61 -1
  27. package/crates/mint-cli/src/interactive/resume_picker.rs +367 -25
  28. package/crates/mint-cli/src/interactive/slash_commands.rs +648 -371
  29. package/crates/mint-cli/src/interactive/tool_activity.rs +93 -20
  30. package/crates/mint-cli/src/interactive.rs +37 -0
  31. package/crates/mint-cli/src/main.rs +6 -3
  32. package/crates/mint-cli/src/markdown.rs +2 -37
  33. package/crates/mint-cli/src/onboard.rs +700 -282
  34. package/crates/mint-cli/src/setup.rs +1342 -624
  35. package/crates/mint-cli/src/terminal_theme.rs +159 -35
  36. package/crates/mint-cli/tests/library_intake.rs +1 -0
  37. package/crates/mint-core/src/agent/chat/anthropic.rs +318 -0
  38. package/crates/mint-core/src/agent/chat/custom.rs +149 -0
  39. package/crates/mint-core/src/agent/chat/gemini.rs +518 -0
  40. package/crates/mint-core/src/agent/chat/mod.rs +857 -0
  41. package/crates/mint-core/src/agent/chat/ollama.rs +321 -0
  42. package/crates/mint-core/src/agent/chat/openai.rs +582 -0
  43. package/crates/mint-core/src/agent/chat/streaming.rs +469 -0
  44. package/crates/mint-core/src/agent/chat/tests.rs +1479 -0
  45. package/crates/mint-core/src/agent/memory.rs +56 -2
  46. package/crates/mint-core/src/agent/tasks.rs +2 -2
  47. package/crates/mint-core/src/api_server/routes/chat.rs +24 -2
  48. package/crates/mint-core/src/api_server/routes/gemini_live.rs +14 -1
  49. package/crates/mint-core/src/api_server/routes/html_preview.rs +1 -8
  50. package/crates/mint-core/src/api_server/routes/sessions.rs +21 -0
  51. package/crates/mint-core/src/avatar_bridge.rs +0 -22
  52. package/crates/mint-core/src/browser/cdp.rs +10 -4
  53. package/crates/mint-core/src/browser/headless.rs +582 -0
  54. package/crates/mint-core/src/browser/input.rs +7 -62
  55. package/crates/mint-core/src/browser/interact.rs +0 -14
  56. package/crates/mint-core/src/browser/mod.rs +8 -29
  57. package/crates/mint-core/src/browser/navigate.rs +2 -36
  58. package/crates/mint-core/src/browser/runtime.rs +2 -4
  59. package/crates/mint-core/src/browser/session.rs +50 -466
  60. package/crates/mint-core/src/browser/workflow.rs +142 -32
  61. package/crates/mint-core/src/cron/store.rs +2 -2
  62. package/crates/mint-core/src/integrations/mcp.rs +6 -8
  63. package/crates/mint-core/src/lib.rs +0 -5
  64. package/crates/mint-core/src/media/gemini_live.rs +636 -86
  65. package/crates/mint-core/src/media/library/migration.rs +26 -0
  66. package/crates/mint-core/src/media/library/tests.rs +1 -1
  67. package/crates/mint-core/src/media/library/thumbnails.rs +8 -2
  68. package/crates/mint-core/src/media/pictures.rs +1 -1
  69. package/crates/mint-core/src/media/tool_images.rs +92 -1
  70. package/crates/mint-core/src/mods/manager.rs +101 -35
  71. package/crates/mint-core/src/orchestration/context_render.rs +441 -24
  72. package/crates/mint-core/src/orchestration/decision_parsing.rs +531 -16
  73. package/crates/mint-core/src/orchestration/full_skill_result_tests.rs +12 -0
  74. package/crates/mint-core/src/orchestration/loop_guard.rs +145 -0
  75. package/crates/mint-core/src/orchestration/mcp_outcome_tests.rs +864 -0
  76. package/crates/mint-core/src/orchestration/memory_skill.rs +88 -28
  77. package/crates/mint-core/src/orchestration/mod.rs +320 -4249
  78. package/crates/mint-core/src/orchestration/reliability.rs +67 -27
  79. package/crates/mint-core/src/orchestration/review_regressions.rs +5 -0
  80. package/crates/mint-core/src/orchestration/tests.rs +1665 -0
  81. package/crates/mint-core/src/orchestration/tools/dispatch.rs +967 -0
  82. package/crates/mint-core/src/orchestration/tools/files.rs +1 -0
  83. package/crates/mint-core/src/orchestration/tools/mod.rs +5 -1
  84. package/crates/mint-core/src/orchestration/tools/planning.rs +102 -42
  85. package/crates/mint-core/src/orchestration/tools/shell.rs +129 -58
  86. package/crates/mint-core/src/orchestration/truncation.rs +170 -13
  87. package/crates/mint-core/src/orchestration/types.rs +648 -0
  88. package/crates/mint-core/src/orchestration/verification.rs +0 -3
  89. package/crates/mint-core/src/orchestration/workspace_helpers.rs +24 -6
  90. package/crates/mint-core/src/prompts/agent.rs +52 -76
  91. package/crates/mint-core/src/prompts/tool_catalog.rs +8 -151
  92. package/crates/mint-core/src/search/files.rs +20 -0
  93. package/crates/mint-core/src/slash/mod.rs +228 -265
  94. package/crates/mint-core/src/slash/models.rs +6 -1
  95. package/crates/mint-core/src/system/bg_shell.rs +1 -0
  96. package/crates/mint-core/src/system/config.rs +176 -34
  97. package/crates/mint-mod-runtime/src/lib.rs +37 -23
  98. package/out/web/assets/ArtifactPreviewPanel-Cx6BVOOF.js +2 -0
  99. package/out/web/assets/CalculationCard-D2E74u5q.js +1 -0
  100. package/out/web/assets/CliSessionsView-ZbdtSjvK.css +1 -0
  101. package/out/web/assets/{CliSessionsView-MI8kXMAb.js → CliSessionsView-z5i6qGyb.js} +1 -1
  102. package/out/web/assets/CodeReviewPage-BK2bOScd.css +1 -0
  103. package/out/web/assets/CodeReviewPage-Dp6zHuHu.js +2 -0
  104. package/out/web/assets/{CommandPalette-BD8SlTE5.js → CommandPalette-DaKlzbKs.js} +1 -1
  105. package/out/web/assets/ImageGenCard-BMCJHP9O.js +1 -0
  106. package/out/web/assets/ImageSearchCard-Cld_SOUg.js +1 -0
  107. package/out/web/assets/{ImageStudioPanel-BP7N4rLr.js → ImageStudioPanel-B5N7TjeB.js} +1 -1
  108. package/out/web/assets/LibraryPage-CMB89rJ0.css +1 -0
  109. package/out/web/assets/LibraryPage-DbZEi4W_.js +2 -0
  110. package/out/web/assets/LinkedFoldersView-9B9DIPoZ.js +1 -0
  111. package/out/web/assets/{McpRegistryPicker-CoS83vtc.js → McpRegistryPicker-DnXPlzI7.js} +1 -1
  112. package/out/web/assets/McpServersView-CiNBNUl4.js +1 -0
  113. package/out/web/assets/MermaidCard-BBDNEXbY.js +2 -0
  114. package/out/web/assets/MintDashboard-C_UYPoNV.js +119 -0
  115. package/out/web/assets/MintDashboard-DTd8C_c8.css +1 -0
  116. package/out/web/assets/PlanCard-C2x5pajq.js +1 -0
  117. package/out/web/assets/{PluginsView-jBYmcKh4.js → PluginsView-DoTg9MVa.js} +1 -1
  118. package/out/web/assets/RewindModal-B5oowrR0.js +1 -0
  119. package/out/web/assets/{ScheduledTasksView-5uw9-V9H.js → ScheduledTasksView-BD5DVPkZ.js} +1 -1
  120. package/out/web/assets/{SelectField-DXBQtrUK.js → SelectField-Cy6CghrU.js} +1 -1
  121. package/out/web/assets/SettingsWindow-BYl_oCFh.js +4 -0
  122. package/out/web/assets/SettingsWindow-Ckcgnjt8.css +1 -0
  123. package/out/web/assets/{SkillsView-C-gp9J7m.js → SkillsView-CIeWwq5z.js} +1 -1
  124. package/out/web/assets/StockCard-DxUciKyp.js +1 -0
  125. package/out/web/assets/ToolSurfacePage-qBgs_VHq.css +1 -0
  126. package/out/web/assets/ToolSurfacePage-saVbVrkE.js +38 -0
  127. package/out/web/assets/{UiFeatureCard-6BwxTOCe.js → UiFeatureCard-CdY0hGWy.js} +1 -1
  128. package/out/web/assets/{UiGridCard-DvZcLNxb.js → UiGridCard-BBK3I5hC.js} +1 -1
  129. package/out/web/assets/UiMockupWidget-CpR9EDuc.js +1 -0
  130. package/out/web/assets/{VeoStudioPanel-DOj7_WR3.css → VeoStudioPanel-9kU9YLEN.css} +1 -1
  131. package/out/web/assets/{VeoStudioPanel-DfsOJKv0.js → VeoStudioPanel-Co6-wEWM.js} +2 -2
  132. package/out/web/assets/WeatherCard-Buzi7Vfu.js +1 -0
  133. package/out/web/assets/WorkspacePdfPreview-Bi8Zzyir.js +2 -0
  134. package/out/web/assets/{abnfDiagram-VCTEODGH-BOo3Ckng.js → abnfDiagram-VCTEODGH-CMfR95N2.js} +1 -1
  135. package/out/web/assets/{architecture-7GRP2DOG-ZOwheW3n.js → architecture-7GRP2DOG-DhAM4HyO.js} +1 -1
  136. package/out/web/assets/{architectureDiagram-5GKGNRK7-DC2FDzVd.js → architectureDiagram-5GKGNRK7-Yk3TUJ_F.js} +1 -1
  137. package/out/web/assets/{blockDiagram-I7D4REHJ-BrKFWdAH.js → blockDiagram-I7D4REHJ-X9fBgJik.js} +1 -1
  138. package/out/web/assets/{c4Diagram-7LVT6UL2-BHTHK1Yd.js → c4Diagram-7LVT6UL2-Bk9x7N-8.js} +1 -1
  139. package/out/web/assets/{chunk-4HAMMTFA-BYFkZwNj.js → chunk-4HAMMTFA-Dx5fk1_0.js} +1 -1
  140. package/out/web/assets/{chunk-75Z2AOVW-BSKfSKSA.js → chunk-75Z2AOVW-BszTQoM4.js} +1 -1
  141. package/out/web/assets/{chunk-DU6HZSFF-vIhsiW6n.js → chunk-DU6HZSFF-DK-As3rk.js} +1 -1
  142. package/out/web/assets/{chunk-F27PBJKO-BlYpW9xq.js → chunk-F27PBJKO-LmncZZIS.js} +1 -1
  143. package/out/web/assets/{chunk-GMAD6QVW-BIBz_Ug5.js → chunk-GMAD6QVW-DSQ_sDRJ.js} +1 -1
  144. package/out/web/assets/{chunk-GVQU2GXP-NPSHxeqC.js → chunk-GVQU2GXP-Cno3ulje.js} +1 -1
  145. package/out/web/assets/{chunk-IMKFNOWR-YlJK8_Fp.js → chunk-IMKFNOWR-bIzfY9Jc.js} +1 -1
  146. package/out/web/assets/{chunk-L3NEJ4N5-DMYi4-af.js → chunk-L3NEJ4N5-Dl6eOa0D.js} +1 -1
  147. package/out/web/assets/{chunk-OSK3NFVY-Begd3-jA.js → chunk-OSK3NFVY-BaUGJ-cM.js} +1 -1
  148. package/out/web/assets/{chunk-P2QGCYS3-D1I4xFHN.js → chunk-P2QGCYS3-_066ndhH.js} +1 -1
  149. package/out/web/assets/{chunk-POPQ4Y6H-CafZZzNE.js → chunk-POPQ4Y6H-YT1AKhTv.js} +1 -1
  150. package/out/web/assets/{chunk-PWAF6VOD-Dwh6_Lnt.js → chunk-PWAF6VOD-CrEgDsxh.js} +1 -1
  151. package/out/web/assets/{chunk-SHT3W25Y-B0XrCSEb.js → chunk-SHT3W25Y-_KwaRLOl.js} +1 -1
  152. package/out/web/assets/{chunk-SVP7TREG-CxLsddxC.js → chunk-SVP7TREG-BQ1qb32L.js} +1 -1
  153. package/out/web/assets/{chunk-TICWLB2K-y156QInb.js → chunk-TICWLB2K-BDyehCtg.js} +1 -1
  154. package/out/web/assets/classDiagram-ZZMXUADV-BoSpzRCJ.js +1 -0
  155. package/out/web/assets/classDiagram-v2-VYDZK3BY-BoSpzRCJ.js +1 -0
  156. package/out/web/assets/{config-DqXJXeZM.css → config-2suVFPZg.css} +1 -1
  157. package/out/web/assets/config-CkRCdkxn.js +2 -0
  158. package/out/web/assets/{cynefin-OW5HDTMX-SMVvrLf-.js → cynefin-OW5HDTMX-Dl_31aaN.js} +1 -1
  159. package/out/web/assets/{cynefinDiagram-5FMLGOSQ-rZznN24T.js → cynefinDiagram-5FMLGOSQ-Bpir8jha.js} +1 -1
  160. package/out/web/assets/{dagre-GXQ25YYZ-BOToydFu.js → dagre-GXQ25YYZ-D9xu3nsq.js} +1 -1
  161. package/out/web/assets/{diagram-S7CK7UJ4-TMVaGQEJ.js → diagram-S7CK7UJ4-DeveoEeB.js} +1 -1
  162. package/out/web/assets/{diagram-UQ7AKVKN-C2JK-GP2.js → diagram-UQ7AKVKN-p4xWRESV.js} +1 -1
  163. package/out/web/assets/{diagram-VSXAHHWV-Cw8VSi2K.js → diagram-VSXAHHWV-C7qz9NDF.js} +1 -1
  164. package/out/web/assets/{diagram-VX7I27RA-DXp4fKk9.js → diagram-VX7I27RA-DRiCa3Vd.js} +1 -1
  165. package/out/web/assets/{diagram-Z3DM3KII-CzSicYiW.js → diagram-Z3DM3KII-Bt7zduQX.js} +1 -1
  166. package/out/web/assets/{ebnfDiagram-PWID7BFC-Dqj-zqPu.js → ebnfDiagram-PWID7BFC-DV9WpwdR.js} +1 -1
  167. package/out/web/assets/{erDiagram-RLTQ6QDP-DZwFZAuD.js → erDiagram-RLTQ6QDP-BJ_nwG2m.js} +1 -1
  168. package/out/web/assets/{eventmodeling-NTZA5JFV-C0O-Lvgp.js → eventmodeling-NTZA5JFV-BTBMrfVa.js} +1 -1
  169. package/out/web/assets/flowDiagram-HODETNUW-Cdlq3cJL.js +1 -0
  170. package/out/web/assets/{ganttDiagram-EL5Y4UJY-Da4ULXTl.js → ganttDiagram-EL5Y4UJY-DQLdsXrC.js} +1 -1
  171. package/out/web/assets/{gitGraph-4MIJSDKK-B9wNFZIP.js → gitGraph-4MIJSDKK-CL1OEOQ_.js} +1 -1
  172. package/out/web/assets/{gitGraphDiagram-WWUBYQGX-RjrhB0MP.js → gitGraphDiagram-WWUBYQGX-8cSi42H7.js} +1 -1
  173. package/out/web/assets/index-BocxnrDG.js +168 -0
  174. package/out/web/assets/index-yeh_r55a.css +1 -0
  175. package/out/web/assets/{info-A6RAGUB7-B3dfCpeY.js → info-A6RAGUB7-C1zsX5sc.js} +1 -1
  176. package/out/web/assets/{infoDiagram-27XIBGKW-QVWkLVx7.js → infoDiagram-27XIBGKW-DsRYtIyI.js} +1 -1
  177. package/out/web/assets/{ishikawaDiagram-5VMMS53U-CLFNIRI9.js → ishikawaDiagram-5VMMS53U-B2crwIXj.js} +1 -1
  178. package/out/web/assets/{journeyDiagram-3NMN7TZE-fgOQadYF.js → journeyDiagram-3NMN7TZE-BTH-GyVR.js} +1 -1
  179. package/out/web/assets/{kanban-definition-UXKFOSKX-G3Q_9g9O.js → kanban-definition-UXKFOSKX-BeRfCnuA.js} +1 -1
  180. package/out/web/assets/{mermaid-parser.core-v3Jm7nco.js → mermaid-parser.core-BJwgCBBc.js} +3 -3
  181. package/out/web/assets/{mermaid.core-DTEjLUA1.js → mermaid.core-CsDDodN8.js} +4 -4
  182. package/out/web/assets/{mindmap-definition-YA3MSWOX-C_D42_fF.js → mindmap-definition-YA3MSWOX-B42efOQ1.js} +1 -1
  183. package/out/web/assets/{modelManager-BPLycQrN.js → modelManager-B3ZFMh8v.js} +2 -2
  184. package/out/web/assets/{oauthManager-BUK7ic7q.js → oauthManager-Ch5Du2fF.js} +1 -1
  185. package/out/web/assets/{packet-AYTQ26CC-B-R-SHlF.js → packet-AYTQ26CC-B6xUyE6r.js} +1 -1
  186. package/out/web/assets/{pegDiagram-XKGWAZYB-Da2q_giz.js → pegDiagram-XKGWAZYB-1LabVycL.js} +1 -1
  187. package/out/web/assets/{pie-WAS4IAKB-BC8F0N7-.js → pie-WAS4IAKB-DJwo-nf_.js} +1 -1
  188. package/out/web/assets/{pieDiagram-E7YTZNPT-Iy9REJNC.js → pieDiagram-E7YTZNPT-icmAqzy4.js} +1 -1
  189. package/out/web/assets/{quadrantDiagram-AXDQQJYC-ztsiYw7h.js → quadrantDiagram-AXDQQJYC-CZ-wEx41.js} +1 -1
  190. package/out/web/assets/{radar-RG4KPBEZ-B_1P8Z_z.js → radar-RG4KPBEZ-D7d-Xriw.js} +1 -1
  191. package/out/web/assets/{railroad-74A4TZTK-DuTqczSo.js → railroad-74A4TZTK-viuhdYbs.js} +1 -1
  192. package/out/web/assets/{railroad-abnf-HS5TGJTU-Df29WLmp.js → railroad-abnf-HS5TGJTU-DNXiCNea.js} +1 -1
  193. package/out/web/assets/{railroad-ebnf-LZEXJU2U-ePFMo-qp.js → railroad-ebnf-LZEXJU2U-nkSu1-0C.js} +1 -1
  194. package/out/web/assets/{railroad-peg-WCYAUIDC-DYXLW4_E.js → railroad-peg-WCYAUIDC-BhbMeQzz.js} +1 -1
  195. package/out/web/assets/{railroadDiagram-O6MQD6OU-LStnZf2S.js → railroadDiagram-O6MQD6OU-CLpG1jUX.js} +1 -1
  196. package/out/web/assets/{requirementDiagram-BXWQKSXE-DmzonMH-.js → requirementDiagram-BXWQKSXE-kRDrvWrc.js} +1 -1
  197. package/out/web/assets/{sankeyDiagram-P5KCCOFB-B8vjmUU1.js → sankeyDiagram-P5KCCOFB-DxAwmq4x.js} +1 -1
  198. package/out/web/assets/{sequenceDiagram-WJ2MYXX4-CTnplOAX.js → sequenceDiagram-WJ2MYXX4-aLgY-6Wz.js} +1 -1
  199. package/out/web/assets/{stateDiagram-D77RDMKH-BFrIaLdI.js → stateDiagram-D77RDMKH-D5QWfOhp.js} +1 -1
  200. package/out/web/assets/stateDiagram-v2-MP3YSRHH-D6OiZoAP.js +1 -0
  201. package/out/web/assets/{swimlanes-42K2YHIH-BXGngUNU.js → swimlanes-42K2YHIH-CRs5UyA-.js} +1 -1
  202. package/out/web/assets/swimlanesDiagram-VR7AAH4N-UgEXIsV0.js +8 -0
  203. package/out/web/assets/syntaxHighlight-C-wAGT84.js +3 -0
  204. package/out/web/assets/{timeline-definition-24CTP7MA-CegH7n43.js → timeline-definition-24CTP7MA-Denqd9qb.js} +1 -1
  205. package/out/web/assets/{treeView-Q6P3EWNA-DTpJv2Tw.js → treeView-Q6P3EWNA-0my3Z3s4.js} +1 -1
  206. package/out/web/assets/{treemap-WGGIJYW6-i8M9iJU6.js → treemap-WGGIJYW6-B_EjkLYq.js} +1 -1
  207. package/out/web/assets/{vennDiagram-4TSXK5OY-Dpzo1S8U.js → vennDiagram-4TSXK5OY-DxVg3Ewr.js} +1 -1
  208. package/out/web/assets/{wardley-WFR3VGLG-BrNsgtfw.js → wardley-WFR3VGLG-CGD-Tj4p.js} +1 -1
  209. package/out/web/assets/{wardleyDiagram-VM6X3IG4-lQ92LFE1.js → wardleyDiagram-VM6X3IG4-CmfS39Xm.js} +1 -1
  210. package/out/web/assets/{xychartDiagram-S5SC5T6Z-BaOaEoBd.js → xychartDiagram-S5SC5T6Z-BVM9bKis.js} +1 -1
  211. package/out/web/index-web.html +2 -2
  212. package/out/web/index.html +2 -2
  213. package/package.json +2 -2
  214. package/shared-modules/CODEOWNERS +3 -3
  215. package/shared-modules/SDL2/SDL2_mixer.json +27 -0
  216. package/shared-modules/appstream/README.md +13 -0
  217. package/shared-modules/appstream/appstream-compose.json +111 -0
  218. package/shared-modules/dbus-glib/dbus-glib.json +2 -2
  219. package/shared-modules/libportal/libportal.json +23 -0
  220. package/shared-modules/linux-audio/fluidsynth2-static.json +2 -2
  221. package/shared-modules/linux-audio/fluidsynth2.json +2 -2
  222. package/shared-modules/linux-audio/libinstpatch.json +2 -2
  223. package/shared-modules/linux-audio/liblo-static.json +3 -0
  224. package/shared-modules/luajit/luajit.json +2 -2
  225. package/shared-modules/squashfs-tools/squashfs-tools.json +0 -3
  226. package/slash-commands.json +7 -2
  227. package/src/renderer/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  228. package/src/renderer/shared/agentProgress.ts +51 -3
  229. package/src/renderer/shared/components/Settings/AutomationTab.tsx +2 -56
  230. package/src/renderer/shared/components/Settings/AvatarCropModal.tsx +15 -1
  231. package/src/renderer/shared/components/Settings/GeneralTab.tsx +25 -12
  232. package/src/renderer/shared/components/Settings/ThemeTab.test.tsx +45 -0
  233. package/src/renderer/shared/components/Settings/ThemeTab.tsx +106 -3
  234. package/src/renderer/shared/components/activity/AgentActivityDrawer.tsx +67 -17
  235. package/src/renderer/shared/components/activity/AgentActivityTable.tsx +376 -134
  236. package/src/renderer/shared/components/activity/AskUserActivityCard.test.tsx +122 -0
  237. package/src/renderer/shared/components/activity/AskUserActivityCard.tsx +70 -0
  238. package/src/renderer/shared/components/activity/McpToolResults.tsx +39 -2
  239. package/src/renderer/shared/components/activity/SubagentDagView.tsx +7 -7
  240. package/src/renderer/shared/components/activity/ViewedImages.tsx +41 -2
  241. package/src/renderer/shared/components/app/ChunkErrorBoundary.tsx +3 -3
  242. package/src/renderer/shared/components/app/CommandPalette.tsx +7 -7
  243. package/src/renderer/shared/components/app/DesktopTitlebar.tsx +2 -2
  244. package/src/renderer/shared/components/app/MintDashboard.tsx +27 -17
  245. package/src/renderer/shared/components/app/ModalErrorBoundary.tsx +3 -3
  246. package/src/renderer/shared/components/cards/CalculationCard.tsx +3 -3
  247. package/src/renderer/shared/components/cards/ImageGenCard.tsx +2 -2
  248. package/src/renderer/shared/components/cards/ImageSearchCard.tsx +2 -2
  249. package/src/renderer/shared/components/cards/MermaidCard.tsx +1 -1
  250. package/src/renderer/shared/components/cards/PlanCard.test.tsx +41 -0
  251. package/src/renderer/shared/components/cards/PlanCard.tsx +32 -0
  252. package/src/renderer/shared/components/cards/ReleaseNotesCard.test.tsx +29 -0
  253. package/src/renderer/shared/components/cards/ReleaseNotesCard.tsx +137 -0
  254. package/src/renderer/shared/components/cards/StockCard.tsx +7 -7
  255. package/src/renderer/shared/components/cards/ToolResultCards.tsx +11 -3
  256. package/src/renderer/shared/components/cards/UiMockupWidget.tsx +4 -4
  257. package/src/renderer/shared/components/cards/WeatherCard.tsx +5 -5
  258. package/src/renderer/shared/components/chat/ApprovalCard.test.tsx +11 -0
  259. package/src/renderer/shared/components/chat/ApprovalCard.tsx +21 -2
  260. package/src/renderer/shared/components/chat/ArtifactCards.test.tsx +69 -0
  261. package/src/renderer/shared/components/chat/ArtifactCards.tsx +238 -0
  262. package/src/renderer/shared/components/chat/AttachedDocumentCard.test.tsx +39 -0
  263. package/src/renderer/shared/components/chat/AttachedDocumentCard.tsx +220 -0
  264. package/src/renderer/shared/components/chat/ChatCodeBlock.test.tsx +33 -0
  265. package/src/renderer/shared/components/chat/ChatCodeBlock.tsx +15 -1
  266. package/src/renderer/shared/components/chat/ChatMessageItem.test.tsx +40 -2
  267. package/src/renderer/shared/components/chat/ChatMessageItem.tsx +180 -34
  268. package/src/renderer/shared/components/chat/ChatModeSelector.css +227 -0
  269. package/src/renderer/shared/components/chat/ChatModeSelector.test.tsx +45 -0
  270. package/src/renderer/shared/components/chat/ChatModeSelector.tsx +198 -0
  271. package/src/renderer/shared/components/chat/ChatPanel.test.tsx +22 -0
  272. package/src/renderer/shared/components/chat/ChatPanel.tsx +227 -53
  273. package/src/renderer/shared/components/chat/DiffReviewModal.tsx +6 -6
  274. package/src/renderer/shared/components/chat/GeminiLiveOverlay.test.tsx +142 -1
  275. package/src/renderer/shared/components/chat/GeminiLiveOverlay.tsx +45 -3
  276. package/src/renderer/shared/components/chat/ModelSelectorPopover.tsx +42 -14
  277. package/src/renderer/shared/components/chat/RewindModal.tsx +10 -10
  278. package/src/renderer/shared/components/chat/SlashSuggestions.test.tsx +14 -0
  279. package/src/renderer/shared/components/chat/SourcesBlock.test.tsx +53 -0
  280. package/src/renderer/shared/components/chat/SourcesBlock.tsx +236 -90
  281. package/src/renderer/shared/components/chat/TurnFileChanges.test.tsx +45 -1
  282. package/src/renderer/shared/components/chat/TurnFileChanges.tsx +202 -169
  283. package/src/renderer/shared/components/extensions/CliSessionsView.tsx +5 -4
  284. package/src/renderer/shared/components/extensions/McpRegistryPicker.tsx +3 -3
  285. package/src/renderer/shared/components/studio/LibraryPage.tsx +48 -5
  286. package/src/renderer/shared/components/workspace/ArtifactPreviewPanel.tsx +125 -13
  287. package/src/renderer/shared/components/workspace/CodeReviewPage.test.tsx +50 -0
  288. package/src/renderer/shared/components/workspace/CodeReviewPage.tsx +77 -16
  289. package/src/renderer/shared/components/workspace/GitBranchSelector.tsx +78 -22
  290. package/src/renderer/shared/components/workspace/ToolSurfacePage.test.tsx +13 -0
  291. package/src/renderer/shared/components/workspace/ToolSurfacePage.tsx +48 -28
  292. package/src/renderer/shared/components/workspace/WorkspacePdfPreview.tsx +266 -47
  293. package/src/renderer/shared/components/workspace/WorkspacePreviewActions.test.tsx +18 -6
  294. package/src/renderer/shared/components/workspace/background-terminals.css +11 -11
  295. package/src/renderer/shared/constants/config.ts +1 -5
  296. package/src/renderer/shared/constants/models.test.ts +51 -0
  297. package/src/renderer/shared/constants/models.ts +139 -32
  298. package/src/renderer/shared/conversation/lifecycle.test.ts +91 -3
  299. package/src/renderer/shared/conversation/lifecycle.ts +104 -5
  300. package/src/renderer/shared/conversation/progressiveStream.test.ts +83 -0
  301. package/src/renderer/shared/conversation/progressiveStream.ts +219 -0
  302. package/src/renderer/shared/css/agent-observability.css +133 -0
  303. package/src/renderer/shared/css/chat-ui-cards.css +13 -13
  304. package/src/renderer/shared/css/code-review.css +63 -34
  305. package/src/renderer/shared/css/code-sessions.css +47 -18
  306. package/src/renderer/shared/css/collapsed-paste.css +1 -1
  307. package/src/renderer/shared/css/error-notice.css +1 -1
  308. package/src/renderer/shared/css/file-changes.css +165 -80
  309. package/src/renderer/shared/css/library.css +105 -10
  310. package/src/renderer/shared/css/management-views.css +1 -1
  311. package/src/renderer/shared/css/mcp-results.css +5 -5
  312. package/src/renderer/shared/css/model-selector.css +18 -18
  313. package/src/renderer/shared/css/mods.css +7 -7
  314. package/src/renderer/shared/css/notification-notice.css +2 -2
  315. package/src/renderer/shared/css/queued-messages.css +5 -5
  316. package/src/renderer/shared/css/settings/general.css +18 -13
  317. package/src/renderer/shared/css/settings/profile.css +5 -5
  318. package/src/renderer/shared/css/settings/theme.css +5 -5
  319. package/src/renderer/shared/css/slash-choice.css +2 -2
  320. package/src/renderer/shared/css/slash-suggestions.css +3 -3
  321. package/src/renderer/shared/css/sources-block.css +41 -2
  322. package/src/renderer/shared/css/tools-panel.css +2 -2
  323. package/src/renderer/shared/css/ui-tailwind.css +8 -0
  324. package/src/renderer/shared/css/veo-studio.css +2 -2
  325. package/src/renderer/shared/css/viewed-images.css +7 -7
  326. package/src/renderer/shared/platform.ts +2 -1
  327. package/src/renderer/shared/theme/themeManager.test.ts +17 -0
  328. package/src/renderer/shared/theme/themeManager.ts +21 -4
  329. package/src/renderer/shared/theme/themes.ts +54 -0
  330. package/src/renderer/shared/theme/tokens.css +6 -4
  331. package/src/renderer/shared/types.ts +1 -1
  332. package/src/renderer/shared/utils/agentActivity.test.ts +468 -2
  333. package/src/renderer/shared/utils/agentActivity.ts +602 -35
  334. package/src/renderer/shared/utils/artifactBrowser.test.ts +37 -32
  335. package/src/renderer/shared/utils/artifactBrowser.ts +17 -19
  336. package/src/renderer/shared/utils/attachedDocument.test.ts +73 -0
  337. package/src/renderer/shared/utils/attachedDocument.ts +49 -0
  338. package/src/renderer/shared/utils/fileIcons.test.ts +59 -0
  339. package/src/renderer/shared/utils/fileIcons.ts +149 -16
  340. package/src/renderer/shared/utils/markdown.tsx +72 -19
  341. package/src/renderer/shared/utils/markdown.webImages.test.tsx +16 -0
  342. package/src/renderer/shared/utils/mcpResults.test.tsx +29 -0
  343. package/src/renderer/shared/utils/slashCommandProcessor.ts +4 -1
  344. package/src/renderer/shared/utils/syntaxHighlight.test.tsx +11 -1
  345. package/src/renderer/shared/utils/syntaxHighlight.tsx +51 -3
  346. package/src/renderer/shared/utils/useGeminiLiveVoice.ts +324 -51
  347. package/src/renderer/shared/utils/workspaceDrag.test.ts +153 -0
  348. package/src/renderer/shared/utils/workspaceDrag.ts +142 -0
  349. package/src/renderer/shared/utils/workspaceMedia.ts +10 -2
  350. package/src/renderer/src/App.tsx +14 -8
  351. package/src/renderer/src/agentProgress.ts +1 -0
  352. package/src/renderer/src/components/ScreenPicker.css +1 -1
  353. package/src/renderer/src/components/WorkspacePanel.tsx +6 -5
  354. package/src/renderer/src/css/app-shell.css +4 -4
  355. package/src/renderer/src/css/chat.css +1261 -241
  356. package/src/renderer/src/css/desktop-tools.css +11 -11
  357. package/src/renderer/src/css/sidebar-workspace.css +2 -2
  358. package/src/renderer/src/css/tool-surfaces.css +12 -12
  359. package/src/renderer/src/index.css +38 -20
  360. package/src/renderer/src/tauri.ts +22 -2
  361. package/src/renderer/src-web/App.tsx +14 -0
  362. package/src/renderer/src-web/agentProgress.ts +1 -0
  363. package/src/renderer/src-web/css/app-shell.css +4 -4
  364. package/src/renderer/src-web/css/chat.css +1278 -190
  365. package/src/renderer/src-web/css/mobile.css +29 -13
  366. package/src/renderer/src-web/css/settings/mobile.css +2 -2
  367. package/src/renderer/src-web/css/sidebar-workspace.css +1 -1
  368. package/src/renderer/src-web/index.css +38 -20
  369. package/src/renderer/src-web/tauri.ts +22 -2
  370. package/src/renderer/tests/browserArtifacts.browser.tsx +1 -1
  371. package/src/renderer/tests/library.browser.tsx +3 -0
  372. package/src/renderer/tests/liveVoice.browser.html +1 -0
  373. package/src/renderer/tests/workspaceDrop.browser.tsx +1 -1
  374. package/src-tauri/src/app/lifecycle.rs +1 -14
  375. package/src-tauri/src/background/headless.rs +14 -8
  376. package/src-tauri/src/commands/conversation.rs +38 -0
  377. package/src-tauri/src/native/mod.rs +0 -1
  378. package/src-tauri/src/native/system.rs +4 -47
  379. package/crates/mint-cli/src/interactive/chat_tui.rs +0 -8855
  380. package/crates/mint-core/src/agent/chat.rs +0 -4394
  381. package/crates/mint-core/src/browser/lifecycle.rs +0 -291
  382. package/crates/mint-core/src/browser/logging.rs +0 -20
  383. package/crates/mint-core/src/orchestration/tools/browser.rs +0 -31
  384. package/out/web/assets/ArtifactPreviewPanel-S0dPfYFx.js +0 -2
  385. package/out/web/assets/CalculationCard-CRjP3E1j.js +0 -1
  386. package/out/web/assets/CliSessionsView-C3Br2v5Y.css +0 -1
  387. package/out/web/assets/CodeReviewPage-CUJceQme.css +0 -1
  388. package/out/web/assets/CodeReviewPage-VCUgPla_.js +0 -2
  389. package/out/web/assets/ImageGenCard-BCXxkVJX.js +0 -1
  390. package/out/web/assets/ImageSearchCard-N3yQOr8Z.js +0 -1
  391. package/out/web/assets/LibraryPage-DAxUTAg7.css +0 -1
  392. package/out/web/assets/LibraryPage-WlviRdR8.js +0 -2
  393. package/out/web/assets/LinkedFoldersView-CKRgroWK.js +0 -1
  394. package/out/web/assets/McpServersView-D3wHnuHg.js +0 -1
  395. package/out/web/assets/MermaidCard-NqrHdyJW.js +0 -2
  396. package/out/web/assets/MintDashboard-B2DJsDDO.css +0 -1
  397. package/out/web/assets/MintDashboard-COw_xol7.js +0 -63
  398. package/out/web/assets/RewindModal-DempuDod.js +0 -1
  399. package/out/web/assets/SettingsWindow-2YP3yj7s.js +0 -4
  400. package/out/web/assets/SettingsWindow-Dz8LQVgD.css +0 -1
  401. package/out/web/assets/StockCard-BDMCe7mx.js +0 -1
  402. package/out/web/assets/ToolSurfacePage-B0J_q0Jl.js +0 -38
  403. package/out/web/assets/ToolSurfacePage-CRIQ1owD.css +0 -1
  404. package/out/web/assets/UiMockupWidget-DD73QWg1.js +0 -1
  405. package/out/web/assets/WeatherCard-CPucIfq8.js +0 -1
  406. package/out/web/assets/WorkspacePdfPreview-Dx_lkjNu.js +0 -2
  407. package/out/web/assets/classDiagram-ZZMXUADV-BgJ5WtSp.js +0 -1
  408. package/out/web/assets/classDiagram-v2-VYDZK3BY-BgJ5WtSp.js +0 -1
  409. package/out/web/assets/config-CvIO5hkn.js +0 -2
  410. package/out/web/assets/flowDiagram-HODETNUW-uqCHJond.js +0 -1
  411. package/out/web/assets/index-BmpulIkg.js +0 -168
  412. package/out/web/assets/index-CkvBwhX_.css +0 -1
  413. package/out/web/assets/stateDiagram-v2-MP3YSRHH-uf3kdNW4.js +0 -1
  414. package/out/web/assets/swimlanesDiagram-VR7AAH4N-Y8q5bQce.js +0 -8
  415. package/shared-modules/libsecret/libsecret.json +0 -23
  416. package/shared-modules/libusb/libusb.json +0 -27
  417. package/shared-modules/lzo/lzo.json +0 -27
  418. package/src/renderer/src/components/BrowserShell.tsx +0 -108
  419. package/src/renderer/src/components/BrowserSuggestionsPopup.tsx +0 -91
  420. package/src/renderer/src/components/browser-shell.css +0 -185
  421. package/src-tauri/src/native/browser.rs +0 -252
@@ -12,8 +12,8 @@
12
12
  {
13
13
  "type": "git",
14
14
  "url": "https://github.com/openresty/luajit2.git",
15
- "tag": "v2.1-20260717",
16
- "commit": "1e5c0db1a86c9d0645bdd05e88e3e7a295831074",
15
+ "tag": "v2.1-20260724",
16
+ "commit": "982cd8323eafd8604a9e5f2a916aa50b9f67d9ed",
17
17
  "x-checker-data": {
18
18
  "type": "git",
19
19
  "tag-pattern": "^v([\\d.-]+)$",
@@ -18,8 +18,5 @@
18
18
  "tag-pattern": "^([\\d.]+)$"
19
19
  }
20
20
  }
21
- ],
22
- "modules": [
23
- "../lzo/lzo.json"
24
21
  ]
25
22
  }
@@ -6,12 +6,15 @@
6
6
  { "token": "/onboard", "usage": "", "description": "Configure AI providers, search engines, media models, and bridges", "category": "system", "surfaces": ["cli", "web", "desktop"] },
7
7
  { "token": "/init", "usage": "", "description": "Scan the codebase and write an AGENTS.md (build/test commands, architecture, conventions)", "category": "system", "surfaces": ["cli", "web", "desktop"] },
8
8
  { "token": "/fast", "usage": "[on|off]", "description": "Toggle fast mode (hide thinking traces)", "category": "system", "surfaces": ["cli", "web", "desktop"] },
9
- { "token": "/plan", "usage": "[<task>|on|off|list|show <name>]", "description": "Run task in plan mode, toggle plan mode, or list/show plans saved under .agents/plans/", "category": "system", "surfaces": ["cli", "web", "desktop"] },
9
+ { "token": "/plan", "usage": "[<task>|on|off]", "description": "Run task in plan mode or toggle plan mode", "category": "system", "surfaces": ["cli", "web", "desktop"] },
10
+ { "token": "/plan list", "usage": "[n]", "description": "Interactively browse and view saved plans", "category": "system", "surfaces": ["cli", "web", "desktop"] },
10
11
  { "token": "/models", "usage": "[name]", "description": "List providers or switch provider", "category": "models", "surfaces": ["cli", "web", "desktop"] },
11
12
  { "token": "/thinking", "usage": "[on|off|low|medium|high|extra_high|status]", "description": "Toggle thinking mode or adjust thinking effort level", "category": "models", "surfaces": ["cli", "web", "desktop"] },
12
13
  { "token": "/temperature", "usage": "[<provider> [model] [temp]|<temp>|default|status]", "description": "Interactive temperature picker or set/inspect per-model temperatures", "category": "models", "surfaces": ["cli", "web", "desktop"] },
13
14
  { "token": "/clear", "usage": "", "description": "Clear conversation history", "category": "system", "surfaces": ["cli", "web", "desktop"] },
14
15
  { "token": "/resume", "usage": "[<id|search>]", "description": "Resume and switch conversation session", "category": "system", "surfaces": ["cli", "web", "desktop"] },
16
+ { "token": "/edit", "usage": "", "description": "Edit the last prompt and resend, replacing its previous turn and response", "category": "system", "surfaces": ["cli", "web", "desktop"] },
17
+ { "token": "/retry", "usage": "", "description": "Retry or edit the last prompt, replacing its previous turn and response", "category": "system", "surfaces": ["cli", "web", "desktop"] },
15
18
  { "token": "/branch", "usage": "[<name>]", "description": "Select or switch the current workspace Git branch", "category": "workspace", "surfaces": ["cli"] },
16
19
  { "token": "/cd", "usage": "<path>", "description": "Change workspace directory", "category": "workspace", "surfaces": ["cli", "web", "desktop"] },
17
20
  { "token": "/image", "usage": "<path> [prompt]", "description": "Attach image from file", "category": "tools", "surfaces": ["cli", "web", "desktop"] },
@@ -88,5 +91,7 @@
88
91
  { "token": "/undo", "usage": "", "description": "Undo the latest workspace file action, with conflict checks", "category": "tools", "surfaces": ["cli", "web", "desktop"] },
89
92
  { "token": "/palette", "usage": "", "description": "Open interactive command palette and action menu", "category": "system", "surfaces": ["cli", "web", "desktop"] },
90
93
  { "token": "/browser", "usage": "[on|off|headless|headed|status]", "description": "Configure browser automation tools (on/off) or mode (headless/headed)", "category": "tools", "surfaces": ["cli", "web", "desktop"] },
91
- { "token": "/browser status", "usage": "", "description": "Show current browser automation configuration and detected binary", "category": "tools", "surfaces": ["cli", "web", "desktop"] }
94
+ { "token": "/browser status", "usage": "", "description": "Show current browser automation configuration and detected binary", "category": "tools", "surfaces": ["cli", "web", "desktop"] },
95
+ { "token": "/voice", "usage": "[send|stop]", "description": "Record voice input from your microphone or start live voice mode", "category": "tools", "surfaces": ["cli", "web", "desktop"] },
96
+ { "token": "F8", "usage": "", "description": "Toggle microphone voice dictation in the TUI composer", "surfaces": ["cli"] }
92
97
  ]
@@ -1 +1 @@
1
- {"version":1,"projects":{"":{"files":{"shared/utils/agentActivity.test.ts":{"failed":false,"duration":40.027050999999915,"lastRun":1793183773429},"shared/platform.test.ts":{"failed":false,"duration":109.64923900000008,"lastRun":1793183773429},"shared/conversation/coordinator.test.ts":{"failed":false,"duration":20.026970000000006,"lastRun":1793183773429},"shared/conversation/lifecycle.test.ts":{"failed":false,"duration":80.52009099999998,"lastRun":1793183773429},"shared/conversation/projectNavigation.test.ts":{"failed":false,"duration":20.83651599999996,"lastRun":1793183773429},"shared/conversation/syncView.test.ts":{"failed":false,"duration":6.9900650000000155,"lastRun":1793183773429},"shared/conversation/transport.test.ts":{"failed":false,"duration":536.693028,"lastRun":1793183773429},"shared/library/controller.test.ts":{"failed":false,"duration":16.50159100000002,"lastRun":1793183773429},"shared/library/transport.test.ts":{"failed":false,"duration":76.04240700000003,"lastRun":1793183773429},"shared/theme/themeManager.test.ts":{"failed":false,"duration":14.008066999999983,"lastRun":1793183773429},"shared/utils/artifactBrowser.test.ts":{"failed":false,"duration":27.533172999999977,"lastRun":1793183773429},"shared/utils/cardJson.test.ts":{"failed":false,"duration":12.104575000000011,"lastRun":1793183773429},"shared/utils/contextCompaction.test.tsx":{"failed":false,"duration":26.065079000000026,"lastRun":1793183773429},"shared/utils/mcpResults.test.tsx":{"failed":false,"duration":57.573138000000085,"lastRun":1793183773429},"shared/utils/nativeRecordingSession.test.ts":{"failed":false,"duration":16.042235000000005,"lastRun":1793183773429},"shared/utils/notificationSettings.test.ts":{"failed":false,"duration":10.387980999999968,"lastRun":1793183773429},"shared/utils/notifications.test.ts":{"failed":false,"duration":15.880479999999977,"lastRun":1793183773429},"shared/utils/pastedText.test.ts":{"failed":false,"duration":6.944248000000016,"lastRun":1793183773429},"shared/utils/progressCache.test.ts":{"failed":false,"duration":12.385761000000002,"lastRun":1793183773429},"shared/utils/sessionSources.test.ts":{"failed":false,"duration":55.81931899999995,"lastRun":1793183773429},"shared/utils/syntaxHighlight.test.tsx":{"failed":false,"duration":54.93748500000004,"lastRun":1793183773429},"shared/utils/workspaceListPreferences.test.ts":{"failed":false,"duration":14.05891200000002,"lastRun":1793183773429},"shared/utils/workspacePane.test.ts":{"failed":false,"duration":12.926693,"lastRun":1793183773429},"shared/utils/workspacePreview.test.ts":{"failed":false,"duration":100.04454300000009,"lastRun":1793183773429},"shared/utils/workspaceSnapshot.test.ts":{"failed":false,"duration":17.28131400000001,"lastRun":1793183773429},"shared/components/Settings/MemoryTab.test.tsx":{"failed":false,"duration":26.29360399999996,"lastRun":1793183773429},"shared/components/Settings/NotificationsTab.test.tsx":{"failed":false,"duration":23.82480499999997,"lastRun":1793183773429},"shared/components/chat/ApprovalCard.test.tsx":{"failed":false,"duration":30.134253000000058,"lastRun":1793183773429},"shared/components/chat/ChatMessageItem.test.tsx":{"failed":false,"duration":318.785257,"lastRun":1793183773429},"shared/components/chat/ChatPanel.test.tsx":{"failed":false,"duration":29.24033700000018,"lastRun":1793183773429},"shared/components/chat/GeminiLiveOverlay.test.tsx":{"failed":false,"duration":44.660064999999804,"lastRun":1793183773429},"shared/components/chat/SlashSuggestions.test.tsx":{"failed":false,"duration":114.17350899999997,"lastRun":1793183773429},"shared/components/chat/VoicePill.test.tsx":{"failed":false,"duration":16.966045000000122,"lastRun":1793183773429},"shared/components/extensions/CliSessionsView.test.tsx":{"failed":false,"duration":61.2925409999998,"lastRun":1793183773429},"shared/components/extensions/ModUi.test.tsx":{"failed":false,"duration":33.30287599999997,"lastRun":1793183773429},"shared/components/extensions/SkillsView.test.tsx":{"failed":false,"duration":29.079979000000094,"lastRun":1793183773429},"shared/components/ui/SelectField.test.tsx":{"failed":false,"duration":17.565294999999878,"lastRun":1793183773429},"shared/components/workspace/BackgroundTerminals.test.tsx":{"failed":false,"duration":8.144984000000022,"lastRun":1793183773429},"shared/components/workspace/ToolSurfacePage.test.tsx":{"failed":false,"duration":70.17192100000011,"lastRun":1793183773429},"shared/components/workspace/WorkspacePreviewActions.test.tsx":{"failed":false,"duration":142.7974139999999,"lastRun":1793183773429},"shared/utils/markdown.webImages.test.tsx":{"failed":false,"duration":90.81762600000002,"lastRun":1793182038780},"shared/utils/viewedImages.test.ts":{"failed":false,"duration":11.297821999999996,"lastRun":1793182038780},"src/components/liveTranslateFrames.test.ts":{"failed":false,"duration":18.077312000000006,"lastRun":1793182038780},"shared/components/activity/RunSummaryDashboard.test.tsx":{"failed":false,"duration":80.88592800000004,"lastRun":1793182038780},"shared/components/activity/SubagentDagView.test.ts":{"failed":false,"duration":12.650046000000032,"lastRun":1793182038780},"shared/components/activity/SubagentStatusStrip.test.tsx":{"failed":false,"duration":30.136209000000008,"lastRun":1793182038780},"shared/components/Settings/CustomProviderLogoPicker.test.tsx":{"failed":false,"duration":41.86565899999994,"lastRun":1793182038780},"shared/components/ui/ProviderBrandIcon.test.tsx":{"failed":false,"duration":23.60773400000005,"lastRun":1793182038780},"shared/components/chat/QueuedMessagesBanner.test.tsx":{"failed":false,"duration":30.937026000000003,"lastRun":1793182038780},"shared/components/chat/TurnFileChanges.test.tsx":{"failed":false,"duration":24.704264999999964,"lastRun":1793182038780}}}}}
1
+ {"version":1,"projects":{"":{"files":{"shared/utils/agentActivity.test.ts":{"failed":false,"duration":74.68115,"lastRun":1794711934122},"shared/platform.test.ts":{"failed":false,"duration":167.60485,"lastRun":1794711934122},"shared/conversation/coordinator.test.ts":{"failed":false,"duration":12.203535999999986,"lastRun":1794711934122},"shared/conversation/lifecycle.test.ts":{"failed":false,"duration":195.067431,"lastRun":1794711934122},"shared/conversation/projectNavigation.test.ts":{"failed":false,"duration":37.12674900000002,"lastRun":1794711934122},"shared/conversation/syncView.test.ts":{"failed":false,"duration":8.248370999999963,"lastRun":1794711934122},"shared/conversation/transport.test.ts":{"failed":false,"duration":651.6762119999999,"lastRun":1794711934122},"shared/library/controller.test.ts":{"failed":false,"duration":12.613306999999963,"lastRun":1794711934122},"shared/library/transport.test.ts":{"failed":false,"duration":63.27990699999998,"lastRun":1794711934122},"shared/theme/themeManager.test.ts":{"failed":false,"duration":14.115149999999971,"lastRun":1794711934122},"shared/utils/artifactBrowser.test.ts":{"failed":false,"duration":25.255110000000002,"lastRun":1794711934122},"shared/utils/cardJson.test.ts":{"failed":false,"duration":12.019497999999999,"lastRun":1794711934122},"shared/utils/contextCompaction.test.tsx":{"failed":false,"duration":23.443441000000007,"lastRun":1794711934122},"shared/utils/mcpResults.test.tsx":{"failed":false,"duration":54.09891600000003,"lastRun":1794711934122},"shared/utils/nativeRecordingSession.test.ts":{"failed":false,"duration":12.781210999999985,"lastRun":1794711934122},"shared/utils/notificationSettings.test.ts":{"failed":false,"duration":7.269725000000022,"lastRun":1794711934122},"shared/utils/notifications.test.ts":{"failed":false,"duration":22.19806299999999,"lastRun":1794711934122},"shared/utils/pastedText.test.ts":{"failed":false,"duration":17.01037100000002,"lastRun":1794711934122},"shared/utils/progressCache.test.ts":{"failed":false,"duration":14.497963000000027,"lastRun":1794711934122},"shared/utils/sessionSources.test.ts":{"failed":false,"duration":38.63473900000008,"lastRun":1794711934122},"shared/utils/syntaxHighlight.test.tsx":{"failed":false,"duration":63.384461999999985,"lastRun":1794711934122},"shared/utils/workspaceListPreferences.test.ts":{"failed":false,"duration":12.346294999999998,"lastRun":1794711934122},"shared/utils/workspacePane.test.ts":{"failed":false,"duration":14.303937000000019,"lastRun":1794711934122},"shared/utils/workspacePreview.test.ts":{"failed":false,"duration":228.54220800000002,"lastRun":1794711934122},"shared/utils/workspaceSnapshot.test.ts":{"failed":false,"duration":14.155031000000008,"lastRun":1794711934122},"shared/components/Settings/MemoryTab.test.tsx":{"failed":false,"duration":27.761302,"lastRun":1794711934122},"shared/components/Settings/NotificationsTab.test.tsx":{"failed":false,"duration":22.887137999999993,"lastRun":1794711934122},"shared/components/chat/ApprovalCard.test.tsx":{"failed":false,"duration":75.91465499999958,"lastRun":1794711934122},"shared/components/chat/ChatMessageItem.test.tsx":{"failed":false,"duration":417.2941850000002,"lastRun":1794711934122},"shared/components/chat/ChatPanel.test.tsx":{"failed":false,"duration":35.519512000000304,"lastRun":1794711934122},"shared/components/chat/GeminiLiveOverlay.test.tsx":{"failed":false,"duration":65.10267999999996,"lastRun":1794711934122},"shared/components/chat/SlashSuggestions.test.tsx":{"failed":false,"duration":219.54700000000003,"lastRun":1794711934122},"shared/components/chat/VoicePill.test.tsx":{"failed":false,"duration":15.675452999999834,"lastRun":1794711934122},"shared/components/extensions/CliSessionsView.test.tsx":{"failed":false,"duration":57.13724600000023,"lastRun":1794711934122},"shared/components/extensions/ModUi.test.tsx":{"failed":false,"duration":91.94093300000009,"lastRun":1794711934122},"shared/components/extensions/SkillsView.test.tsx":{"failed":false,"duration":31.764030000000048,"lastRun":1794711934122},"shared/components/ui/SelectField.test.tsx":{"failed":false,"duration":15.119639000000006,"lastRun":1794711934122},"shared/components/workspace/BackgroundTerminals.test.tsx":{"failed":false,"duration":8.939891000000046,"lastRun":1794711934122},"shared/components/workspace/ToolSurfacePage.test.tsx":{"failed":false,"duration":69.98606400000017,"lastRun":1794711934122},"shared/components/workspace/WorkspacePreviewActions.test.tsx":{"failed":false,"duration":126.59361799999988,"lastRun":1794711934122},"shared/utils/markdown.webImages.test.tsx":{"failed":false,"duration":105.505361,"lastRun":1794214846331},"shared/utils/viewedImages.test.ts":{"failed":false,"duration":10.134315000000015,"lastRun":1794214846331},"src/components/liveTranslateFrames.test.ts":{"failed":false,"duration":29.59982500000001,"lastRun":1794214846331},"shared/components/activity/RunSummaryDashboard.test.tsx":{"failed":false,"duration":91.52480800000001,"lastRun":1794214846331},"shared/components/activity/SubagentDagView.test.ts":{"failed":false,"duration":14.174296999999967,"lastRun":1794214846331},"shared/components/activity/SubagentStatusStrip.test.tsx":{"failed":false,"duration":54.643602000000044,"lastRun":1794214846331},"shared/components/Settings/CustomProviderLogoPicker.test.tsx":{"failed":false,"duration":46.935133000000064,"lastRun":1794214846331},"shared/components/ui/ProviderBrandIcon.test.tsx":{"failed":false,"duration":38.44240099999996,"lastRun":1794214846331},"shared/components/chat/QueuedMessagesBanner.test.tsx":{"failed":false,"duration":37.36570599999999,"lastRun":1794214846331},"shared/components/chat/TurnFileChanges.test.tsx":{"failed":false,"duration":44.71720800000003,"lastRun":1794214846331},"shared/components/chat/SourcesBlock.test.tsx":{"failed":false,"duration":31.33332100000007,"lastRun":1794214846331},"shared/conversation/progressiveStream.test.ts":{"failed":false,"duration":13.339047999999991,"lastRun":1794214846331},"shared/components/chat/ChatCodeBlock.test.tsx":{"failed":false,"duration":58.37564699999996,"lastRun":1794214846331},"shared/constants/models.test.ts":{"failed":false,"duration":11.463003000000015,"lastRun":1794214846331},"shared/components/cards/ReleaseNotesCard.test.tsx":{"failed":false,"duration":59.24009000000001,"lastRun":1794214846331},"shared/components/cards/PlanCard.test.tsx":{"failed":false,"duration":78.54705599999988,"lastRun":1794214846331},"shared/components/chat/ArtifactCards.test.tsx":{"failed":false,"duration":33.190233000000035,"lastRun":1794711934122},"shared/utils/workspaceDrag.test.ts":{"failed":false,"duration":15.73349300000001,"lastRun":1794711934122},"shared/components/Settings/ThemeTab.test.tsx":{"failed":false,"duration":82.93911500000013,"lastRun":1794214846331},"shared/utils/fileIcons.test.ts":{"failed":false,"duration":12.504846999999984,"lastRun":1794214846331},"shared/components/workspace/CodeReviewPage.test.tsx":{"failed":false,"duration":48.53411199999937,"lastRun":1794214846331},"shared/utils/attachedDocument.test.ts":{"failed":false,"duration":10.880305000000021,"lastRun":1794214846331},"shared/components/chat/AttachedDocumentCard.test.tsx":{"failed":false,"duration":105.18471300000004,"lastRun":1794214846331},"shared/components/chat/ChatModeSelector.test.tsx":{"failed":false,"duration":31.021543000000065,"lastRun":1794214846331},"shared/components/activity/AskUserActivityCard.test.tsx":{"failed":false,"duration":117.32442300000002,"lastRun":1794214846331},"shared/utils/test_render.test.tsx":{"failed":false,"duration":33.70705700000008,"lastRun":1794284842924}}}}}
@@ -100,6 +100,10 @@ export function reduceLiveAgentProgress(
100
100
  const index = current.findIndex(item => item.type === 'ToolProgress' && item.data.callId === event.data.callId)
101
101
  if (index >= 0) { const next = current.slice(); next[index] = event; return next }
102
102
  }
103
+ if (event.type === 'PlanUpdated') {
104
+ const index = current.findIndex(item => item.type === 'PlanUpdated')
105
+ if (index >= 0) { const next = current.slice(); next[index] = event; return next }
106
+ }
103
107
 
104
108
  if (event.type === 'ThinkingDelta') {
105
109
  const index = current.findIndex(
@@ -153,10 +157,12 @@ export function compactAgentProgressForPersistence(progress: AgentProgress[]): A
153
157
  for (const event of progress) {
154
158
  if (event.type === 'ToolProgress') latestProgress.set(event.data.callId, event)
155
159
  if (event.type === 'DeviceState' && event.data.update.state !== 'accepted') latestProgress.set(`device:${event.data.callId}`,event)
160
+ if (event.type === 'PlanUpdated') latestProgress.set('plan:active', event)
156
161
  }
157
162
  for (const event of progress) {
158
163
  if (event.type === 'ToolProgress' && latestProgress.get(event.data.callId) !== event) continue
159
164
  if(event.type==='DeviceState' && event.data.update.state!=='accepted' && latestProgress.get(`device:${event.data.callId}`)!==event) continue
165
+ if (event.type === 'PlanUpdated' && latestProgress.get('plan:active') !== event) continue
160
166
  if (event.type === 'ThinkingDelta') {
161
167
  if (!completedIds.has(event.data.id)) {
162
168
  const previous = interrupted.get(event.data.id)
@@ -192,6 +198,22 @@ export function hasAgentToolActivity(progress: AgentProgress[]): boolean {
192
198
  return progress.some((event) => event.type === 'ToolStart' || event.type === 'ToolEnd')
193
199
  }
194
200
 
201
+ export function hasAgentDrawerActivity(progress: AgentProgress[]): boolean {
202
+ return progress.some(
203
+ (event) =>
204
+ event.type === 'ToolStart' ||
205
+ event.type === 'ToolEnd' ||
206
+ event.type === 'ToolArtifacts' ||
207
+ event.type === 'DeviceState' ||
208
+ event.type === 'ToolDiscovery' ||
209
+ event.type === 'PlanUpdated' ||
210
+ event.type === 'SubagentStarted' ||
211
+ event.type === 'SubagentFinished' ||
212
+ event.type === 'RunCompleted' ||
213
+ event.type === 'ContextCompaction',
214
+ )
215
+ }
216
+
195
217
  export function mergeActivitySnapshots(
196
218
  current: Record<string, AgentProgress[]>,
197
219
  interactions: InteractionMemory[],
@@ -280,11 +302,11 @@ function deriveFileChangesFromProgress(progress: AgentProgress[]): FileChange[]
280
302
  }
281
303
  } else if (event.data.action === 'write_file' || event.data.action === 'note_write') {
282
304
  const input = (event.data.input as any) || {}
283
- let path = input.path || input.name || input.title || input.filePath || ''
305
+ let path = input.path || input.Path || input.name || input.title || input.filePath || ''
284
306
  if (event.data.action === 'note_write' && path && !path.includes('/') && !path.startsWith('.config/')) {
285
307
  path = `.config/mint/notes/${path}`
286
308
  }
287
- const fileContent = input.fileContent ?? input.file_content ?? input.content ?? input.body ?? input.text ?? ''
309
+ const fileContent = input.fileContent ?? input.file_content ?? input.Content ?? input.content ?? input.body ?? input.text ?? ''
288
310
  if (typeof path === 'string' && path.trim()) {
289
311
  const additions = fileContent ? fileContent.split('\n').length : 0
290
312
  activeEdit = {
@@ -296,13 +318,39 @@ function deriveFileChangesFromProgress(progress: AgentProgress[]): FileChange[]
296
318
  hunks: [{ oldText: '', newText: fileContent }]
297
319
  }
298
320
  }
321
+ } else if (event.data.action === 'edit_file') {
322
+ const input = (event.data.input as any) || {}
323
+ const path = input.Path || input.path || input.filePath || ''
324
+ const target = input.Target ?? input.target ?? ''
325
+ const replacement = input.Replacement ?? input.replacement ?? ''
326
+ if (typeof path === 'string' && path.trim()) {
327
+ const deletions = target ? target.split('\n').length : 0
328
+ const additions = replacement ? replacement.split('\n').length : 0
329
+ activeEdit = {
330
+ action: 'edit_file',
331
+ path: path.trim(),
332
+ created: false,
333
+ additions,
334
+ deletions,
335
+ hunks: [{ oldText: target, newText: replacement }]
336
+ }
337
+ }
299
338
  } else {
300
339
  activeEdit = null
301
340
  }
302
341
  } else if (event.type === 'ToolEnd') {
303
- if (activeEdit && (event.data.action === 'apply_patch' || event.data.action === 'write_file' || event.data.action === 'note_write')) {
342
+ if (activeEdit && (event.data.action === 'apply_patch' || event.data.action === 'write_file' || event.data.action === 'note_write' || event.data.action === 'edit_file')) {
304
343
  const isError = typeof event.data.result === 'string' && (event.data.result.startsWith('Error:') || event.data.result.startsWith('Failed:'))
305
344
  if (!isError) {
345
+ const lineMatch = typeof event.data.result === 'string' && event.data.result.match(/\+(\d+)\/-(\d+) lines/)
346
+ if (lineMatch) {
347
+ const add = parseInt(lineMatch[1], 10)
348
+ const del = parseInt(lineMatch[2], 10)
349
+ if (!isNaN(add) && !isNaN(del)) {
350
+ activeEdit.additions = add
351
+ activeEdit.deletions = del
352
+ }
353
+ }
306
354
  try {
307
355
  const applied = JSON.parse(event.data.result)
308
356
  if (Array.isArray(applied) && applied.length > 0) {
@@ -27,65 +27,11 @@ export default function AutomationTab({
27
27
  </h2>
28
28
  </div>
29
29
  </div>
30
- <div className="toggle-card" style={{ marginBottom: '16px' }}>
31
- <div className="toggle-row">
32
- <div>
33
- <label>Browser automation tools</label>
34
- <p className="hint">Allows the agent to open web pages, execute JavaScript/SPA, and capture screenshots automatically using headless Chromium.</p>
35
- </div>
36
- <label className="settings-toggle-switch">
37
- <input
38
- type="checkbox"
39
- checked={config.browserAutomationEnabled ?? true}
40
- onChange={(e) => updateField('browserAutomationEnabled', e.target.checked)}
41
- />
42
- <span className="settings-toggle-slider"></span>
43
- </label>
44
- </div>
45
- </div>
46
30
  <div className="form-grid single">
47
31
  <div className="setting-row">
48
- <label>Agent browser mode</label>
49
- <div className="pill-segmented" role="radiogroup" aria-label="Agent browser mode">
50
- {[{ id: 'headless', label: 'Headless' }, { id: 'headed', label: 'Show window' }].map(option => <button key={option.id} type="button" role="radio" aria-checked={config.browserAgentMode === option.id} className={`pill-segmented-btn ${config.browserAgentMode === option.id ? 'active' : ''}`} onClick={() => updateField('browserAgentMode', option.id)}>{option.label}</button>)}
51
- </div>
52
- <p className="hint">Headless runs in the background. Opening Mint Browser yourself still shows its window.</p>
53
- </div>
54
- <div className="setting-row">
55
- <label>Agent browser executable</label>
32
+ <label>Chromium executable</label>
56
33
  <input type="text" value={config.browserExecutable} placeholder="Auto-detect Chrome / Chromium / Edge" onChange={event => updateField('browserExecutable', event.target.value)} />
57
- <p className="hint">Optional executable path for Chromium-based automation. Firefox is not supported by this engine.</p>
58
- </div>
59
- <div className="setting-row">
60
- <label>Browser engine</label>
61
- <div className="pill-segmented" role="radiogroup" aria-label="Browser engine">
62
- {[
63
- { id: 'chromium', label: 'Chromium' },
64
- { id: '/usr/bin/firefox', label: 'Firefox' },
65
- ].map(o => (
66
- <button
67
- key={o.id}
68
- type="button"
69
- role="radio"
70
- aria-checked={config.automationBrowser === o.id}
71
- className={`pill-segmented-btn ${config.automationBrowser === o.id ? 'active' : ''}`}
72
- onClick={() => updateField('automationBrowser', o.id)}
73
- >
74
- {o.label}
75
- </button>
76
- ))}
77
- </div>
78
- <p className="hint">Chromium is bundled; Firefox uses your system install (Linux).</p>
79
- </div>
80
- <div className="setting-row">
81
- <label>Chromium DevTools endpoint</label>
82
- <input type="text" value={config.browserDebugUrl} onChange={(e) => updateField('browserDebugUrl', e.target.value)} />
83
- <p className="hint">Required for native tab reading and selector clicks.</p>
84
- </div>
85
- <div className="setting-row">
86
- <label>Browser extension context endpoint</label>
87
- <input type="text" value={config.browserExtensionContextUrl} onChange={(e) => updateField('browserExtensionContextUrl', e.target.value)} />
88
- <p className="hint">Fallback endpoint used when Chromium remote debugging is unavailable.</p>
34
+ <p className="hint">Optional executable path for headless Chromium operations and CLI browser workflows (`mint browser run`). Firefox is not supported by this engine.</p>
89
35
  </div>
90
36
  </div>
91
37
  </section>
@@ -7,6 +7,7 @@ interface AvatarCropModalProps {
7
7
  onConfirm: (croppedDataUri: string) => Promise<void> | void
8
8
  title?: string
9
9
  outputFormat?: 'image/jpeg' | 'image/png' | 'image/webp'
10
+ circular?: boolean
10
11
  }
11
12
 
12
13
  const CROP_SIZE = 280
@@ -18,7 +19,8 @@ export default function AvatarCropModal({
18
19
  onClose,
19
20
  onConfirm,
20
21
  title,
21
- outputFormat = 'image/jpeg',
22
+ outputFormat = 'image/png',
23
+ circular = true,
22
24
  }: AvatarCropModalProps) {
23
25
  const [zoom, setZoom] = useState(1)
24
26
  const [rotation, setRotation] = useState(0) // in degrees (0, 90, 180, 270)
@@ -196,6 +198,14 @@ export default function AvatarCropModal({
196
198
  ctx.imageSmoothingEnabled = true
197
199
  ctx.imageSmoothingQuality = 'high'
198
200
 
201
+ if (circular) {
202
+ ctx.save()
203
+ ctx.beginPath()
204
+ ctx.arc(OUTPUT_SIZE / 2, OUTPUT_SIZE / 2, OUTPUT_SIZE / 2, 0, Math.PI * 2)
205
+ ctx.closePath()
206
+ ctx.clip()
207
+ }
208
+
199
209
  // Ratio between export output and preview box
200
210
  const R = OUTPUT_SIZE / CROP_SIZE
201
211
 
@@ -215,6 +225,10 @@ export default function AvatarCropModal({
215
225
  imgNaturalSize.height
216
226
  )
217
227
 
228
+ if (circular) {
229
+ ctx.restore()
230
+ }
231
+
218
232
  const croppedDataUri = outputFormat === 'image/png'
219
233
  ? canvas.toDataURL('image/png')
220
234
  : canvas.toDataURL(outputFormat, 0.95)
@@ -13,6 +13,7 @@ import {
13
13
  IMAGE_GEN_PROVIDER_MODELS,
14
14
  VEO_STUDIO_MODELS,
15
15
  getModelMetadata,
16
+ hasNativeThinkingSupport,
16
17
  } from '../../constants/models'
17
18
  import type {
18
19
  CustomProviderConfig,
@@ -534,14 +535,17 @@ export default function GeneralTab({
534
535
  })()
535
536
 
536
537
  const meta = getModelMetadata(activeModelRaw, config.aiProvider)
538
+ const hasNativeThinking = hasNativeThinkingSupport(activeModelRaw, config.aiProvider)
537
539
  const modelConfigs = (config.modelThinkingConfigs ?? {}) as Record<string, { enabled?: boolean; effort?: string }>
538
540
  const customModelThinking = activeModelRaw ? modelConfigs[activeModelRaw] : undefined
539
541
  const hasCustomModel = customModelThinking !== undefined
540
542
 
541
543
  const isThinkingSupported = meta.supportsThinking
542
- const currentEnabled = customModelThinking?.enabled !== undefined
544
+ const currentEnabled = !isThinkingSupported
545
+ ? false
546
+ : customModelThinking?.enabled !== undefined
543
547
  ? customModelThinking.enabled
544
- : (config.thinkingEnabled ?? true)
548
+ : (hasNativeThinking ? (config.thinkingEnabled ?? true) : false)
545
549
 
546
550
  const currentEffort = (customModelThinking?.effort || config.thinkingEffort || 'medium').toLowerCase()
547
551
 
@@ -599,8 +603,10 @@ export default function GeneralTab({
599
603
  </label>
600
604
  <div className="thinking-card-status" style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
601
605
  <span className="section-current-badge" style={{ fontSize: '0.75rem' }}>
602
- {currentEnabled
603
- ? `Thinking ON (${effortLabelMap[currentEffort] || 'Medium'})${!isThinkingSupported ? ' · Force' : ''}`
606
+ {!isThinkingSupported
607
+ ? 'Unavailable (Non-Text Model)'
608
+ : currentEnabled
609
+ ? `Thinking ON (${effortLabelMap[currentEffort] || 'Medium'})${hasNativeThinking ? '' : ' · Prompted CoT'}`
604
610
  : 'Thinking OFF'}
605
611
  </span>
606
612
  {hasCustomModel && (
@@ -622,25 +628,32 @@ export default function GeneralTab({
622
628
  <div>
623
629
  <span style={{ fontSize: '0.82rem', fontWeight: 500 }}>Enable thinking</span>
624
630
  <p style={{ margin: '2px 0 0 0', fontSize: '0.73rem', color: 'var(--text-muted)' }}>
625
- {isThinkingSupported
626
- ? 'Allow model to output chain-of-thought tokens.'
627
- : currentEnabled
628
- ? 'Chain-of-thought token generation enabled (force toggle).'
629
- : 'Model not flagged as reasoning by default — toggle on to force enable.'}
631
+ {!isThinkingSupported
632
+ ? 'Image, audio, and embedding models do not support Chain-of-Thought reasoning.'
633
+ : hasNativeThinking
634
+ ? 'Uses the provider’s native Reasoning API (thinkingBudget / reasoning_effort / thinking).'
635
+ : 'Uses Prompted Chain-of-Thought (<think>...</think>) so the model reasons step-by-step before answering.'}
630
636
  </p>
631
637
  </div>
632
- <label className="settings-toggle-switch">
638
+ <label
639
+ className="settings-toggle-switch"
640
+ style={!isThinkingSupported ? { opacity: 0.45, cursor: 'not-allowed' } : undefined}
641
+ >
633
642
  <input
634
643
  type="checkbox"
644
+ disabled={!isThinkingSupported}
635
645
  checked={currentEnabled}
636
- onChange={(e) => handleToggleThinking(e.target.checked)}
646
+ onChange={(e) => {
647
+ if (!isThinkingSupported) return
648
+ handleToggleThinking(e.target.checked)
649
+ }}
637
650
  />
638
651
  <span className="settings-toggle-slider"></span>
639
652
  </label>
640
653
  </div>
641
654
 
642
655
  {/* Effort Level Row */}
643
- {currentEnabled && (
656
+ {isThinkingSupported && currentEnabled && (
644
657
  <div style={{ marginTop: '0.5rem', paddingTop: '0.5rem', borderTop: '1px solid var(--border)' }}>
645
658
  <div className="thinking-card-effort-row" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
646
659
  <span style={{ fontSize: '0.78rem', fontWeight: 600, color: 'var(--text-muted)', textTransform: 'none', letterSpacing: '0.04em' }}>
@@ -0,0 +1,45 @@
1
+ import React from 'react'
2
+ import { renderToStaticMarkup } from 'react-dom/server'
3
+ import { describe, expect, it } from 'vitest'
4
+ import ThemeTab from './ThemeTab'
5
+ import { DEFAULT_CONFIG } from '../../constants/config'
6
+ import { TEXT_COLOR_FLAVORS } from '../../theme/themes'
7
+
8
+ describe('ThemeTab Text Color Picker', () => {
9
+ it('renders the Text color section with curated swatches and custom hex toggle', () => {
10
+ const html = renderToStaticMarkup(
11
+ <ThemeTab
12
+ config={{ ...DEFAULT_CONFIG, textColor: '#f8fafc' }}
13
+ updateField={() => {}}
14
+ />
15
+ )
16
+ expect(html).toContain('Text color')
17
+ expect(html).toContain('Custom Hex...')
18
+ expect(html).toContain('aria-label="Text colors"')
19
+
20
+ for (const flavor of TEXT_COLOR_FLAVORS) {
21
+ expect(html).toContain(flavor.name)
22
+ }
23
+ })
24
+
25
+ it('marks the active flavor based on config.textColor', () => {
26
+ const html = renderToStaticMarkup(
27
+ <ThemeTab
28
+ config={{ ...DEFAULT_CONFIG, textColor: '#fde047' }}
29
+ updateField={() => {}}
30
+ />
31
+ )
32
+ // Retro Amber flavor (#fde047) should have aria-checked="true"
33
+ expect(html).toMatch(/role="radio"[^>]*aria-checked="true"[^>]*title="Warm CRT phosphor amber gold"/)
34
+ })
35
+
36
+ it('marks Pure White as active when default #f8fafc is set', () => {
37
+ const html = renderToStaticMarkup(
38
+ <ThemeTab
39
+ config={{ ...DEFAULT_CONFIG, textColor: '#f8fafc' }}
40
+ updateField={() => {}}
41
+ />
42
+ )
43
+ expect(html).toMatch(/role="radio"[^>]*aria-checked="true"[^>]*title="Crisp classic bright white"/)
44
+ })
45
+ })
@@ -1,7 +1,7 @@
1
1
  import SelectField from '../ui/SelectField'
2
2
  import React, { useState } from 'react'
3
3
  import { DEFAULT_CONFIG } from '../../constants/config'
4
- import { THEME_PRESETS, ACCENT_FLAVORS, ThemePreset, AccentFlavor } from '../../theme/themes'
4
+ import { THEME_PRESETS, ACCENT_FLAVORS, TEXT_COLOR_FLAVORS, ThemePreset, AccentFlavor, TextColorFlavor } from '../../theme/themes'
5
5
 
6
6
  interface ThemeTabProps {
7
7
  config: typeof DEFAULT_CONFIG
@@ -11,6 +11,7 @@ interface ThemeTabProps {
11
11
 
12
12
  export default function ThemeTab({ config, updateField, updateFields }: ThemeTabProps) {
13
13
  const [showCustomAccent, setShowCustomAccent] = useState(false)
14
+ const [showCustomText, setShowCustomText] = useState(false)
14
15
 
15
16
  const isPresetActive = (preset: ThemePreset) => {
16
17
  if (config.theme !== preset.theme) return false
@@ -21,6 +22,7 @@ export default function ThemeTab({ config, updateField, updateFields }: ThemeTab
21
22
  const patch: Partial<typeof DEFAULT_CONFIG> = {
22
23
  theme: preset.theme,
23
24
  accentColor: preset.accentColor,
25
+ textColor: preset.textColor || preset.systemTextColor,
24
26
  systemTextColor: preset.systemTextColor,
25
27
  chatTextColor: preset.chatTextColor,
26
28
  surfaceStyle: preset.theme === 'light' ? 'opaque' : 'glass',
@@ -30,6 +32,7 @@ export default function ThemeTab({ config, updateField, updateFields }: ThemeTab
30
32
  } else {
31
33
  updateField('theme', preset.theme)
32
34
  updateField('accentColor', preset.accentColor)
35
+ updateField('textColor', patch.textColor)
33
36
  updateField('systemTextColor', preset.systemTextColor)
34
37
  updateField('chatTextColor', preset.chatTextColor)
35
38
  updateField('surfaceStyle', patch.surfaceStyle)
@@ -46,6 +49,20 @@ export default function ThemeTab({ config, updateField, updateFields }: ThemeTab
46
49
  }
47
50
  }
48
51
 
52
+ const handleSelectTextColor = (flavor: TextColorFlavor) => {
53
+ if (updateFields) {
54
+ updateFields({
55
+ textColor: flavor.color,
56
+ systemTextColor: flavor.color,
57
+ chatTextColor: flavor.color,
58
+ })
59
+ } else {
60
+ updateField('textColor', flavor.color)
61
+ updateField('systemTextColor', flavor.color)
62
+ updateField('chatTextColor', flavor.color)
63
+ }
64
+ }
65
+
49
66
  const COLOR_MODES = [
50
67
  {
51
68
  id: 'system',
@@ -112,6 +129,7 @@ export default function ThemeTab({ config, updateField, updateFields }: ThemeTab
112
129
  ]
113
130
 
114
131
  const currentAccent = (config.accentColor || '').toLowerCase()
132
+ const currentText = (config.textColor || config.systemTextColor || '#f8fafc').toLowerCase()
115
133
  const TUI_MODES = [
116
134
  { id: 'system', name: 'Auto', description: 'Use terminal colors' },
117
135
  { id: 'dark', name: 'Dark', description: 'Dark terminal palette' },
@@ -231,13 +249,30 @@ export default function ThemeTab({ config, updateField, updateFields }: ThemeTab
231
249
  onClick={() => {
232
250
  if (mode.id === 'light') {
233
251
  if (updateFields) {
234
- updateFields({ theme: 'light', surfaceStyle: 'opaque' })
252
+ updateFields({ theme: 'light', surfaceStyle: 'opaque', textColor: '#0f172a', systemTextColor: '#0f172a', chatTextColor: '#0f172a' })
235
253
  } else {
236
254
  updateField('theme', 'light')
237
255
  updateField('surfaceStyle', 'opaque')
256
+ updateField('textColor', '#0f172a')
257
+ updateField('systemTextColor', '#0f172a')
258
+ updateField('chatTextColor', '#0f172a')
238
259
  }
239
260
  } else {
240
- updateField('theme', mode.id)
261
+ const isSwitchingFromLight = config.theme === 'light'
262
+ const nextText = isSwitchingFromLight ? '#f8fafc' : (config.textColor || '#f8fafc')
263
+ if (updateFields) {
264
+ updateFields({
265
+ theme: mode.id,
266
+ ...(isSwitchingFromLight ? { textColor: nextText, systemTextColor: nextText, chatTextColor: nextText } : {})
267
+ })
268
+ } else {
269
+ updateField('theme', mode.id)
270
+ if (isSwitchingFromLight) {
271
+ updateField('textColor', nextText)
272
+ updateField('systemTextColor', nextText)
273
+ updateField('chatTextColor', nextText)
274
+ }
275
+ }
241
276
  }
242
277
  }}
243
278
  >
@@ -318,6 +353,74 @@ export default function ThemeTab({ config, updateField, updateFields }: ThemeTab
318
353
  )}
319
354
  </div>
320
355
 
356
+ {/* Text color */}
357
+ <div className="setting-row stacked">
358
+ <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
359
+ <label>Text color</label>
360
+ <button
361
+ type="button"
362
+ className="custom-accent-toggle"
363
+ onClick={() => setShowCustomText(!showCustomText)}
364
+ >
365
+ {showCustomText ? 'Use Curated Flavors' : 'Custom Hex...'}
366
+ </button>
367
+ </div>
368
+
369
+ {!showCustomText ? (
370
+ <div className="flavor-grid" role="radiogroup" aria-label="Text colors">
371
+ {TEXT_COLOR_FLAVORS.map((flavor) => {
372
+ const isSelected = currentText === flavor.color.toLowerCase() || (flavor.id === 'white' && (currentText === '#ffffff' || currentText === '#f8fafc'))
373
+ const isWhite = flavor.color.toLowerCase() === '#ffffff'
374
+ return (
375
+ <button
376
+ key={flavor.id}
377
+ type="button"
378
+ role="radio"
379
+ aria-checked={isSelected}
380
+ className={`flavor-card ${isSelected ? 'active' : ''}`}
381
+ onClick={() => handleSelectTextColor(flavor)}
382
+ title={flavor.description}
383
+ >
384
+ <span
385
+ className="flavor-swatch"
386
+ style={{
387
+ background: flavor.color,
388
+ border: isWhite ? '1px solid rgba(255,255,255,0.2)' : 'none',
389
+ }}
390
+ >
391
+ {isSelected && (
392
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke={flavor.contrastText} strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round">
393
+ <polyline points="20 6 9 17 4 12"></polyline>
394
+ </svg>
395
+ )}
396
+ </span>
397
+ <span className="flavor-name">{flavor.name}</span>
398
+ </button>
399
+ )
400
+ })}
401
+ </div>
402
+ ) : (
403
+ <div className="custom-accent-box">
404
+ <input
405
+ type="color"
406
+ value={config.textColor || config.systemTextColor || '#f8fafc'}
407
+ onChange={(e) => {
408
+ const val = e.target.value
409
+ if (updateFields) {
410
+ updateFields({ textColor: val, systemTextColor: val, chatTextColor: val })
411
+ } else {
412
+ updateField('textColor', val)
413
+ updateField('systemTextColor', val)
414
+ updateField('chatTextColor', val)
415
+ }
416
+ }}
417
+ className="custom-accent-input"
418
+ />
419
+ <span className="custom-accent-value">{config.textColor || config.systemTextColor || '#f8fafc'}</span>
420
+ </div>
421
+ )}
422
+ </div>
423
+
321
424
  <div className="toggle-row reduced-effects-row">
322
425
  <div>
323
426
  <label id="reduced-effects-label" htmlFor="reduced-effects">Reduce effects</label>