@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
@@ -13,6 +13,19 @@ import CalculationCard from '../components/CalculationCard'
13
13
  import ImageSearchCard from '../components/ImageSearchCard'
14
14
  import ImageGenCard from '../components/ImageGenCard'
15
15
  import MermaidCard from '../components/MermaidCard'
16
+ import UiGridCard from '../components/UiGridCard'
17
+ import { parseCardJsonSafely } from './cardJson'
18
+ import UiFeatureCard from '../components/UiFeatureCard'
19
+ import UiMockupWidget from '../components/UiMockupWidget'
20
+ import type { WebSearchSource } from './agentActivity'
21
+ import {
22
+ Info,
23
+ Lightbulb,
24
+ AlertCircle,
25
+ AlertTriangle,
26
+ ShieldAlert,
27
+ type LucideIcon,
28
+ } from 'lucide-react'
16
29
 
17
30
  /**
18
31
  * Unwraps Brave Search internal image proxy URLs (imgs.search.brave.com)
@@ -134,7 +147,7 @@ export function renderSpeakerIcon(isSpeaking: boolean): ReactNode {
134
147
  export function renderCopyIcon(isCopied: boolean): ReactNode {
135
148
  if (isCopied) {
136
149
  return (
137
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" style={{ display: 'block', color: 'var(--accent, #10b981)' }}>
150
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" style={{ display: 'block', color: 'var(--interactive-fg)' }}>
138
151
  <polyline points="20 6 9 17 4 12" />
139
152
  </svg>
140
153
  )
@@ -158,19 +171,33 @@ function flattenText(node: ReactNode): string {
158
171
  return ''
159
172
  }
160
173
 
161
- /** Wraps bare "@mention" tokens in plain-text children with a highlight span, without touching already-rendered elements (links, code, bold, ...). */
174
+ /** Wraps bare "@mention" tokens with styled spans and strips any leftover "[badge:color text]" into plain natural text. */
162
175
  function highlightMentions(node: ReactNode, keyPrefix = 'm'): ReactNode {
163
176
  if (typeof node === 'string') {
164
- const parts = node.split(/(@[\w\-.\/]+)/g)
177
+ const parts = node.split(/(@[\w\-.\/]+|\[badge(?::[a-zA-Z]+)?\s+[^\]]+\])/g)
165
178
  if (parts.length <= 1) return node
166
- return parts.map((part, i) =>
167
- i % 2 === 1
168
- ? <span key={`${keyPrefix}-${i}`} className="chat-mention">{part}</span>
169
- : part ? <Fragment key={`${keyPrefix}-t-${i}`}>{part}</Fragment> : null
170
- )
179
+ return parts.map((part, i) => {
180
+ if (i % 2 === 1) {
181
+ if (part.startsWith('@')) {
182
+ return (
183
+ <span key={`${keyPrefix}-${i}`} className="chat-mention">
184
+ {part}
185
+ </span>
186
+ )
187
+ }
188
+ const badgeMatch = part.match(/^\[badge(?::([a-zA-Z]+))?\s+([^\]]+)\]$/)
189
+ if (badgeMatch) {
190
+ // Render plain natural text without robotic badge frame/pill
191
+ return <Fragment key={`${keyPrefix}-${i}`}>{badgeMatch[2]}</Fragment>
192
+ }
193
+ }
194
+ return part ? <Fragment key={`${keyPrefix}-t-${i}`}>{part}</Fragment> : null
195
+ })
171
196
  }
172
197
  if (Array.isArray(node)) {
173
- return node.map((child, i) => <Fragment key={`${keyPrefix}-${i}`}>{highlightMentions(child, `${keyPrefix}-${i}`)}</Fragment>)
198
+ return node.map((child, i) => (
199
+ <Fragment key={`${keyPrefix}-${i}`}>{highlightMentions(child, `${keyPrefix}-${i}`)}</Fragment>
200
+ ))
174
201
  }
175
202
  return node
176
203
  }
@@ -222,50 +249,220 @@ function trimListItemEdges(children: ReactNode): ReactNode {
222
249
  return arr
223
250
  }
224
251
 
