@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
@@ -5,7 +5,7 @@ import { detectArtifactType, type ArtifactFile } from '../../utils/artifacts'
5
5
  import TerminalDock from './TerminalDock'
6
6
  import type { FileChange } from '../../types'
7
7
  import { ListTodo, Paperclip, Puzzle, Image as ImageIcon, Layers, ChevronLeft, ChevronRight } from 'lucide-react'
8
- import { WORKSPACE_FILE_MIME, parseWorkspaceFileDrag, type WorkspaceFileDrag } from '../../utils/workspaceDrag'
8
+ import { WORKSPACE_FILE_MIME, parseWorkspaceFileDrag, setWorkspaceDragData, type WorkspaceFileDrag } from '../../utils/workspaceDrag'
9
9
 
10
10
  const ArtifactPreviewPanel = lazy(() => import('./ArtifactPreviewPanel').then(m => ({ default: m.ArtifactPreviewPanel })))
11
11
  const CodeReviewPage = lazy(() => import('./CodeReviewPage'))
@@ -531,34 +531,45 @@ export default function ToolSurfacePage({
531
531
  role="tablist"
532
532
  aria-label="Open tool pages"
533
533
  >
534
- {surfaces.map((surface) => (
535
- <div
536
- className={`tool-surface-tab ${surface.id === active.id ? 'is-active' : ''}`}
537
- key={surface.id}
538
- onContextMenu={(event) => {
539
- event.preventDefault()
540
- event.stopPropagation()
541
- setTabMenuState({
542
- id: surface.id,
543
- x: Math.min(event.clientX, window.innerWidth - 180),
544
- y: Math.min(event.clientY, window.innerHeight - 150),
545
- })
546
- }}
547
- >
548
- <button
549
- type="button"
550
- role="tab"
551
- aria-selected={surface.id === active.id}
552
- title={surface.title}
553
- aria-label={surface.title}
554
- onClick={() => { setTabMenuState(null); onSelect(surface.id) }}
534
+ {surfaces.map((surface) => {
535
+ const isPreview = surface.kind === 'preview' && Boolean(surface.artifact?.path)
536
+ return (
537
+ <div
538
+ className={`tool-surface-tab ${surface.id === active.id ? 'is-active' : ''}`}
539
+ key={surface.id}
540
+ draggable={isPreview}
541
+ onDragStart={isPreview ? (event) => {
542
+ setWorkspaceDragData(event.dataTransfer, {
543
+ path: surface.artifact.path,
544
+ root: surface.artifact.workspacePath || workspacePath,
545
+ url: surface.artifact.url,
546
+ })
547
+ } : undefined}
548
+ onContextMenu={(event) => {
549
+ event.preventDefault()
550
+ event.stopPropagation()
551
+ setTabMenuState({
552
+ id: surface.id,
553
+ x: Math.min(event.clientX, window.innerWidth - 180),
554
+ y: Math.min(event.clientY, window.innerHeight - 150),
555
+ })
556
+ }}
555
557
  >
556
- <span className={`tool-surface-tab-icon is-${surface.kind}`} aria-hidden="true">{surfaceIcon(surface)}</span>
557
- <span className="tool-surface-tab-title">{surface.title}</span>
558
- </button>
559
- <button type="button" className="tool-surface-tab-close" onClick={() => onClose(surface.id)} aria-label={`Close ${surface.title}`} title="Close">×</button>
560
- </div>
561
- ))}
558
+ <button
559
+ type="button"
560
+ role="tab"
561
+ aria-selected={surface.id === active.id}
562
+ title={surface.title}
563
+ aria-label={surface.title}
564
+ onClick={() => { setTabMenuState(null); onSelect(surface.id) }}
565
+ >
566
+ <span className={`tool-surface-tab-icon is-${surface.kind}`} aria-hidden="true">{surfaceIcon(surface)}</span>
567
+ <span className="tool-surface-tab-title">{surface.title}</span>
568
+ </button>
569
+ <button type="button" className="tool-surface-tab-close" onClick={() => onClose(surface.id)} aria-label={`Close ${surface.title}`} title="Close">×</button>
570
+ </div>
571
+ )
572
+ })}
562
573
  </div>
563
574
  {hasOverflow && (
564
575
  <button
@@ -636,10 +647,19 @@ export default function ToolSurfacePage({
636
647
  <div className="tool-surface-tabs-dropdown-list">
637
648
  {surfaces.map((s) => {
638
649
  const isActive = s.id === active.id
650
+ const isPreview = s.kind === 'preview' && Boolean(s.artifact?.path)
639
651
  return (
640
652
  <div
641
653
  key={s.id}
642
654
  className={`tool-surface-tabs-dropdown-item ${isActive ? 'is-active' : ''}`}
655
+ draggable={isPreview}
656
+ onDragStart={isPreview ? (event) => {
657
+ setWorkspaceDragData(event.dataTransfer, {
658
+ path: s.artifact.path,
659
+ root: s.artifact.workspacePath || workspacePath,
660
+ url: s.artifact.url,
661
+ })
662
+ } : undefined}
643
663
  onClick={() => {
644
664
  onSelect(s.id)
645
665
  setTabsSwitcherOpen(false)
@@ -1,11 +1,128 @@
1
- import { useEffect, useRef, useState } from 'react'
1
+ import { useEffect, useRef, useState, useCallback } from 'react'
2
2
  import type { PDFDocumentProxy } from 'pdfjs-dist'
3
3
  import workerUrl from 'pdfjs-dist/legacy/build/pdf.worker.min.mjs?url'
4
4
  import { readPdfRange } from '../../utils/pdfRange'
5
5
  import WorkspaceFileInfo from './WorkspaceFileInfo'
6
6
  import '../../css/workspace-media-preview.css'
7
7
 
8
- export default function WorkspacePdfPreview({ url, path, root, byteLength, range }: { url: string; path: string; root?: string; byteLength?: number; range?: boolean }) {
8
+ function PdfPageItem({
9
+ pdf,
10
+ pageNumber,
11
+ width,
12
+ zoom,
13
+ onVisible,
14
+ }: {
15
+ pdf: PDFDocumentProxy
16
+ pageNumber: number
17
+ width: number
18
+ zoom: number
19
+ onVisible?: (page: number) => void
20
+ }) {
21
+ const canvasRef = useRef<HTMLCanvasElement>(null)
22
+ const containerRef = useRef<HTMLDivElement>(null)
23
+
24
+ useEffect(() => {
25
+ let cancelled = false
26
+ let renderTask: any = null
27
+
28
+ void pdf.getPage(pageNumber).then((page) => {
29
+ if (cancelled || !canvasRef.current) return
30
+ const normal = page.getViewport({ scale: 1 })
31
+ const viewport = page.getViewport({ scale: (width / normal.width) * zoom })
32
+ const output = Math.min(
33
+ window.devicePixelRatio || 1,
34
+ 2,
35
+ Math.sqrt(8_000_000 / (viewport.width * viewport.height))
36
+ )
37
+ const canvas = canvasRef.current
38
+ canvas.width = Math.ceil(viewport.width * output)
39
+ canvas.height = Math.ceil(viewport.height * output)
40
+ canvas.style.width = `${viewport.width}px`
41
+ canvas.style.height = `${viewport.height}px`
42
+
43
+ renderTask = page.render({
44
+ canvas,
45
+ viewport,
46
+ transform: output === 1 ? undefined : [output, 0, 0, output, 0, 0],
47
+ })
48
+ return renderTask.promise
49
+ }).catch(() => {})
50
+
51
+ return () => {
52
+ cancelled = true
53
+ renderTask?.cancel()
54
+ }
55
+ }, [pdf, pageNumber, width, zoom])
56
+
57
+ useEffect(() => {
58
+ if (!containerRef.current || !onVisible) return
59
+ const el = containerRef.current
60
+ const observer = new IntersectionObserver(
61
+ (entries) => {
62
+ for (const entry of entries) {
63
+ if (entry.isIntersecting && entry.intersectionRatio >= 0.4) {
64
+ onVisible(pageNumber)
65
+ }
66
+ }
67
+ },
68
+ { threshold: 0.4 }
69
+ )
70
+ observer.observe(el)
71
+ return () => observer.disconnect()
72
+ }, [pageNumber, onVisible])
73
+
74
+ return (
75
+ <div
76
+ ref={containerRef}
77
+ id={`pdf-page-${pageNumber}`}
78
+ className="workspace-pdf-page-container"
79
+ style={{
80
+ display: 'flex',
81
+ flexDirection: 'column',
82
+ alignItems: 'center',
83
+ marginBottom: '24px',
84
+ position: 'relative',
85
+ width: '100%',
86
+ }}
87
+ >
88
+ <canvas
89
+ ref={canvasRef}
90
+ style={{
91
+ boxShadow: '0 6px 24px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.08)',
92
+ borderRadius: 'var(--radius-xs, 6px)',
93
+ display: 'block',
94
+ background: '#ffffff',
95
+ maxWidth: '100%',
96
+ }}
97
+ aria-label={`PDF page ${pageNumber}`}
98
+ />
99
+ <span
100
+ style={{
101
+ marginTop: '8px',
102
+ fontSize: '11px',
103
+ color: 'var(--text-muted, #a1a1aa)',
104
+ fontWeight: 500,
105
+ }}
106
+ >
107
+ Slide {pageNumber} of {pdf.numPages}
108
+ </span>
109
+ </div>
110
+ )
111
+ }
112
+
113
+ export default function WorkspacePdfPreview({
114
+ url,
115
+ path,
116
+ root,
117
+ byteLength,
118
+ range,
119
+ }: {
120
+ url: string
121
+ path: string
122
+ root?: string
123
+ byteLength?: number
124
+ range?: boolean
125
+ }) {
9
126
  const [pdf, setPdf] = useState<PDFDocumentProxy | null>(null)
10
127
  const [pageNumber, setPageNumber] = useState(1)
11
128
  const [zoom, setZoom] = useState(1)
@@ -14,7 +131,6 @@ export default function WorkspacePdfPreview({ url, path, root, byteLength, range
14
131
  const [retry, setRetry] = useState(0)
15
132
  const [width, setWidth] = useState(500)
16
133
  const area = useRef<HTMLDivElement>(null)
17
- const canvas = useRef<HTMLCanvasElement>(null)
18
134
 
19
135
  useEffect(() => {
20
136
  const element = area.current
@@ -28,62 +144,165 @@ export default function WorkspacePdfPreview({ url, path, root, byteLength, range
28
144
  let cancelled = false
29
145
  let task: ReturnType<typeof import('pdfjs-dist').getDocument> | undefined
30
146
  const controllers = new Set<AbortController>()
31
- setPdf(null); setError(''); setLoading(true); setPageNumber(1)
147
+ setPdf(null)
148
+ setError('')
149
+ setLoading(true)
150
+ setPageNumber(1)
151
+
32
152
  void (async () => {
33
153
  const library = await import('pdfjs-dist/legacy/build/pdf.mjs')
34
154
  if (cancelled) return
35
155
  library.GlobalWorkerOptions.workerSrc = workerUrl
36
- const assets = import.meta.env.DEV ? new URL('/pdfjs/', location.href).href : new URL(['..', 'pdfjs', ''].join('/'), import.meta.url).href
37
- const options = { cMapUrl: `${assets}cmaps/`, cMapPacked: true, standardFontDataUrl: `${assets}standard_fonts/`, wasmUrl: `${assets}wasm/`, useSystemFonts: true, isEvalSupported: false, disableAutoFetch: true, disableStream: true }
156
+ const assets = import.meta.env.DEV
157
+ ? new URL('/pdfjs/', location.href).href
158
+ : new URL(['..', 'pdfjs', ''].join('/'), import.meta.url).href
159
+ const options = {
160
+ cMapUrl: `${assets}cmaps/`,
161
+ cMapPacked: true,
162
+ standardFontDataUrl: `${assets}standard_fonts/`,
163
+ wasmUrl: `${assets}wasm/`,
164
+ useSystemFonts: true,
165
+ isEvalSupported: false,
166
+ disableAutoFetch: true,
167
+ disableStream: true,
168
+ }
38
169
  if (range && byteLength) {
39
170
  class FileRanges extends library.PDFDataRangeTransport {
40
171
  requestDataRange(begin: number, end: number) {
41
- const controller = new AbortController(); controllers.add(controller)
42
- void readPdfRange(url, begin, end, controller.signal).then(bytes => { if (!cancelled) this.onDataRange(begin, bytes) }).catch(reason => {
43
- if (!cancelled) { setError(String(reason instanceof Error ? reason.message : reason)); setLoading(false); void task?.destroy() }
44
- }).finally(() => controllers.delete(controller))
172
+ const controller = new AbortController()
173
+ controllers.add(controller)
174
+ void readPdfRange(url, begin, end, controller.signal)
175
+ .then((bytes) => {
176
+ if (!cancelled) this.onDataRange(begin, bytes)
177
+ })
178
+ .catch((reason) => {
179
+ if (!cancelled) {
180
+ setError(String(reason instanceof Error ? reason.message : reason))
181
+ setLoading(false)
182
+ void task?.destroy()
183
+ }
184
+ })
185
+ .finally(() => controllers.delete(controller))
186
+ }
187
+ abort() {
188
+ for (const controller of controllers) controller.abort()
189
+ controllers.clear()
45
190
  }
46
- abort() { for (const controller of controllers) controller.abort(); controllers.clear() }
47
191
  }
48
- task = library.getDocument({ ...options, range: new FileRanges(byteLength, new Uint8Array()), rangeChunkSize: 64 * 1024 })
49
- } else task = library.getDocument({ ...options, url })
192
+ task = library.getDocument({
193
+ ...options,
194
+ range: new FileRanges(byteLength, new Uint8Array()),
195
+ rangeChunkSize: 64 * 1024,
196
+ })
197
+ } else {
198
+ task = library.getDocument({ ...options, url })
199
+ }
50
200
  const document = await task.promise
51
- if (!cancelled) setPdf(document)
52
- })().catch(reason => { if (!cancelled) { setError(reason instanceof Error ? reason.message : String(reason)); setLoading(false) } })
53
- return () => { cancelled = true; for (const controller of controllers) controller.abort(); void task?.destroy() }
201
+ if (!cancelled) {
202
+ setPdf(document)
203
+ setLoading(false)
204
+ }
205
+ })().catch((reason) => {
206
+ if (!cancelled) {
207
+ setError(reason instanceof Error ? reason.message : String(reason))
208
+ setLoading(false)
209
+ }
210
+ })
211
+
212
+ return () => {
213
+ cancelled = true
214
+ for (const controller of controllers) controller.abort()
215
+ void task?.destroy()
216
+ }
54
217
  }, [url, byteLength, range, retry])
55
218
 
219
+ const scrollToPage = useCallback((p: number) => {
220
+ if (!pdf) return
221
+ const target = Math.max(1, Math.min(pdf.numPages, p))
222
+ setPageNumber(target)
223
+ const el = document.getElementById(`pdf-page-${target}`)
224
+ if (el) {
225
+ el.scrollIntoView({ behavior: 'smooth', block: 'start' })
226
+ }
227
+ }, [pdf])
228
+
56
229
  useEffect(() => {
57
- if (!pdf || !canvas.current) return
58
- let cancelled = false
59
- let render: ReturnType<Awaited<ReturnType<PDFDocumentProxy['getPage']>>['render']> | undefined
60
- setLoading(true)
61
- void pdf.getPage(pageNumber).then(page => {
62
- if (cancelled || !canvas.current) return
63
- const normal = page.getViewport({ scale: 1 })
64
- const viewport = page.getViewport({ scale: width / normal.width * zoom })
65
- const output = Math.min(window.devicePixelRatio || 1, 2, Math.sqrt(8_000_000 / (viewport.width * viewport.height)))
66
- canvas.current.width = Math.ceil(viewport.width * output)
67
- canvas.current.height = Math.ceil(viewport.height * output)
68
- canvas.current.style.width = `${viewport.width}px`; canvas.current.style.height = `${viewport.height}px`
69
- render = page.render({ canvas: canvas.current, viewport, transform: output === 1 ? undefined : [output, 0, 0, output, 0, 0] })
70
- return render.promise
71
- }).then(() => { if (!cancelled) setLoading(false) }).catch(reason => { if (!cancelled) { setError(reason instanceof Error ? reason.message : String(reason)); setLoading(false) } })
72
- return () => { cancelled = true; render?.cancel() }
73
- }, [pdf, pageNumber, width, zoom])
230
+ if (!pdf) return
231
+ const onKeyDown = (e: KeyboardEvent) => {
232
+ const targetTag = (e.target as HTMLElement)?.tagName
233
+ if (['INPUT', 'TEXTAREA'].includes(targetTag)) return
234
+ if (e.key === 'ArrowRight' || e.key === 'ArrowDown' || e.key === 'PageDown' || e.key === ' ') {
235
+ e.preventDefault()
236
+ scrollToPage(pageNumber + 1)
237
+ } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp' || e.key === 'PageUp') {
238
+ e.preventDefault()
239
+ scrollToPage(pageNumber - 1)
240
+ }
241
+ }
242
+ window.addEventListener('keydown', onKeyDown)
243
+ return () => window.removeEventListener('keydown', onKeyDown)
244
+ }, [pdf, pageNumber, scrollToPage])
74
245
 
75
- return <section className="workspace-pdf-preview" aria-label="PDF preview">
76
- <div className="workspace-pdf-controls" role="toolbar" aria-label="PDF controls">
77
- <button type="button" aria-label="Previous PDF page" disabled={!pdf || pageNumber <= 1} onClick={() => setPageNumber(value => value - 1)}>Previous</button>
78
- <span aria-live="polite">{pageNumber} / {pdf?.numPages ?? '–'}</span>
79
- <button type="button" aria-label="Next PDF page" disabled={!pdf || pageNumber >= pdf.numPages} onClick={() => setPageNumber(value => value + 1)}>Next</button>
80
- <button type="button" aria-label="Zoom PDF out" disabled={zoom <= .5} onClick={() => setZoom(value => Math.max(.5, value - .25))}>−</button>
81
- <span>{Math.round(zoom * 100)}%</span>
82
- <button type="button" aria-label="Zoom PDF in" disabled={zoom >= 2} onClick={() => setZoom(value => Math.min(2, value + .25))}>+</button>
83
- </div>
84
- <div className="workspace-pdf-pages" ref={area}>
85
- {loading && !error && <p role="status">Loading PDF…</p>}
86
- {error ? <><p className="workspace-media-error" role="alert">Could not display PDF: {error}</p><button type="button" onClick={() => setRetry(value => value + 1)}>Retry PDF</button><WorkspaceFileInfo path={path} root={root} /></> : <canvas ref={canvas} aria-label={`PDF page ${pageNumber}`} />}
87
- </div>
88
- </section>
246
+ const pageCount = pdf?.numPages || 0
247
+ const pages = Array.from({ length: pageCount }, (_, i) => i + 1)
248
+
249
+ return (
250
+ <section className="workspace-pdf-preview" aria-label="PDF preview">
251
+ <div className="workspace-pdf-controls" role="toolbar" aria-label="PDF controls">
252
+ <span style={{ fontWeight: 600, fontSize: '12px', color: 'var(--text-main)' }} aria-live="polite">
253
+ Slide {pageNumber} / {pdf?.numPages ?? '–'}
254
+ </span>
255
+ <div style={{ height: '14px', width: '1px', background: 'var(--border)', margin: '0 4px' }} />
256
+ <div style={{ display: 'inline-flex', alignItems: 'center', gap: '6px' }}>
257
+ <button
258
+ type="button"
259
+ aria-label="Zoom PDF out"
260
+ disabled={zoom <= 0.5}
261
+ onClick={() => setZoom((value) => Math.max(0.5, value - 0.25))}
262
+ >
263
+ −
264
+ </button>
265
+ <span style={{ fontSize: '11px', minWidth: '36px', textAlign: 'center' }}>{Math.round(zoom * 100)}%</span>
266
+ <button
267
+ type="button"
268
+ aria-label="Zoom PDF in"
269
+ disabled={zoom >= 2}
270
+ onClick={() => setZoom((value) => Math.min(2, value + 0.25))}
271
+ >
272
+ +
273
+ </button>
274
+ </div>
275
+ </div>
276
+
277
+ <div className="workspace-pdf-pages" ref={area}>
278
+ {loading && !error && <p role="status">Loading PDF…</p>}
279
+ {error ? (
280
+ <>
281
+ <p className="workspace-media-error" role="alert">
282
+ Could not display PDF: {error}
283
+ </p>
284
+ <button type="button" onClick={() => setRetry((value) => value + 1)}>
285
+ Retry PDF
286
+ </button>
287
+ <WorkspaceFileInfo path={path} root={root} />
288
+ </>
289
+ ) : (
290
+ pdf && (
291
+ <div style={{ display: 'flex', flexDirection: 'column', width: '100%', alignItems: 'center' }}>
292
+ {pages.map((num) => (
293
+ <PdfPageItem
294
+ key={num}
295
+ pdf={pdf}
296
+ pageNumber={num}
297
+ width={width}
298
+ zoom={zoom}
299
+ onVisible={setPageNumber}
300
+ />
301
+ ))}
302
+ </div>
303
+ )
304
+ )}
305
+ </div>
306
+ </section>
307
+ )
89
308
  }
@@ -43,9 +43,9 @@ it('renders images fitted inside Preview without a binary code tab and with form
43
43
  expect(webpHtml).toContain('WEBP')
44
44
  })
45
45
 
46
- it('identifies the browser action as Mint Browser instead of a generic popup', () => {
46
+ it('identifies the browser action as preview in system browser', () => {
47
47
  const html = renderToStaticMarkup(<ArtifactPreviewPanel artifact={{ path: 'site/index.html', url: 'http://127.0.0.1:12345/site/index.html' }} onClose={() => {}} />)
48
- expect(html).toContain('aria-label="Open in Mint Browser (Mint Auto)"')
48
+ expect(html).toContain('aria-label="Open preview"')
49
49
  })
50
50
 
51
51
  it('renders pure code files in code mode with language chip and without preview toggle or browser button', () => {
@@ -62,7 +62,7 @@ it('renders pure code files in code mode with language chip and without preview
62
62
  expect(html).toContain('import')
63
63
  expect(html).toContain('json')
64
64
  expect(html).toContain('hello')
65
- expect(html).not.toContain('aria-label="Open in Mint Browser (Mint Auto)"')
65
+ expect(html).not.toContain('aria-label="Open preview"')
66
66
  })
67
67
 
68
68
  it('renders dual-mode toggles for markdown, svg, and html without showing browser button for non-html', () => {
@@ -71,19 +71,31 @@ it('renders dual-mode toggles for markdown, svg, and html without showing browse
71
71
  )
72
72
  expect(mdHtml).toMatch(/>Preview<\/button>/)
73
73
  expect(mdHtml).toMatch(/>Code<\/button>/)
74
- expect(mdHtml).not.toContain('aria-label="Open in Mint Browser (Mint Auto)"')
74
+ expect(mdHtml).not.toContain('aria-label="Open preview"')
75
75
 
76
76
  const svgHtml = renderToStaticMarkup(
77
77
  <ArtifactPreviewPanel artifact={{ path: 'icons/logo.svg', content: '<svg></svg>' }} onClose={() => {}} />,
78
78
  )
79
79
  expect(svgHtml).toMatch(/>Preview<\/button>/)
80
80
  expect(svgHtml).toMatch(/>Code<\/button>/)
81
- expect(svgHtml).not.toContain('aria-label="Open in Mint Browser (Mint Auto)"')
81
+ expect(svgHtml).not.toContain('aria-label="Open preview"')
82
82
 
83
83
  const webHtml = renderToStaticMarkup(
84
84
  <ArtifactPreviewPanel artifact={{ path: 'index.html', content: '<h1>Hi</h1>' }} onClose={() => {}} />,
85
85
  )
86
86
  expect(webHtml).toMatch(/>Preview<\/button>/)
87
87
  expect(webHtml).toMatch(/>Code<\/button>/)
88
- expect(webHtml).toContain('aria-label="Open in Mint Browser (Mint Auto)"')
88
+ expect(webHtml).toContain('aria-label="Open preview"')
89
89
  })
90
+
91
+ it('makes the artifact header draggable for dragging into chat', () => {
92
+ const html = renderToStaticMarkup(
93
+ <ArtifactPreviewPanel
94
+ artifact={{ path: 'Harness_Presentation.pdf', content: '' }}
95
+ onClose={() => {}}
96
+ />,
97
+ )
98
+ expect(html).toContain('draggable="true"')
99
+ expect(html).toContain('artifact-preview-header-drag')
100
+ })
101
+
@@ -48,7 +48,7 @@
48
48
  height: 36px;
49
49
  place-items: center;
50
50
  border: 1px solid color-mix(in srgb, var(--accent, #10b981) 28%, transparent);
51
- border-radius: 11px;
51
+ border-radius: var(--radius-md, 10px);
52
52
  background: color-mix(in srgb, var(--accent, #10b981) 10%, transparent);
53
53
  color: var(--accent, #10b981);
54
54
  font-weight: 700;
@@ -80,7 +80,7 @@
80
80
  min-height: 38px;
81
81
  padding: 0 10px;
82
82
  border: 1px solid var(--border, #343438);
83
- border-radius: 10px;
83
+ border-radius: var(--radius-md, 10px);
84
84
  background: var(--bg-surface-soft, rgba(255, 255, 255, 0.03));
85
85
  color: var(--text-main, #eeeeef);
86
86
  cursor: pointer;
@@ -95,7 +95,7 @@
95
95
  .background-terminal-panel > p {
96
96
  margin: 0;
97
97
  padding: 9px 10px;
98
- border-radius: 9px;
98
+ border-radius: var(--radius-sm, 8px);
99
99
  background: color-mix(in srgb, var(--status-error, #f18585) 9%, transparent);
100
100
  }
101
101
 
@@ -116,7 +116,7 @@
116
116
  gap: 7px;
117
117
  padding: 22px 14px;
118
118
  border: 1px dashed var(--border, #343438);
119
- border-radius: 12px;
119
+ border-radius: var(--radius-xl, 18px);
120
120
  color: var(--text-muted, #94a3b8);
121
121
  text-align: center;
122
122
  }
@@ -126,7 +126,7 @@
126
126
  width: 34px;
127
127
  height: 34px;
128
128
  place-items: center;
129
- border-radius: 10px;
129
+ border-radius: var(--radius-md, 10px);
130
130
  background: var(--bg-surface-soft, rgba(255, 255, 255, 0.05));
131
131
  color: var(--accent, #10b981);
132
132
  font-weight: 700;
@@ -147,7 +147,7 @@
147
147
  min-width: 0;
148
148
  padding: 11px;
149
149
  border: 1px solid var(--border, #343438);
150
- border-radius: 12px;
150
+ border-radius: var(--radius-xl, 18px);
151
151
  background: var(--bg-surface-soft, rgba(255, 255, 255, 0.025));
152
152
  }
153
153
 
@@ -172,7 +172,7 @@
172
172
 
173
173
  .background-terminal-state {
174
174
  padding: 2px 7px;
175
- border-radius: 999px;
175
+ border-radius: var(--radius-full, 9999px);
176
176
  background: var(--bg-surface-hover, rgba(255, 255, 255, 0.06));
177
177
  font-size: 10px;
178
178
  text-transform: capitalize;
@@ -187,7 +187,7 @@
187
187
  margin: 9px 0 7px;
188
188
  padding: 8px 9px;
189
189
  border: 1px solid var(--border, #343438);
190
- border-radius: 8px;
190
+ border-radius: var(--radius-sm, 8px);
191
191
  background: var(--input-bg, #101012);
192
192
  color: var(--text-main, #eeeeef);
193
193
  white-space: pre-wrap;
@@ -211,7 +211,7 @@
211
211
  min-height: 30px;
212
212
  padding: 5px 9px;
213
213
  border: 1px solid var(--border, #343438);
214
- border-radius: 8px;
214
+ border-radius: var(--radius-sm, 8px);
215
215
  background: var(--bg-surface-soft, rgba(255, 255, 255, 0.04));
216
216
  cursor: pointer;
217
217
  text-decoration: none;
@@ -254,7 +254,7 @@
254
254
  overflow: auto;
255
255
  padding: 10px;
256
256
  border: 1px solid var(--border, #343438);
257
- border-radius: 9px;
257
+ border-radius: var(--radius-sm, 8px);
258
258
  background: var(--input-bg, #101012);
259
259
  }
260
260
 
@@ -285,7 +285,7 @@
285
285
  .background-terminal-output > header > button {
286
286
  display: inline-flex; align-items: center; justify-content: center;
287
287
  width: 26px; height: 26px; margin-left: auto; padding: 0;
288
- border: 1px solid var(--border, #343438); border-radius: 7px;
288
+ border: 1px solid var(--border, #343438); border-radius: var(--radius-sm, 8px);
289
289
  background: var(--bg-surface-soft, rgba(255,255,255,.04)); color: var(--text-muted, #94a3b8);
290
290
  cursor: pointer;
291
291
  }
@@ -9,6 +9,7 @@ export const DEFAULT_CONFIG = {
9
9
  theme: 'dark',
10
10
  tuiTheme: 'dark' as 'system' | 'dark' | 'light',
11
11
  accentColor: '#10b981',
12
+ textColor: '#f8fafc',
12
13
  systemTextColor: '#f8fafc',
13
14
  chatTextColor: '#f8fafc',
14
15
  customBgStart: '#0f172a',
@@ -66,14 +67,9 @@ export const DEFAULT_CONFIG = {
66
67
  hfApiKey: '',
67
68
  bflApiKey: '',
68
69
  bflModel: 'flux-pro-1.1',
69
- automationBrowser: 'chromium',
70
- browserAutomationEnabled: true,
71
- browserAgentMode: 'headless',
72
70
  browserExecutable: '',
73
71
  browserViewportWidth: 1440,
74
72
  browserViewportHeight: 900,
75
- browserDebugUrl: 'http://127.0.0.1:9222/json/list',
76
- browserExtensionContextUrl: 'http://127.0.0.1:3212/context',
77
73
  enableHeadlessTaskQueue: false,
78
74
  enableAutoUpdate: false,
79
75
  updaterEndpoint: '',