252
+ function parseJsonSafely(codeText: string): any {
253
+ if (!codeText || !codeText.trim()) return null
254
+ let cleaned = codeText.trim()
255
+ if (cleaned.startsWith('```')) {
256
+ cleaned = cleaned.replace(/^```[a-zA-Z0-9_-]*\s*/, '').replace(/\s*```$/, '').trim()
257
+ }
258
+ return parseCardJsonSafely(cleaned)
259
+ }
260
+
261
+ function renderJsonCard(
262
+ codeText: string,
263
+ lang: string,
264
+ render: (data: any) => ReactNode,
265
+ ): ReactNode {
266
+ const parsed = parseJsonSafely(codeText)
267
+ return parsed
268
+ ? render(parsed)
269
+ : <ChatCodeBlock code={codeText} language={lang} />
270
+ }
271
+
225
272
  function renderCodeCard(lang: string, codeText: string): ReactNode {
226
273
  switch (lang) {
227
274
  case 'weather_json':
228
275
  case 'weather-json':
229
- try {
230
- return <WeatherCard data={JSON.parse(codeText)} />
231
- } catch {
232
- return <ChatCodeBlock code={codeText} language={lang} />
233
- }
276
+ return renderJsonCard(codeText, lang, (data) => <WeatherCard data={data} />)
234
277
  case 'stock_json':
235
278
  case 'stock-json':
236
- try {
237
- return <StockCard data={JSON.parse(codeText)} />
238
- } catch {
239
- return <ChatCodeBlock code={codeText} language={lang} />
240
- }
279
+ return renderJsonCard(codeText, lang, (data) => <StockCard data={data} />)
241
280
  case 'calculation_json':
242
281
  case 'calculation-json':
243
- try {
244
- return <CalculationCard data={JSON.parse(codeText)} />
245
- } catch {
246
- return <ChatCodeBlock code={codeText} language={lang} />
247
- }
282
+ return renderJsonCard(codeText, lang, (data) => <CalculationCard data={data} />)
248
283
  case 'image_search_json':
249
284
  case 'image-search-json':
250
- try {
251
- return <ImageSearchCard data={JSON.parse(codeText)} />
252
- } catch {
253
- return <ChatCodeBlock code={codeText} language={lang} />
254
- }
285
+ return renderJsonCard(codeText, lang, (data) => <ImageSearchCard data={data} />)
255
286
  case 'image_gen_json':
256
287
  case 'image-gen-json':
257
- try {
258
- return <ImageGenCard data={JSON.parse(codeText)} />
259
- } catch {
260
- return <ChatCodeBlock code={codeText} language={lang} />
261
- }
288
+ return renderJsonCard(codeText, lang, (data) => <ImageGenCard data={data} />)
262
289
  case 'mermaid':
263
290
  return <MermaidCard code={codeText} />
291
+ case 'ui_grid':
292
+ case 'ui-grid':
293
+ case 'ui_grid_json':
294
+ case 'ui-grid-json': {
295
+ let clean = codeText.trim()
296
+ if (/^ui[-_]grid(?:[-_]json)?\s*/i.test(clean)) {
297
+ clean = clean.replace(/^ui[-_]grid(?:[-_]json)?\s*/i, '')
298
+ }
299
+ const parsed = parseJsonSafely(clean)
300
+ if (parsed) return <UiGridCard data={parsed} />
301
+ return <ChatCodeBlock code={codeText} language={lang} />
302
+ }
303
+ case 'ui_card':
304
+ case 'ui-card':
305
+ case 'ui_card_json':
306
+ case 'ui-card-json':
307
+ case 'ui_feature':
308
+ case 'ui-feature': {
309
+ let clean = codeText.trim()
310
+ if (/^ui[-_](?:card|feature)(?:[-_]json)?\s*/i.test(clean)) {
311
+ clean = clean.replace(/^ui[-_](?:card|feature)(?:[-_]json)?\s*/i, '')
312
+ }
313
+ const parsed = parseJsonSafely(clean)
314
+ if (parsed) return <UiFeatureCard data={parsed} />
315
+ return <ChatCodeBlock code={codeText} language={lang} />
316
+ }
317
+ case 'ui_mockup':
318
+ case 'ui-mockup':
319
+ case 'ui_mockup_json':
320
+ case 'ui-mockup-json': {
321
+ let clean = codeText.trim()
322
+ if (/^ui[-_]mockup(?:[-_]json)?\s*/i.test(clean)) {
323
+ clean = clean.replace(/^ui[-_]mockup(?:[-_]json)?\s*/i, '')
324
+ }
325
+ const parsed = parseJsonSafely(clean)
326
+ if (parsed) return <UiMockupWidget data={parsed} />
327
+ return <ChatCodeBlock code={codeText} language={lang} />
328
+ }
264
329
  default:
265
330
  return <ChatCodeBlock code={codeText} language={lang} />
266
331
  }
267
332
  }
268
333
 
334
+ function stripAlertTag(node: ReactNode): ReactNode {
335
+ let done = false
336
+ function clean(item: ReactNode): ReactNode {
337
+ if (done || item == null) return item
338
+ if (typeof item === 'string') {
339
+ const match = item.match(/^\s*\[!(?:NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]\s*(?:\r?\n)?/i)
340
+ if (match) {
341
+ done = true
342
+ return item.slice(match[0].length)
343
+ }
344
+ return item
345
+ }
346
+ if (Array.isArray(item)) {
347
+ return item.map(clean).filter((v) => v !== '' && v != null)
348
+ }
349
+ if (isValidElement(item)) {
350
+ const props = item.props as { children?: ReactNode }
351
+ if (props.children) {
352
+ return cloneElement(item, {}, clean(props.children))
353
+ }
354
+ }
355
+ return item
356
+ }
357
+ return clean(node)
358
+ }
359
+
360
+ function renderAlertBox(type: string, children: ReactNode): ReactNode {
361
+ const config: { title: string; color: string; border: string; bg: string; borderSubtle: string; Icon: LucideIcon } = {
362
+ NOTE: { title: 'Note', color: '#38bdf8', border: '#38bdf8', bg: 'rgba(56, 189, 248, 0.08)', borderSubtle: 'rgba(56, 189, 248, 0.25)', Icon: Info },
363
+ TIP: { title: 'Tip', color: '#34d399', border: '#10b981', bg: 'rgba(16, 185, 129, 0.08)', borderSubtle: 'rgba(16, 185, 129, 0.25)', Icon: Lightbulb },
364
+ IMPORTANT: { title: 'Important', color: '#c084fc', border: '#a855f7', bg: 'rgba(168, 85, 247, 0.08)', borderSubtle: 'rgba(168, 85, 247, 0.25)', Icon: AlertCircle },
365
+ WARNING: { title: 'Warning', color: '#fbbf24', border: '#f59e0b', bg: 'rgba(245, 158, 11, 0.08)', borderSubtle: 'rgba(245, 158, 11, 0.25)', Icon: AlertTriangle },
366
+ CAUTION: { title: 'Caution', color: '#f87171', border: '#ef4444', bg: 'rgba(239, 68, 68, 0.08)', borderSubtle: 'rgba(239, 68, 68, 0.25)', Icon: ShieldAlert },
367
+ }[type] || { title: 'Note', color: '#38bdf8', border: '#38bdf8', bg: 'rgba(56, 189, 248, 0.08)', borderSubtle: 'rgba(56, 189, 248, 0.25)', Icon: Info }
368
+
369
+ const IconComponent = config.Icon
370
+ return (
371
+ <div
372
+ className={`chat-callout-card chat-callout--${type.toLowerCase()}`}
373
+ style={{
374
+ margin: '14px 0',
375
+ padding: '12px 16px',
376
+ borderRadius: '10px',
377
+ borderLeft: `4px solid ${config.border}`,
378
+ borderTop: `1px solid ${config.borderSubtle}`,
379
+ borderRight: `1px solid ${config.borderSubtle}`,
380
+ borderBottom: `1px solid ${config.borderSubtle}`,
381
+ '--callout-tint': config.bg,
382
+ '--callout-accent': config.border,
383
+ boxShadow: '0 2px 10px rgba(0, 0, 0, 0.15)',
384
+ } as CSSProperties}
385
+ >
386
+ <div
387
+ style={{
388
+ display: 'flex',
389
+ alignItems: 'center',
390
+ gap: '8px',
391
+ marginBottom: '6px',
392
+ color: config.color,
393
+ fontWeight: 700,
394
+ fontSize: '0.86rem',
395
+ letterSpacing: '0.3px',
396
+ textTransform: 'none',
397
+ }}
398
+ >
399
+ <IconComponent size={16} strokeWidth={2.2} />
400
+ <span>{config.title}</span>
401
+ </div>
402
+ <div style={{ fontSize: '0.86rem', color: 'var(--text-chat, #cbd5e1)', lineHeight: 1.5 }}>
403
+ {children}
404
+ </div>
405
+ </div>
406
+ )
407
+ }
408
+
409
+ function renderMessageImage(src: string | undefined, alt: string | undefined, sourceUrl?: string): ReactNode {
410
+ const url = resolveMediaUrl(String(src || ''))
411
+ const label = alt || 'Generated Image'
412
+ const isExternal = /^https?:\/\//.test(url)
413
+ if (isExternal) {
414
+ const pageUrl = sourceUrl && /^https?:\/\//.test(sourceUrl) ? sourceUrl : url
415
+ return (
416
+ <div
417
+ className="chat-media-card chat-media-card--thumbnail"
418
+ style={{ margin: '6px 0 10px', borderRadius: '10px', overflow: 'hidden', border: '1px solid var(--border, rgba(255,255,255,0.12))', background: 'var(--panel-bg, #141416)', maxWidth: '420px' }}
419
+ >
420
+ <a href={pageUrl} target="_blank" rel="noopener noreferrer" title={sourceUrl ? `Open source page: ${label}` : label} style={{ display: 'block', textDecoration: 'none' }}>
421
+ <img
422
+ src={url}
423
+ alt={label}
424
+ loading="lazy"
425
+ referrerPolicy="no-referrer"
426
+ style={{ width: '100%', maxHeight: '200px', objectFit: 'cover', display: 'block' }}
427
+ onError={(e) => { const card = e.currentTarget.closest('.chat-media-card') as HTMLElement | null; if (card) card.style.display = 'none' }}
428
+ />
429
+ </a>
430
+ {(label !== 'Generated Image' || sourceUrl) && (
431
+ <div style={{ padding: '5px 10px', fontSize: '0.72rem', color: 'var(--text-muted, #64748b)', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '8px' }}>
432
+ <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{label}</span>
433
+ {sourceUrl && (
434
+ <a href={url} target="_blank" rel="noopener noreferrer" style={{ flexShrink: 0, color: 'var(--interactive-fg-hover)' }}>
435
+ View full image
436
+ </a>
437
+ )}
438
+ </div>
439
+ )}
440
+ </div>
441
+ )
442
+ }
443
+ return (
444
+ <div className="chat-media-card" style={{ margin: '10px 0', borderRadius: '12px', overflow: 'hidden', border: '1px solid var(--border, rgba(255,255,255,0.12))', background: 'var(--panel-bg, #141416)' }}>
445
+ <img src={url} alt={label} referrerPolicy="no-referrer" style={{ width: '100%', maxHeight: '420px', objectFit: 'contain', display: 'block', borderRadius: '8px' }} />
446
+ </div>
447
+ )
448
+ }
449
+
450
+ function renderMessageLink(href: string | undefined, children: ReactNode, node: any, sourceByImage?: Map<string, string>): ReactNode {
451
+ const imageNode = node?.children?.length === 1 && node.children[0]?.tagName === 'img'
452
+ ? node.children[0]
453
+ : null
454
+ if (imageNode) {
455
+ const imageUrl = String(imageNode.properties?.src || '')
456
+ const sourceUrl = sourceByImage?.get(resolveMediaUrl(imageUrl)) || href
457
+ return renderMessageImage(imageUrl, String(imageNode.properties?.alt || ''), sourceUrl)
458
+ }
459
+ return (
460
+ <a href={href} target="_blank" rel="noopener noreferrer" className="chat-link">
461
+ {highlightMentions(children)}
462
+ </a>
463
+ )
464
+ }
465
+
269
466
  // `ol`/`ul` inject `ordered`/`index` onto their `li` children (via cloneElement below) so each
270
467
  // list item knows how to render itself without needing shared state; react-markdown's own
271
468
  // component types don't declare these, so the object is cast to `Components` where it's used.
@@ -275,6 +472,10 @@ const mdComponents = {
275
472
  if (EMOJI_HEADER_RE.test(text)) {
276
473
  return <div className="chat-heading chat-heading-3 chat-section-title">{children}</div>
277
474
  }
475
+ const alertMatch = text.match(/^\s*\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]/i)
476
+ if (alertMatch) {
477
+ return renderAlertBox(alertMatch[1].toUpperCase(), stripAlertTag(children))
478
+ }
278
479
  // A plain <div> (not <p>) so block-level media cards can nest inside safely.
279
480
  return <div className="chat-paragraph">{highlightMentions(children)}</div>
280
481
  },
@@ -309,48 +510,29 @@ const mdComponents = {
309
510
  )
310
511
  },
311
512
  strong: ({ children }) => <strong className="chat-bold-highlight">{children}</strong>,
312
- a: ({ href, children }) => (
313
- <a href={href} target="_blank" rel="noopener noreferrer" className="chat-link">
314
- {highlightMentions(children)}
315
- </a>
316
- ),
317
- img: ({ src, alt }) => {
318
- const rawUrl = String(src || '')
319
- const url = resolveMediaUrl(rawUrl)
320
- const label = alt || 'Generated Image'
321
- const isExternal = url.startsWith('https://') || url.startsWith('http://')
322
- if (isExternal) {
323
- return (
324
- <a
325
- href={url}
326
- target="_blank"
327
- rel="noopener noreferrer"
328
- title={label}
329
- className="chat-media-card chat-media-card--thumbnail"
330
- style={{ display: 'block', margin: '6px 0 10px 0', borderRadius: '10px', overflow: 'hidden', border: '1px solid var(--border, rgba(255,255,255,0.12))', background: 'var(--panel-bg, #141416)', maxWidth: '420px', textDecoration: 'none', cursor: 'pointer' }}
331
- >
332
- <img
333
- src={url}
334
- alt={label}
335
- loading="lazy"
336
- referrerPolicy="no-referrer"
337
- style={{ width: '100%', maxHeight: '200px', objectFit: 'cover', display: 'block' }}
338
- onError={(e) => { (e.currentTarget as HTMLImageElement).closest('a')!.style.display = 'none' }}
339
- />
340
- {label !== 'Generated Image' && (
341
- <div style={{ padding: '5px 10px', fontSize: '0.72rem', color: 'var(--text-muted, #64748b)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{label}</div>
342
- )}
343
- </a>
344
- )
345
- }
346
- return (
347
- <div className="chat-media-card" style={{ margin: '10px 0', borderRadius: '12px', overflow: 'hidden', border: '1px solid var(--border, rgba(255,255,255,0.12))', background: 'var(--panel-bg, #141416)' }}>
348
- <img src={url} alt={label} referrerPolicy="no-referrer" style={{ width: '100%', maxHeight: '420px', objectFit: 'contain', display: 'block', borderRadius: '8px' }} />
349
- </div>
350
- )
351
- },
513
+ a: ({ href, children, node }) => renderMessageLink(href, children, node),
514
+ img: ({ src, alt }) => renderMessageImage(src, alt),
352
515
  code({ children }) {
353
- // Only reached for inline code — block code is intercepted by `pre` below.
516
+ // Detect single-line UI widgets parsed as inline code (e.g. `ui-card [...]` or ```ui-card [...]```)
517
+ const rawText = typeof children === 'string'
518
+ ? children
519
+ : Array.isArray(children) && children.every((c) => typeof c === 'string')
520
+ ? children.join('')
521
+ : ''
522
+ if (rawText) {
523
+ const trimmed = rawText.trim()
524
+ const match = trimmed.match(/^(ui[-_](?:card|grid|mockup|feature)(?:[-_]json)?)\s+([\s\S]+)$/i)
525
+ if (match) {
526
+ const lang = match[1].replace(/_/g, '-').toLowerCase()
527
+ const parsed = parseJsonSafely(match[2].trim())
528
+ if (parsed) {
529
+ if (lang.startsWith('ui-grid')) return <UiGridCard data={parsed} />
530
+ if (lang.startsWith('ui-card') || lang.startsWith('ui-feature')) return <UiFeatureCard data={parsed} />
531
+ if (lang.startsWith('ui-mockup')) return <UiMockupWidget data={parsed} />
532
+ }
533
+ }
534
+ }
535
+ // Only reached for regular inline code — block code is intercepted by `pre` below.
354
536
  return <code className="chat-inline-code">{children}</code>
355
537
  },
356
538
  pre({ node }) {
@@ -362,8 +544,40 @@ const mdComponents = {
362
544
  ? rawClassName.split(/\s+/)
363
545
  : []
364
546
  const langClass = classNames.find((c) => c.startsWith('language-'))
365
- const lang = langClass ? langClass.slice('language-'.length) : 'plaintext'
366
- const codeText = readHastText(codeNode).replace(/\n$/, '')
547
+ let lang = langClass ? langClass.slice('language-'.length) : 'plaintext'
548
+ let codeText = readHastText(codeNode).replace(/\n$/, '')
549
+
550
+ // Check if AST node has data.meta with arguments/json (e.g. ```ui-card [{"title": ...}]```)
551
+ const meta = (codeNode as any)?.data?.meta
552
+ if (typeof meta === 'string' && meta.trim()) {
553
+ const trimmedMeta = meta.trim()
554
+ if (!codeText.trim()) {
555
+ codeText = trimmedMeta
556
+ } else if (trimmedMeta.startsWith('[') || trimmedMeta.startsWith('{')) {
557
+ codeText = trimmedMeta + '\n' + codeText
558
+ }
559
+ }
560
+
561
+ // If lang has JSON attached (e.g. language-ui-card [{"title": ...}])
562
+ if (lang.includes('[') || lang.includes('{')) {
563
+ const splitIdx = lang.search(/[\s\[\{]/)
564
+ if (splitIdx > 0) {
565
+ const extractedLang = lang.slice(0, splitIdx)
566
+ const rest = lang.slice(splitIdx)
567
+ lang = extractedLang
568
+ codeText = (rest + ' ' + codeText).trim()
569
+ }
570
+ }
571
+
572
+ // If lang is plaintext or generic, but codeText starts with ui-card / ui-grid / ui-mockup
573
+ if (lang === 'plaintext' || !lang) {
574
+ const match = codeText.trim().match(/^(ui[-_](?:card|grid|mockup|feature)(?:[-_]json)?)\s+([\s\S]+)$/i)
575
+ if (match) {
576
+ lang = match[1].replace(/_/g, '-').toLowerCase()
577
+ codeText = match[2].trim()
578
+ }
579
+ }
580
+
367
581
  return renderCodeCard(lang, codeText)
368
582
  },
369
583
  table: ({ children }) => (
@@ -410,7 +624,7 @@ const mdComponents = {
410
624
  // `style` here comes from the cloneElement calls in `thead`/`tbody` above.
411
625
  tr: ({ children, style }: { children?: ReactNode; style?: CSSProperties }) => <tr style={style}>{children}</tr>,
412
626
  th: ({ children }) => (
413
- <th style={{ padding: '12px 16px', fontWeight: 700, color: 'var(--accent, #38bdf8)', fontFamily: 'ui-sans-serif, system-ui, sans-serif' }}>
627
+ <th style={{ padding: '12px 16px', fontWeight: 700, color: 'var(--interactive-fg)', fontFamily: 'ui-sans-serif, system-ui, sans-serif' }}>
414
628
  {highlightMentions(children)}
415
629
  </th>
416
630
  ),
@@ -419,6 +633,31 @@ const mdComponents = {
419
633
  {highlightMentions(children)}
420
634
  </td>
421
635
  ),
636
+
637
+ blockquote: ({ children }) => {
638
+ const rawText = flattenText(children).trim()
639
+ const alertMatch = rawText.match(/^\s*\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]/i)
640
+
641
+ if (alertMatch) {
642
+ return renderAlertBox(alertMatch[1].toUpperCase(), stripAlertTag(children))
643
+ }
644
+
645
+ return (
646
+ <blockquote
647
+ style={{
648
+ margin: '12px 0',
649
+ padding: '8px 16px',
650
+ borderLeft: '3px solid var(--accent, #38bdf8)',
651
+ background: 'rgba(255, 255, 255, 0.02)',
652
+ borderRadius: '0 8px 8px 0',
653
+ color: 'var(--text-muted, #94a3b8)',
654
+ fontStyle: 'italic',
655
+ }}
656
+ >
657
+ {children}
658
+ </blockquote>
659
+ )
660
+ },
422
661
  }
423
662
 
424
663
  /** Normalizes non-standard list markers ("(1)", "[1]", "•") to plain GFM syntax so remark recognizes them as real lists. */
@@ -460,11 +699,21 @@ function splitVideoSegments(text: string): Segment[] {
460
699
  return segments
461
700
  }
462
701
 
463
- export function renderFormattedMessage(text: string): ReactNode {
702
+ export function renderFormattedMessage(text: string, webSources: WebSearchSource[] = []): ReactNode {
464
703
  const displayText = readableAssistantText(text)
465
704
  if (!displayText) return null
466
705
 
467
706
  const segments = splitVideoSegments(displayText)
707
+ const sourceByImage = new Map(
708
+ webSources.filter((source) => source.imageUrl).map((source) => [resolveMediaUrl(source.imageUrl!), source.url]),
709
+ )
710
+ const components = webSources.length === 0 ? mdComponents : {
711
+ ...mdComponents,
712
+ a: ({ href, children, node }: { href?: string; children?: ReactNode; node?: any }) =>
713
+ renderMessageLink(href, children, node, sourceByImage),
714
+ img: ({ src, alt }: { src?: string; alt?: string }) =>
715
+ renderMessageImage(src, alt, sourceByImage.get(resolveMediaUrl(String(src || '')))),
716
+ }
468
717
 
469
718
  return (
470
719
  <div className="chat-formatted-body">
@@ -477,7 +726,7 @@ export function renderFormattedMessage(text: string): ReactNode {
477
726
  )
478
727
  }
479
728
  return (
480
- <ReactMarkdown key={`md-${i}`} remarkPlugins={[remarkGfm]} components={mdComponents as Components}>
729
+ <ReactMarkdown key={`md-${i}`} remarkPlugins={[remarkGfm]} components={components as Components}>
481
730
  {normalizeListMarkers(segment.value)}
482
731
  </ReactMarkdown>
483
732
  )
@@ -0,0 +1,40 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { renderToStaticMarkup } from 'react-dom/server'
3
+ import { renderFormattedMessage } from './markdown'
4
+ import type { WebSearchSource } from './agentActivity'
5
+
6
+ const source: WebSearchSource = {
7
+ title: 'WindowPet',
8
+ url: 'https://github.com/SeakMengs/WindowPet',
9
+ imageUrl: 'https://opengraph.githubassets.com/example/SeakMengs/WindowPet',
10
+ snippet: '',
11
+ domain: 'github.com',
12
+ faviconUrl: '',
13
+ }
14
+
15
+ describe('web search image links', () => {
16
+ it('opens the paired source page from the thumbnail and the image file from a separate link', () => {
17
+ const html = renderToStaticMarkup(renderFormattedMessage(`![WindowPet](${source.imageUrl})`, [source]))
18
+
19
+ expect(html).toContain(`href="${source.url}"`)
20
+ expect(html).toContain(`href="${source.imageUrl}"`)
21
+ expect(html).toContain('View full image')
22
+ })
23
+
24
+ it('does not invent a source page for an unrelated image', () => {
25
+ const otherImage = 'https://example.com/other.png'
26
+ const html = renderToStaticMarkup(renderFormattedMessage(`![Other](${otherImage})`, [source]))
27
+
28
+ expect(html).toContain(`href="${otherImage}"`)
29
+ expect(html).not.toContain(`href="${source.url}"`)
30
+ expect(html).not.toContain('View full image')
31
+ })
32
+
33
+ it('uses an explicitly linked page without nesting image links', () => {
34
+ const html = renderToStaticMarkup(renderFormattedMessage(`[![WindowPet](${source.imageUrl})](${source.url})`))
35
+
36
+ expect(html).toContain(`href="${source.url}"`)
37
+ expect(html).toContain(`href="${source.imageUrl}"`)
38
+ expect(html).not.toMatch(/<a[^>]*>\s*<a/)
39
+ })
40
+ })
@@ -7,6 +7,7 @@
7
7
  interface ProviderResponse {
8
8
  provider: string
9
9
  fallbackProvider?: string | null
10
+ fallbackReason?: string | null
10
11
  }
11
12
 
12
13
  export function badge(provider: string, model: string): string {
@@ -14,7 +15,9 @@ export function badge(provider: string, model: string): string {
14
15
  }
15
16
 
16
17
  export function providerLabel(provider: string): string {
17
- switch (provider) {
18
+ if (!provider) return 'Primary provider'
19
+ const normalized = provider.startsWith('custom:') ? provider.replace(/^custom:/, '') : provider
20
+ switch (normalized.toLowerCase()) {
18
21
  case 'gemini': return 'Gemini'
19
22
  case 'openai': return 'OpenAI'
20
23
  case 'openrouter': return 'OpenRouter'
@@ -23,7 +26,8 @@ export function providerLabel(provider: string): string {
23
26
  case 'huggingface': return 'Hugging Face'
24
27
  case 'local_openai': return 'Local OpenAI'
25
28
  case 'ollama': return 'Ollama'
26
- default: return provider || 'Primary provider'
29
+ case 'groq': return 'Groq'
30
+ default: return normalized.charAt(0).toUpperCase() + normalized.slice(1)
27
31
  }
28
32
  }
29
33
 
@@ -31,6 +35,7 @@ export function fallbackNotice(
31
35
  response: ProviderResponse | null | undefined,
32
36
  ): string {
33
37
  if (!response?.fallbackProvider) return ''
34
- return `${providerLabel(response.fallbackProvider)} unavailable, fell back to ${providerLabel(response.provider)}.`
38
+ const reasonText = response.fallbackReason ? ` (${response.fallbackReason})` : ''
39
+ return `${providerLabel(response.fallbackProvider)} unavailable${reasonText}, fell back to ${providerLabel(response.provider)}.`
35
40
  }
36
41
 
@@ -0,0 +1,43 @@
1
+ /** Capture one frame from an explicitly user-approved screen share. */
2
+ async function captureBrowserScreen(): Promise<string> {
3
+ if (!navigator.mediaDevices?.getDisplayMedia) {
4
+ throw new Error('Screen sharing is unavailable in this browser. Use a supported desktop browser or attach an image file.')
5
+ }
6
+
7
+ const stream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: false })
8
+ try {
9
+ await new Promise<void>((resolve) => requestAnimationFrame(() => requestAnimationFrame(() => resolve())))
10
+ const video = document.createElement('video')
11
+ video.srcObject = stream
12
+ video.muted = true
13
+ video.playsInline = true
14
+ await new Promise<void>((resolve, reject) => {
15
+ const timeout = window.setTimeout(() => reject(new Error('The screen share did not produce a frame. Please try again.')), 8000)
16
+ video.addEventListener('loadeddata', () => { window.clearTimeout(timeout); resolve() }, { once: true })
17
+ video.addEventListener('error', () => { window.clearTimeout(timeout); reject(new Error('Unable to read the shared screen.')) }, { once: true })
18
+ void video.play().catch((reason) => { window.clearTimeout(timeout); reject(reason) })
19
+ })
20
+ if (!video.videoWidth || !video.videoHeight) throw new Error('The selected screen has no image.')
21
+ const canvas = document.createElement('canvas')
22
+ canvas.width = video.videoWidth
23
+ canvas.height = video.videoHeight
24
+ const context = canvas.getContext('2d')
25
+ if (!context) throw new Error('Unable to prepare the screenshot.')
26
+ context.drawImage(video, 0, 0)
27
+ return canvas.toDataURL('image/png')
28
+ } finally {
29
+ stream.getTracks().forEach((track) => track.stop())
30
+ }
31
+ }
32
+
33
+ async function captureNativeWithoutMint(): Promise<string> {
34
+ const { invoke } = await import('@tauri-apps/api/core')
35
+ return invoke<string>('capture_chat_screen')
36
+ }
37
+
38
+ export async function captureScreenForChat(isDesktopApp: boolean): Promise<string> {
39
+ if (isDesktopApp && navigator.userAgent.toLowerCase().includes('linux')) {
40
+ return captureNativeWithoutMint()
41
+ }
42
+ return captureBrowserScreen()
43
+ }
@@ -8,7 +8,7 @@
8
8
 
9
9
  export interface SlashCommandExecutionResult {
10
10
  handled: boolean
11
- action?: 'open_image_picker' | 'paste_image' | 'generate_veo' | 'system_message'
11
+ action?: 'open_image_picker' | 'paste_image' | 'generate_veo' | 'system_message' | 'resume_session'
12
12
  payload?: any
13
13
  systemText?: string
14
14
  }
@@ -39,6 +39,9 @@ export function executeSlashCommand(input: string): SlashCommandExecutionResult
39
39
  case '/paste':
40
40
  return { handled: true, action: 'paste_image', payload: { prompt: rest } }
41
41
 
42
+ case '/resume':
43
+ return { handled: true, action: 'resume_session', payload: { query: rest } }
44
+
42
45
  case '/veo': {
43
46
  if (!rest) {
44
47
  return {