@pheem49/mint 1.16.0 → 1.17.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 (848) hide show
  1. package/Cargo.lock +6 -6
  2. package/Cargo.toml +1 -1
  3. package/README.md +1 -1
  4. package/Release_Note.md +71 -72
  5. package/apps/mint-companion/src-tauri/src/compact.rs +69 -0
  6. package/apps/mint-companion/src-tauri/src/main.rs +218 -11
  7. package/apps/mint-companion/vite.config.ts +2 -1
  8. package/crates/mint-cli/src/agent/live_status.rs +43 -2
  9. package/crates/mint-cli/src/agent.rs +178 -38
  10. package/crates/mint-cli/src/commands/agent.rs +225 -31
  11. package/crates/mint-cli/src/commands/browser.rs +127 -0
  12. package/crates/mint-cli/src/commands/config.rs +14 -1
  13. package/crates/mint-cli/src/commands/knowledge.rs +16 -2
  14. package/crates/mint-cli/src/commands/mod.rs +15 -1
  15. package/crates/mint-cli/src/commands/tailnet_web.rs +2 -7
  16. package/crates/mint-cli/src/companion_navigation.rs +268 -0
  17. package/crates/mint-cli/src/interactive/chat_tui.rs +1065 -63
  18. package/crates/mint-cli/src/interactive/command_ui.rs +39 -0
  19. package/crates/mint-cli/src/interactive/slash_commands.rs +114 -6
  20. package/crates/mint-cli/src/interactive/tool_activity.rs +375 -36
  21. package/crates/mint-cli/src/interactive.rs +37 -5
  22. package/crates/mint-cli/src/main.rs +23 -2
  23. package/crates/mint-cli/src/onboard.rs +3494 -1336
  24. package/crates/mint-cli/tests/mods_testing.rs +5 -1
  25. package/crates/mint-companion-protocol/src/lib.rs +113 -0
  26. package/crates/mint-core/src/agent/chat.rs +240 -1
  27. package/crates/mint-core/src/agent/memory.rs +73 -6
  28. package/crates/mint-core/src/agent/safety.rs +56 -4
  29. package/crates/mint-core/src/agent/skill_inventory.rs +3 -1
  30. package/crates/mint-core/src/agent/skills.rs +1 -0
  31. package/crates/mint-core/src/api_server/routes/auth.rs +1 -4
  32. package/crates/mint-core/src/api_server/routes/chat.rs +29 -15
  33. package/crates/mint-core/src/api_server/routes/misc.rs +116 -0
  34. package/crates/mint-core/src/api_server/routes/profile_oauth.rs +43 -26
  35. package/crates/mint-core/src/api_server/routes/sessions.rs +93 -76
  36. package/crates/mint-core/src/api_server/routes/skills_subagents.rs +11 -7
  37. package/crates/mint-core/src/api_server/routes/status_health.rs +18 -8
  38. package/crates/mint-core/src/api_server.rs +211 -65
  39. package/crates/mint-core/src/avatar_bridge.rs +5 -2
  40. package/crates/mint-core/src/browser/cdp.rs +82 -26
  41. package/crates/mint-core/src/browser/lifecycle.rs +143 -43
  42. package/crates/mint-core/src/browser/mod.rs +5 -4
  43. package/crates/mint-core/src/browser/navigate.rs +82 -9
  44. package/crates/mint-core/src/browser/runtime.rs +284 -0
  45. package/crates/mint-core/src/browser/session.rs +263 -7
  46. package/crates/mint-core/src/browser/workflow.rs +386 -0
  47. package/crates/mint-core/src/companion/navigation.rs +115 -0
  48. package/crates/mint-core/src/companion.rs +109 -1
  49. package/crates/mint-core/src/integrations/mcp_result.rs +45 -0
  50. package/crates/mint-core/src/lib.rs +10 -6
  51. package/crates/mint-core/src/media/image_proxy.rs +563 -0
  52. package/crates/mint-core/src/media/tool_images.rs +196 -0
  53. package/crates/mint-core/src/media/tts/playback.rs +609 -0
  54. package/crates/mint-core/src/media/tts.rs +1 -0
  55. package/crates/mint-core/src/media.rs +2 -0
  56. package/crates/mint-core/src/orchestration/context_render.rs +450 -33
  57. package/crates/mint-core/src/orchestration/decision_parsing.rs +5 -23
  58. package/crates/mint-core/src/orchestration/diagnostics.rs +307 -0
  59. package/crates/mint-core/src/orchestration/image_regressions.rs +379 -0
  60. package/crates/mint-core/src/orchestration/loop_guard.rs +334 -0
  61. package/crates/mint-core/src/orchestration/mod.rs +1104 -560
  62. package/crates/mint-core/src/orchestration/reliability.rs +541 -0
  63. package/crates/mint-core/src/orchestration/repeated_failures.rs +8 -0
  64. package/crates/mint-core/src/orchestration/review_regressions.rs +174 -28
  65. package/crates/mint-core/src/orchestration/tools/files.rs +31 -3
  66. package/crates/mint-core/src/orchestration/tools/plugins_mcp.rs +19 -4
  67. package/crates/mint-core/src/orchestration/tools/project.rs +1 -1
  68. package/crates/mint-core/src/orchestration/tools/shell.rs +29 -5
  69. package/crates/mint-core/src/orchestration/tools/web.rs +5 -1
  70. package/crates/mint-core/src/orchestration/trajectory_schema.rs +353 -0
  71. package/crates/mint-core/src/orchestration/truncation.rs +211 -0
  72. package/crates/mint-core/src/orchestration/verification.rs +36 -6
  73. package/crates/mint-core/src/orchestration/workspace_helpers.rs +54 -23
  74. package/crates/mint-core/src/prompts/agent.rs +31 -40
  75. package/crates/mint-core/src/prompts/tool_catalog.rs +134 -40
  76. package/crates/mint-core/src/search/web_search.rs +44 -3
  77. package/crates/mint-core/src/slash/mod.rs +464 -1
  78. package/crates/mint-core/src/swarm/batch.rs +643 -0
  79. package/crates/mint-core/src/swarm/dossier.rs +152 -0
  80. package/crates/mint-core/src/swarm/labels.rs +100 -0
  81. package/crates/mint-core/src/swarm/mod.rs +158 -0
  82. package/crates/mint-core/src/swarm/permissions.rs +167 -0
  83. package/crates/mint-core/src/system/auth.rs +156 -7
  84. package/crates/mint-core/src/system/bg_shell.rs +77 -9
  85. package/crates/mint-core/src/system/config.rs +92 -3
  86. package/crates/mint-core/src/system/mint_web.rs +33 -12
  87. package/crates/mint-core/src/system/shell.rs +179 -10
  88. package/crates/mint-core/src/system/workspace.rs +204 -0
  89. package/crates/mint-core/tests/background_retention.rs +1 -1
  90. package/crates/mint-core/tests/memory_persistence.rs +27 -0
  91. package/out/web/assets/ArtifactPreviewPanel-DAT_Y7i0.css +1 -0
  92. package/out/web/assets/ArtifactPreviewPanel-S0dPfYFx.js +2 -0
  93. package/out/web/assets/CalculationCard-CRjP3E1j.js +1 -0
  94. package/out/web/assets/{CliSessionsView-CtzUJpK_.css → CliSessionsView-C3Br2v5Y.css} +1 -1
  95. package/out/web/assets/CliSessionsView-MI8kXMAb.js +1 -0
  96. package/out/web/assets/CodeReviewPage-CUJceQme.css +1 -0
  97. package/out/web/assets/CodeReviewPage-VCUgPla_.js +2 -0
  98. package/out/web/assets/CommandPalette-BD8SlTE5.js +1 -0
  99. package/out/web/assets/ImageGenCard-BCXxkVJX.js +1 -0
  100. package/out/web/assets/ImageSearchCard-N3yQOr8Z.js +1 -0
  101. package/out/web/assets/ImageStudioPanel-BP7N4rLr.js +1 -0
  102. package/out/web/assets/LibraryPage-WlviRdR8.js +2 -0
  103. package/out/web/assets/LinkedFoldersView-CKRgroWK.js +1 -0
  104. package/out/web/assets/McpRegistryPicker-CoS83vtc.js +1 -0
  105. package/out/web/assets/McpServersView-D3wHnuHg.js +1 -0
  106. package/out/web/assets/MermaidCard-NqrHdyJW.js +2 -0
  107. package/out/web/assets/MintDashboard-B2DJsDDO.css +1 -0
  108. package/out/web/assets/MintDashboard-COw_xol7.js +63 -0
  109. package/out/web/assets/PluginsView-jBYmcKh4.js +1 -0
  110. package/out/web/assets/RewindModal-DempuDod.js +1 -0
  111. package/out/web/assets/ScheduledTasksView-5uw9-V9H.js +1 -0
  112. package/out/web/assets/SelectField-DXBQtrUK.js +1 -0
  113. package/out/web/assets/SelectField-lFEkkWCU.css +1 -0
  114. package/out/web/assets/SettingsWindow-2YP3yj7s.js +4 -0
  115. package/out/web/assets/SettingsWindow-Dz8LQVgD.css +1 -0
  116. package/out/web/assets/SkillsView-C-gp9J7m.js +2 -0
  117. package/out/web/assets/StockCard-BDMCe7mx.js +1 -0
  118. package/out/web/assets/ToolSurfacePage-B0J_q0Jl.js +38 -0
  119. package/out/web/assets/ToolSurfacePage-CRIQ1owD.css +1 -0
  120. package/out/web/assets/UiFeatureCard-6BwxTOCe.js +1 -0
  121. package/out/web/assets/UiGridCard-DvZcLNxb.js +1 -0
  122. package/out/web/assets/UiMockupWidget-DD73QWg1.js +1 -0
  123. package/out/web/assets/VeoStudioPanel-DfsOJKv0.js +4 -0
  124. package/out/web/assets/WeatherCard-CPucIfq8.js +1 -0
  125. package/out/web/assets/WorkspacePanel-BfHKkulU.js +1 -0
  126. package/out/web/assets/WorkspacePdfPreview-Dx_lkjNu.js +2 -0
  127. package/out/web/assets/abnfDiagram-VCTEODGH-BOo3Ckng.js +1 -0
  128. package/out/web/assets/architecture-7GRP2DOG-ZOwheW3n.js +1 -0
  129. package/out/web/assets/architectureDiagram-5GKGNRK7-DC2FDzVd.js +36 -0
  130. package/out/web/assets/{blockDiagram-NRAW4CY4-BrrqzHW5.js → blockDiagram-I7D4REHJ-BrKFWdAH.js} +4 -4
  131. package/out/web/assets/c4Diagram-7LVT6UL2-BHTHK1Yd.js +38 -0
  132. package/out/web/assets/chunk-2Q5K7J3B-D2JLPQzF.js +1 -0
  133. package/out/web/assets/{chunk-TEH6E4GO-G4Cdlyrt.js → chunk-4HAMMTFA-BYFkZwNj.js} +3 -3
  134. package/out/web/assets/{chunk-5VM5RSS4-BiPuE0io.js → chunk-5VM5RSS4-BZ2oBPYQ.js} +1 -1
  135. package/out/web/assets/chunk-75Z2AOVW-BSKfSKSA.js +2 -0
  136. package/out/web/assets/chunk-DU6HZSFF-vIhsiW6n.js +128 -0
  137. package/out/web/assets/chunk-F27PBJKO-BlYpW9xq.js +1 -0
  138. package/out/web/assets/chunk-FOHPRMQF-JXEeeJ9r.js +161 -0
  139. package/out/web/assets/{chunk-GMAD6QVW-BuhEcgHq.js → chunk-GMAD6QVW-BIBz_Ug5.js} +12 -12
  140. package/out/web/assets/chunk-GVQU2GXP-NPSHxeqC.js +1 -0
  141. package/out/web/assets/chunk-IMKFNOWR-YlJK8_Fp.js +231 -0
  142. package/out/web/assets/chunk-JWPE2WC7-BeEMUFDw.js +1 -0
  143. package/out/web/assets/chunk-L3NEJ4N5-DMYi4-af.js +1 -0
  144. package/out/web/assets/chunk-OSK3NFVY-Begd3-jA.js +10 -0
  145. package/out/web/assets/chunk-P2QGCYS3-D1I4xFHN.js +1 -0
  146. package/out/web/assets/chunk-POPQ4Y6H-CafZZzNE.js +1 -0
  147. package/out/web/assets/chunk-PWAF6VOD-Dwh6_Lnt.js +1 -0
  148. package/out/web/assets/chunk-SHT3W25Y-B0XrCSEb.js +168 -0
  149. package/out/web/assets/{chunk-SVP7TREG-Bu_yYb-V.js → chunk-SVP7TREG-CxLsddxC.js} +1 -1
  150. package/out/web/assets/{chunk-LCL6LL3I-BhXV9zyH.js → chunk-TICWLB2K-y156QInb.js} +4 -4
  151. package/out/web/assets/chunk-XXDRQBXY-B9YlhOkE.js +1 -0
  152. package/out/web/assets/chunk-Y2CYZVJY-BxCWjNVG.js +1 -0
  153. package/out/web/assets/classDiagram-ZZMXUADV-BgJ5WtSp.js +1 -0
  154. package/out/web/assets/classDiagram-v2-VYDZK3BY-BgJ5WtSp.js +1 -0
  155. package/out/web/assets/config-CvIO5hkn.js +2 -0
  156. package/out/web/assets/config-DqXJXeZM.css +1 -0
  157. package/out/web/assets/core-Mi3s5D4_.js +1 -0
  158. package/out/web/assets/cose-bilkent-JH36ORCC-qlna31ty.js +1 -0
  159. package/out/web/assets/cynefin-OW5HDTMX-SMVvrLf-.js +1 -0
  160. package/out/web/assets/cynefinDiagram-5FMLGOSQ-rZznN24T.js +62 -0
  161. package/out/web/assets/cytoscape.esm-DWtAUG0r.js +321 -0
  162. package/out/web/assets/dagre-CnWJJM5f.js +1 -0
  163. package/out/web/assets/dagre-GXQ25YYZ-BOToydFu.js +4 -0
  164. package/out/web/assets/diagram-S7CK7UJ4-TMVaGQEJ.js +30 -0
  165. package/out/web/assets/diagram-UQ7AKVKN-C2JK-GP2.js +41 -0
  166. package/out/web/assets/{diagram-VSXAHHWV-BJ86Ov2Y.js → diagram-VSXAHHWV-Cw8VSi2K.js} +1 -1
  167. package/out/web/assets/diagram-VX7I27RA-DXp4fKk9.js +24 -0
  168. package/out/web/assets/diagram-Z3DM3KII-CzSicYiW.js +24 -0
  169. package/out/web/assets/dist-9ISJ7r-g.js +1 -0
  170. package/out/web/assets/dist-js-BV3mI7uw.js +1 -0
  171. package/out/web/assets/ebnfDiagram-PWID7BFC-Dqj-zqPu.js +1 -0
  172. package/out/web/assets/{erDiagram-SSCWMZ5O-CzzmnZWT.js → erDiagram-RLTQ6QDP-DZwFZAuD.js} +3 -3
  173. package/out/web/assets/event-D7D-EBy9.js +1 -0
  174. package/out/web/assets/eventmodeling-NTZA5JFV-C0O-Lvgp.js +1 -0
  175. package/out/web/assets/flowDiagram-HODETNUW-uqCHJond.js +1 -0
  176. package/out/web/assets/ganttDiagram-EL5Y4UJY-Da4ULXTl.js +292 -0
  177. package/out/web/assets/gitGraph-4MIJSDKK-B9wNFZIP.js +1 -0
  178. package/out/web/assets/gitGraphDiagram-WWUBYQGX-RjrhB0MP.js +106 -0
  179. package/out/web/assets/graphlib-Bh9gHply.js +1 -0
  180. package/out/web/assets/index-BmpulIkg.js +168 -0
  181. package/out/web/assets/index-CkvBwhX_.css +1 -0
  182. package/out/web/assets/info-A6RAGUB7-B3dfCpeY.js +1 -0
  183. package/out/web/assets/infoDiagram-27XIBGKW-QVWkLVx7.js +2 -0
  184. package/out/web/assets/{ishikawaDiagram-5VMMS53U-s38yo28y.js → ishikawaDiagram-5VMMS53U-CLFNIRI9.js} +4 -4
  185. package/out/web/assets/journeyDiagram-3NMN7TZE-fgOQadYF.js +139 -0
  186. package/out/web/assets/jsx-runtime-DmUwWVTj.js +1 -0
  187. package/out/web/assets/{kanban-definition-3QL26DDD-DodjgySL.js → kanban-definition-UXKFOSKX-G3Q_9g9O.js} +6 -6
  188. package/out/web/assets/katex-MCdQaEAD.js +257 -0
  189. package/out/web/assets/mermaid-parser.core-v3Jm7nco.js +7 -0
  190. package/out/web/assets/mermaid.core-DTEjLUA1.js +44 -0
  191. package/out/web/assets/{mindmap-definition-FBJOCRG2-260WBDxZ.js → mindmap-definition-YA3MSWOX-C_D42_fF.js} +4 -4
  192. package/out/web/assets/modelManager-BPLycQrN.js +2 -0
  193. package/out/web/assets/oauthManager-BUK7ic7q.js +1 -0
  194. package/out/web/assets/packet-AYTQ26CC-B-R-SHlF.js +1 -0
  195. package/out/web/assets/pdf-Bcahc2yC.js +56 -0
  196. package/out/web/assets/pdf.worker.min-Dkey6ZUl.mjs +27 -0
  197. package/out/web/assets/pegDiagram-XKGWAZYB-Da2q_giz.js +1 -0
  198. package/out/web/assets/pie-WAS4IAKB-BC8F0N7-.js +1 -0
  199. package/out/web/assets/pieDiagram-E7YTZNPT-Iy9REJNC.js +39 -0
  200. package/out/web/assets/{quadrantDiagram-AXDQQJYC-B8D3gU5d.js → quadrantDiagram-AXDQQJYC-ztsiYw7h.js} +4 -4
  201. package/out/web/assets/radar-RG4KPBEZ-B_1P8Z_z.js +1 -0
  202. package/out/web/assets/railroad-74A4TZTK-DuTqczSo.js +1 -0
  203. package/out/web/assets/railroad-abnf-HS5TGJTU-Df29WLmp.js +1 -0
  204. package/out/web/assets/railroad-ebnf-LZEXJU2U-ePFMo-qp.js +1 -0
  205. package/out/web/assets/railroad-peg-WCYAUIDC-DYXLW4_E.js +1 -0
  206. package/out/web/assets/railroadDiagram-O6MQD6OU-LStnZf2S.js +1 -0
  207. package/out/web/assets/{requirementDiagram-EFPCY7ZU-D2X-Ewik.js → requirementDiagram-BXWQKSXE-DmzonMH-.js} +3 -3
  208. package/out/web/assets/rolldown-runtime-CNOWq4Kh.js +1 -0
  209. package/out/web/assets/rough.esm-CNnFptCR.js +1 -0
  210. package/out/web/assets/sankeyDiagram-P5KCCOFB-B8vjmUU1.js +40 -0
  211. package/out/web/assets/sequenceDiagram-WJ2MYXX4-CTnplOAX.js +162 -0
  212. package/out/web/assets/sizeCapture-INFHLROL-C8Q8DbV5.js +1 -0
  213. package/out/web/assets/src-CRDfRlHM.js +1 -0
  214. package/out/web/assets/stateDiagram-D77RDMKH-BFrIaLdI.js +1 -0
  215. package/out/web/assets/stateDiagram-v2-MP3YSRHH-uf3kdNW4.js +1 -0
  216. package/out/web/assets/studio-BBZQ_-QK.js +1 -0
  217. package/out/web/assets/swimlanes-42K2YHIH-BXGngUNU.js +1 -0
  218. package/out/web/assets/swimlanesDiagram-VR7AAH4N-Y8q5bQce.js +8 -0
  219. package/out/web/assets/timeline-definition-24CTP7MA-CegH7n43.js +120 -0
  220. package/out/web/assets/treeView-Q6P3EWNA-DTpJv2Tw.js +1 -0
  221. package/out/web/assets/treemap-WGGIJYW6-i8M9iJU6.js +1 -0
  222. package/out/web/assets/vennDiagram-4TSXK5OY-Dpzo1S8U.js +34 -0
  223. package/out/web/assets/wardley-WFR3VGLG-BrNsgtfw.js +1 -0
  224. package/out/web/assets/{wardleyDiagram-VM6X3IG4-DAdXELbQ.js → wardleyDiagram-VM6X3IG4-lQ92LFE1.js} +35 -35
  225. package/out/web/assets/window-CkUOP7t0.js +1 -0
  226. package/out/web/assets/workspaces-SYPrmbgC.js +1 -0
  227. package/out/web/assets/{xychartDiagram-S5SC5T6Z-IZIXf3Vo.js → xychartDiagram-S5SC5T6Z-BaOaEoBd.js} +4 -4
  228. package/out/web/index-web.html +4 -4
  229. package/out/web/index.html +4 -4
  230. package/out/web/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  231. package/out/web/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  232. package/out/web/pdfjs/cmaps/78-H.bcmap +0 -0
  233. package/out/web/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  234. package/out/web/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  235. package/out/web/pdfjs/cmaps/78-V.bcmap +0 -0
  236. package/out/web/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  237. package/out/web/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  238. package/out/web/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  239. package/out/web/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  240. package/out/web/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  241. package/out/web/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  242. package/out/web/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  243. package/out/web/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  244. package/out/web/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  245. package/out/web/pdfjs/cmaps/Add-H.bcmap +0 -0
  246. package/out/web/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  247. package/out/web/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  248. package/out/web/pdfjs/cmaps/Add-V.bcmap +0 -0
  249. package/out/web/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  250. package/out/web/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  251. package/out/web/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  252. package/out/web/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  253. package/out/web/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  254. package/out/web/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  255. package/out/web/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  256. package/out/web/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  257. package/out/web/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  258. package/out/web/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  259. package/out/web/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  260. package/out/web/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  261. package/out/web/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  262. package/out/web/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  263. package/out/web/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  264. package/out/web/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  265. package/out/web/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  266. package/out/web/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  267. package/out/web/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  268. package/out/web/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  269. package/out/web/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  270. package/out/web/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  271. package/out/web/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  272. package/out/web/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  273. package/out/web/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  274. package/out/web/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  275. package/out/web/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  276. package/out/web/pdfjs/cmaps/B5-H.bcmap +0 -0
  277. package/out/web/pdfjs/cmaps/B5-V.bcmap +0 -0
  278. package/out/web/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  279. package/out/web/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  280. package/out/web/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  281. package/out/web/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  282. package/out/web/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  283. package/out/web/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  284. package/out/web/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  285. package/out/web/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  286. package/out/web/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  287. package/out/web/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  288. package/out/web/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  289. package/out/web/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  290. package/out/web/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  291. package/out/web/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  292. package/out/web/pdfjs/cmaps/EUC-H.bcmap +0 -0
  293. package/out/web/pdfjs/cmaps/EUC-V.bcmap +0 -0
  294. package/out/web/pdfjs/cmaps/Ext-H.bcmap +0 -0
  295. package/out/web/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  296. package/out/web/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  297. package/out/web/pdfjs/cmaps/Ext-V.bcmap +0 -0
  298. package/out/web/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  299. package/out/web/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  300. package/out/web/pdfjs/cmaps/GB-H.bcmap +4 -0
  301. package/out/web/pdfjs/cmaps/GB-V.bcmap +0 -0
  302. package/out/web/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  303. package/out/web/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  304. package/out/web/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  305. package/out/web/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  306. package/out/web/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  307. package/out/web/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  308. package/out/web/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  309. package/out/web/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  310. package/out/web/pdfjs/cmaps/GBT-H.bcmap +0 -0
  311. package/out/web/pdfjs/cmaps/GBT-V.bcmap +0 -0
  312. package/out/web/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  313. package/out/web/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  314. package/out/web/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  315. package/out/web/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  316. package/out/web/pdfjs/cmaps/H.bcmap +0 -0
  317. package/out/web/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  318. package/out/web/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  319. package/out/web/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  320. package/out/web/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  321. package/out/web/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  322. package/out/web/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  323. package/out/web/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  324. package/out/web/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  325. package/out/web/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  326. package/out/web/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  327. package/out/web/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  328. package/out/web/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  329. package/out/web/pdfjs/cmaps/Hankaku.bcmap +0 -0
  330. package/out/web/pdfjs/cmaps/Hiragana.bcmap +0 -0
  331. package/out/web/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  332. package/out/web/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  333. package/out/web/pdfjs/cmaps/KSC-H.bcmap +0 -0
  334. package/out/web/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  335. package/out/web/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  336. package/out/web/pdfjs/cmaps/KSC-V.bcmap +0 -0
  337. package/out/web/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  338. package/out/web/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  339. package/out/web/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  340. package/out/web/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  341. package/out/web/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  342. package/out/web/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  343. package/out/web/pdfjs/cmaps/Katakana.bcmap +0 -0
  344. package/out/web/pdfjs/cmaps/LICENSE +36 -0
  345. package/out/web/pdfjs/cmaps/NWP-H.bcmap +0 -0
  346. package/out/web/pdfjs/cmaps/NWP-V.bcmap +0 -0
  347. package/out/web/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  348. package/out/web/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  349. package/out/web/pdfjs/cmaps/Roman.bcmap +0 -0
  350. package/out/web/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  351. package/out/web/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  352. package/out/web/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  353. package/out/web/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  354. package/out/web/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  355. package/out/web/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  356. package/out/web/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  357. package/out/web/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  358. package/out/web/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  359. package/out/web/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  360. package/out/web/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  361. package/out/web/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  362. package/out/web/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  363. package/out/web/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  364. package/out/web/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  365. package/out/web/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  366. package/out/web/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  367. package/out/web/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  368. package/out/web/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  369. package/out/web/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  370. package/out/web/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  371. package/out/web/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  372. package/out/web/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  373. package/out/web/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  374. package/out/web/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  375. package/out/web/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  376. package/out/web/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  377. package/out/web/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  378. package/out/web/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  379. package/out/web/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  380. package/out/web/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  381. package/out/web/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  382. package/out/web/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  383. package/out/web/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  384. package/out/web/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  385. package/out/web/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  386. package/out/web/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  387. package/out/web/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  388. package/out/web/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  389. package/out/web/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  390. package/out/web/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  391. package/out/web/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  392. package/out/web/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  393. package/out/web/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  394. package/out/web/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  395. package/out/web/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  396. package/out/web/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  397. package/out/web/pdfjs/cmaps/V.bcmap +0 -0
  398. package/out/web/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  399. package/out/web/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  400. package/out/web/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  401. package/out/web/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  402. package/out/web/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  403. package/out/web/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  404. package/out/web/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  405. package/out/web/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  406. package/out/web/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  407. package/out/web/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  408. package/out/web/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  409. package/out/web/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  410. package/out/web/pdfjs/standard_fonts/LICENSE_LIBERATION +363 -0
  411. package/out/web/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  412. package/out/web/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  413. package/out/web/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  414. package/out/web/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  415. package/out/web/pdfjs/wasm/LICENSE_JBIG2 +196 -0
  416. package/out/web/pdfjs/wasm/LICENSE_OPENJPEG +39 -0
  417. package/out/web/pdfjs/wasm/LICENSE_PDFJS_JBIG2 +13 -0
  418. package/out/web/pdfjs/wasm/LICENSE_PDFJS_OPENJPEG +22 -0
  419. package/out/web/pdfjs/wasm/LICENSE_PDFJS_QCMS +19 -0
  420. package/out/web/pdfjs/wasm/LICENSE_QCMS +21 -0
  421. package/out/web/pdfjs/wasm/jbig2.wasm +0 -0
  422. package/out/web/pdfjs/wasm/jbig2_nowasm_fallback.js +15 -0
  423. package/out/web/pdfjs/wasm/openjpeg.wasm +0 -0
  424. package/out/web/pdfjs/wasm/openjpeg_nowasm_fallback.js +17 -0
  425. package/out/web/pdfjs/wasm/qcms_bg.wasm +0 -0
  426. package/out/web/pdfjs/wasm/quickjs-eval.js +16 -0
  427. package/out/web/pdfjs/wasm/quickjs-eval.wasm +0 -0
  428. package/package.json +6 -4
  429. package/slash-commands.json +8 -2
  430. package/src/bin/index.js +4 -1
  431. package/src/bin/pdfjs-assets.mjs +31 -0
  432. package/src/renderer/node_modules/.vite/vitest/CACHEDIR.TAG +3 -0
  433. package/src/renderer/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  434. package/src/renderer/shared/agentProgress.ts +11 -2
  435. package/src/renderer/shared/components/Settings/AgentsTab.tsx +70 -6
  436. package/src/renderer/shared/components/Settings/AudioTab.tsx +1 -1
  437. package/src/renderer/shared/components/Settings/AutomationTab.tsx +57 -0
  438. package/src/renderer/shared/components/Settings/AvatarCropModal.tsx +18 -12
  439. package/src/renderer/shared/components/Settings/CustomProviderLogoPicker.test.tsx +65 -0
  440. package/src/renderer/shared/components/Settings/CustomProviderLogoPicker.tsx +456 -0
  441. package/src/renderer/shared/components/Settings/GeneralTab.tsx +40 -82
  442. package/src/renderer/shared/components/Settings/PluginsTab.tsx +101 -24
  443. package/src/renderer/shared/components/Settings/ProfileTab.tsx +1 -1
  444. package/src/renderer/shared/components/Settings/SettingsWindow.tsx +796 -0
  445. package/src/renderer/shared/components/Settings/ThemeTab.tsx +13 -1
  446. package/src/renderer/shared/components/{AgentActivityDrawer.tsx → activity/AgentActivityDrawer.tsx} +77 -61
  447. package/src/renderer/shared/components/{AgentActivityTable.tsx → activity/AgentActivityTable.tsx} +46 -7
  448. package/src/renderer/shared/components/{McpToolResults.tsx → activity/McpToolResults.tsx} +32 -13
  449. package/src/renderer/shared/components/{PlanChecklistWidget.tsx → activity/PlanChecklistWidget.tsx} +2 -2
  450. package/src/renderer/shared/components/activity/RunSummaryDashboard.test.tsx +127 -0
  451. package/src/renderer/shared/components/activity/RunSummaryDashboard.tsx +222 -0
  452. package/src/renderer/shared/components/activity/SubagentDagView.test.ts +123 -0
  453. package/src/renderer/shared/components/{SubagentDagView.tsx → activity/SubagentDagView.tsx} +97 -43
  454. package/src/renderer/shared/components/activity/SubagentStatusStrip.test.tsx +82 -0
  455. package/src/renderer/shared/components/activity/SubagentStatusStrip.tsx +107 -0
  456. package/src/renderer/shared/components/activity/ViewedImages.tsx +140 -0
  457. package/src/renderer/shared/components/{AuthGate.tsx → app/AuthGate.tsx} +3 -3
  458. package/src/renderer/shared/components/{ChunkErrorBoundary.tsx → app/ChunkErrorBoundary.tsx} +10 -10
  459. package/src/renderer/shared/components/{CommandPalette.tsx → app/CommandPalette.tsx} +25 -25
  460. package/src/renderer/shared/components/{DashboardSidebar.tsx → app/DashboardSidebar.tsx} +7 -5
  461. package/src/renderer/shared/components/{DesktopTitlebar.tsx → app/DesktopTitlebar.tsx} +7 -24
  462. package/src/renderer/shared/components/{ErrorNotice.tsx → app/ErrorNotice.tsx} +1 -1
  463. package/src/renderer/shared/components/{MintDashboard.tsx → app/MintDashboard.tsx} +191 -212
  464. package/src/renderer/shared/components/{ModalErrorBoundary.tsx → app/ModalErrorBoundary.tsx} +5 -5
  465. package/src/renderer/shared/components/{CalculationCard.tsx → cards/CalculationCard.tsx} +13 -27
  466. package/src/renderer/shared/components/{ImageGenCard.tsx → cards/ImageGenCard.tsx} +9 -22
  467. package/src/renderer/shared/components/{ImageSearchCard.tsx → cards/ImageSearchCard.tsx} +9 -22
  468. package/src/renderer/shared/components/{MermaidCard.tsx → cards/MermaidCard.tsx} +37 -21
  469. package/src/renderer/shared/components/{StockCard.tsx → cards/StockCard.tsx} +15 -31
  470. package/src/renderer/shared/components/cards/ToolResultCards.tsx +86 -0
  471. package/src/renderer/shared/components/{UiFeatureCard.tsx → cards/UiFeatureCard.tsx} +6 -6
  472. package/src/renderer/shared/components/{UiGridCard.tsx → cards/UiGridCard.tsx} +3 -3
  473. package/src/renderer/shared/components/{WeatherCard.tsx → cards/WeatherCard.tsx} +1 -1
  474. package/src/renderer/shared/components/{ApprovalCard.test.tsx → chat/ApprovalCard.test.tsx} +1 -1
  475. package/src/renderer/shared/components/{ApprovalCard.tsx → chat/ApprovalCard.tsx} +5 -5
  476. package/src/renderer/shared/components/{ChatCodeBlock.tsx → chat/ChatCodeBlock.tsx} +1 -1
  477. package/src/renderer/shared/components/{ChatMessageItem.test.tsx → chat/ChatMessageItem.test.tsx} +92 -15
  478. package/src/renderer/shared/components/{ChatMessageItem.tsx → chat/ChatMessageItem.tsx} +73 -157
  479. package/src/renderer/shared/components/chat/ChatPanel.test.tsx +31 -0
  480. package/src/renderer/shared/components/{ChatPanel.tsx → chat/ChatPanel.tsx} +244 -493
  481. package/src/renderer/shared/components/{CollapsiblePasteInput.tsx → chat/CollapsiblePasteInput.tsx} +2 -2
  482. package/src/renderer/shared/components/{DiffReviewModal.tsx → chat/DiffReviewModal.tsx} +40 -40
  483. package/src/renderer/shared/components/{GeminiLiveOverlay.tsx → chat/GeminiLiveOverlay.tsx} +2 -2
  484. package/src/renderer/shared/components/{ModelSelectorPopover.tsx → chat/ModelSelectorPopover.tsx} +3 -3
  485. package/src/renderer/shared/components/chat/QueuedMessagesBanner.test.tsx +89 -0
  486. package/src/renderer/shared/components/chat/QueuedMessagesBanner.tsx +201 -0
  487. package/src/renderer/shared/components/{RewindModal.tsx → chat/RewindModal.tsx} +4 -4
  488. package/src/renderer/shared/components/{SlashChoicePanel.tsx → chat/SlashChoicePanel.tsx} +2 -2
  489. package/src/renderer/shared/components/{SlashSuggestions.tsx → chat/SlashSuggestions.tsx} +4 -4
  490. package/src/renderer/shared/components/{SourcesBlock.tsx → chat/SourcesBlock.tsx} +30 -37
  491. package/src/renderer/shared/components/{ThinkingBlock.tsx → chat/ThinkingBlock.tsx} +1 -1
  492. package/src/renderer/shared/components/chat/TurnFileChanges.test.tsx +86 -0
  493. package/src/renderer/shared/components/chat/TurnFileChanges.tsx +430 -0
  494. package/src/renderer/shared/components/{VoicePill.css → chat/VoicePill.css} +1 -1
  495. package/src/renderer/shared/components/{VoicePill.jsx → chat/VoicePill.jsx} +3 -2
  496. package/src/renderer/shared/components/{CliSessionsView.test.tsx → extensions/CliSessionsView.test.tsx} +2 -2
  497. package/src/renderer/shared/components/{CliSessionsView.tsx → extensions/CliSessionsView.tsx} +14 -12
  498. package/src/renderer/shared/components/{LinkedFoldersView.tsx → extensions/LinkedFoldersView.tsx} +3 -3
  499. package/src/renderer/shared/components/{McpRegistryPicker.tsx → extensions/McpRegistryPicker.tsx} +3 -3
  500. package/src/renderer/shared/components/{McpServersView.tsx → extensions/McpServersView.tsx} +105 -36
  501. package/src/renderer/shared/components/{McpToolAllowlist.tsx → extensions/McpToolAllowlist.tsx} +2 -2
  502. package/src/renderer/shared/components/{ModUi.test.tsx → extensions/ModUi.test.tsx} +9 -4
  503. package/src/renderer/shared/components/{ModsPanel.tsx → extensions/ModsPanel.tsx} +59 -7
  504. package/src/renderer/shared/components/{PluginsView.tsx → extensions/PluginsView.tsx} +6 -6
  505. package/src/renderer/shared/components/{ScheduledTasksView.tsx → extensions/ScheduledTasksView.tsx} +5 -5
  506. package/src/renderer/shared/components/extensions/SkillsView.test.tsx +31 -0
  507. package/src/renderer/shared/components/{SkillsView.tsx → extensions/SkillsView.tsx} +20 -4
  508. package/src/renderer/shared/components/{ImageStudioPanel.tsx → studio/ImageStudioPanel.tsx} +6 -6
  509. package/src/renderer/shared/components/{LibraryItemCard.tsx → studio/LibraryItemCard.tsx} +2 -2
  510. package/src/renderer/shared/components/{LibraryPage.tsx → studio/LibraryPage.tsx} +5 -5
  511. package/src/renderer/shared/components/{LibraryPreview.tsx → studio/LibraryPreview.tsx} +2 -2
  512. package/src/renderer/shared/components/{VeoStudioPanel.tsx → studio/VeoStudioPanel.tsx} +7 -7
  513. package/src/renderer/shared/components/{GlideSelect.css → ui/GlideSelect.css} +7 -6
  514. package/src/renderer/shared/components/ui/ProviderBrandIcon.test.tsx +67 -0
  515. package/src/renderer/shared/components/ui/ProviderBrandIcon.tsx +167 -0
  516. package/src/renderer/shared/components/ui/SelectField.tsx +506 -0
  517. package/src/renderer/shared/components/ui/error-recovery.css +10 -10
  518. package/src/renderer/shared/components/ui/error-recovery.tsx +1 -1
  519. package/src/renderer/shared/components/{ArtifactPreviewPanel.tsx → workspace/ArtifactPreviewPanel.tsx} +256 -112
  520. package/src/renderer/shared/components/workspace/BackgroundTerminals.test.tsx +63 -0
  521. package/src/renderer/shared/components/{BackgroundTerminals.tsx → workspace/BackgroundTerminals.tsx} +40 -9
  522. package/src/renderer/shared/components/{CodeReviewPage.tsx → workspace/CodeReviewPage.tsx} +47 -8
  523. package/src/renderer/shared/components/{GitBranchSelector.tsx → workspace/GitBranchSelector.tsx} +2 -2
  524. package/src/renderer/shared/components/workspace/SessionSources.tsx +113 -0
  525. package/src/renderer/shared/components/{TerminalDock.tsx → workspace/TerminalDock.tsx} +5 -2
  526. package/src/renderer/shared/components/workspace/ToolSurfacePage.test.tsx +68 -0
  527. package/src/renderer/shared/components/{ToolSurfacePage.tsx → workspace/ToolSurfacePage.tsx} +322 -71
  528. package/src/renderer/shared/components/{ToolsPanelToggle.tsx → workspace/ToolsPanelToggle.tsx} +1 -1
  529. package/src/renderer/shared/components/workspace/WorkspaceFileInfo.tsx +28 -0
  530. package/src/renderer/shared/components/workspace/WorkspaceMediaPreview.tsx +17 -0
  531. package/src/renderer/shared/components/{WorkspacePaneResizer.tsx → workspace/WorkspacePaneResizer.tsx} +1 -1
  532. package/src/renderer/shared/components/workspace/WorkspacePdfPreview.tsx +89 -0
  533. package/src/renderer/shared/components/{WorkspacePreviewActions.test.tsx → workspace/WorkspacePreviewActions.test.tsx} +48 -3
  534. package/src/renderer/shared/components/{WorkspacePreviewActions.tsx → workspace/WorkspacePreviewActions.tsx} +3 -3
  535. package/src/renderer/shared/components/{WorkspaceSelector.tsx → workspace/WorkspaceSelector.tsx} +99 -7
  536. package/src/renderer/shared/components/{workspace-selector.css → workspace/workspace-selector.css} +84 -2
  537. package/src/renderer/shared/constants/config.ts +7 -0
  538. package/src/renderer/shared/conversation/coordinator.test.ts +46 -0
  539. package/src/renderer/shared/conversation/coordinator.ts +50 -2
  540. package/src/renderer/shared/conversation/lifecycle.test.ts +163 -1
  541. package/src/renderer/shared/conversation/lifecycle.ts +164 -7
  542. package/src/renderer/shared/conversation/projectNavigation.test.ts +18 -0
  543. package/src/renderer/shared/conversation/projectNavigation.ts +11 -0
  544. package/src/renderer/shared/conversation/transport.test.ts +20 -0
  545. package/src/renderer/shared/conversation/transport.ts +51 -9
  546. package/src/renderer/shared/conversation/useConversationCoordinator.ts +42 -12
  547. package/src/renderer/shared/css/agent-observability.css +72 -11
  548. package/src/renderer/shared/css/chat-ui-cards.css +35 -35
  549. package/src/renderer/shared/css/code-review.css +86 -86
  550. package/src/renderer/shared/css/code-sessions.css +10 -10
  551. package/src/renderer/shared/css/file-changes.css +167 -5
  552. package/src/renderer/shared/css/management-views.css +78 -37
  553. package/src/renderer/shared/css/mcp-results.css +46 -3
  554. package/src/renderer/shared/css/queued-messages.css +221 -0
  555. package/src/renderer/shared/css/session-sources.css +12 -7
  556. package/src/renderer/shared/css/settings/agents.css +2 -2
  557. package/src/renderer/{src-web → shared}/css/settings/base.css +101 -107
  558. package/src/renderer/shared/css/settings/general.css +384 -92
  559. package/src/renderer/shared/css/settings/plugins.css +8 -8
  560. package/src/renderer/shared/css/settings/theme.css +44 -32
  561. package/src/renderer/shared/css/ui-tailwind.css +2 -2
  562. package/src/renderer/shared/css/viewed-images.css +89 -0
  563. package/src/renderer/shared/css/workspace-file-info.css +12 -0
  564. package/src/renderer/shared/css/workspace-media-preview.css +13 -0
  565. package/src/renderer/shared/env.d.ts +9 -0
  566. package/src/renderer/shared/platform.test.ts +143 -0
  567. package/src/renderer/shared/platform.ts +10 -4
  568. package/src/renderer/shared/speech/player.ts +160 -0
  569. package/src/renderer/shared/speech/types.ts +11 -0
  570. package/src/renderer/shared/theme/themeManager.test.ts +20 -0
  571. package/src/renderer/shared/theme/themeManager.ts +3 -1
  572. package/src/renderer/shared/theme/themes.ts +17 -4
  573. package/src/renderer/shared/theme/tokens.css +448 -51
  574. package/src/renderer/shared/types.ts +56 -1
  575. package/src/renderer/shared/utils/agentActivity.test.ts +165 -6
  576. package/src/renderer/shared/utils/agentActivity.ts +181 -31
  577. package/src/renderer/shared/utils/artifactBrowser.ts +1 -1
  578. package/src/renderer/shared/utils/artifacts.ts +55 -0
  579. package/src/renderer/shared/utils/contextCompaction.test.tsx +1 -1
  580. package/src/renderer/shared/utils/externalLinks.ts +91 -0
  581. package/src/renderer/shared/utils/lazyWithRetry.ts +13 -0
  582. package/src/renderer/shared/utils/markdown.tsx +169 -35
  583. package/src/renderer/shared/utils/markdown.webImages.test.tsx +124 -2
  584. package/src/renderer/shared/utils/mcpResults.test.tsx +24 -1
  585. package/src/renderer/shared/utils/pdfRange.ts +16 -0
  586. package/src/renderer/shared/utils/previewObjectUrls.ts +20 -0
  587. package/src/renderer/shared/utils/sessionSources.test.ts +41 -1
  588. package/src/renderer/shared/utils/sessionSources.ts +2 -0
  589. package/src/renderer/shared/utils/slashCommandProcessor.ts +4 -1
  590. package/src/renderer/shared/utils/speech.ts +18 -4
  591. package/src/renderer/shared/utils/useNativeVoiceInput.ts +19 -5
  592. package/src/renderer/shared/utils/useSessionSources.ts +4 -0
  593. package/src/renderer/shared/utils/viewedImages.test.ts +129 -0
  594. package/src/renderer/shared/utils/viewedImages.ts +81 -10
  595. package/src/renderer/shared/utils/workspaceDrag.ts +30 -0
  596. package/src/renderer/shared/utils/workspaceImage.ts +17 -0
  597. package/src/renderer/shared/utils/workspaceListPreferences.test.ts +64 -0
  598. package/src/renderer/shared/utils/workspaceListPreferences.ts +54 -0
  599. package/src/renderer/shared/utils/workspaceMedia.ts +41 -0
  600. package/src/renderer/shared/utils/workspacePreview.test.ts +147 -2
  601. package/src/renderer/shared/utils/workspacePreview.ts +34 -3
  602. package/src/renderer/shared/utils/workspaces.ts +3 -2
  603. package/src/renderer/src/App.tsx +6 -8
  604. package/src/renderer/src/components/ChatPanel.tsx +1 -1
  605. package/src/renderer/src/components/DashboardSidebar.tsx +2 -2
  606. package/src/renderer/src/components/ImageStudioPanel.tsx +1 -1
  607. package/src/renderer/src/components/LiveTranslateControls.tsx +1 -1
  608. package/src/renderer/src/components/MintDashboard.tsx +1 -1
  609. package/src/renderer/src/components/ProactiveGlow.tsx +1 -1
  610. package/src/renderer/src/components/ScreenPicker.tsx +1 -1
  611. package/src/renderer/src/components/SettingsWindow.tsx +6 -830
  612. package/src/renderer/src/components/SpotlightWindow.tsx +4 -32
  613. package/src/renderer/src/components/VeoStudioPanel.tsx +1 -1
  614. package/src/renderer/src/components/WorkspacePanel.tsx +45 -12
  615. package/src/renderer/src/components/browser-shell.css +26 -26
  616. package/src/renderer/src/components/browser-suggestions-popup.css +8 -8
  617. package/src/renderer/src/css/app-shell.css +22 -102
  618. package/src/renderer/src/css/chat.css +221 -34
  619. package/src/renderer/src/css/desktop-tools.css +6 -337
  620. package/src/renderer/src/css/sidebar-workspace.css +20 -0
  621. package/src/renderer/src/css/spotlight.css +2 -2
  622. package/src/renderer/src/css/tool-surfaces.css +328 -58
  623. package/src/renderer/src/css/widget.css +6 -5
  624. package/src/renderer/src/env.d.ts +13 -0
  625. package/src/renderer/src/index.css +15 -63
  626. package/src/renderer/src/tauri.ts +77 -11
  627. package/src/renderer/src/voiceInput.ts +3 -1
  628. package/src/renderer/src-web/App.tsx +6 -8
  629. package/src/renderer/src-web/components/ChatPanel.tsx +1 -1
  630. package/src/renderer/src-web/components/DashboardSidebar.tsx +2 -2
  631. package/src/renderer/src-web/components/ImageStudioPanel.tsx +1 -1
  632. package/src/renderer/src-web/components/MintDashboard.tsx +1 -1
  633. package/src/renderer/src-web/components/SettingsWindow.tsx +6 -851
  634. package/src/renderer/src-web/components/VeoStudioPanel.tsx +1 -1
  635. package/src/renderer/src-web/css/app-shell.css +16 -100
  636. package/src/renderer/src-web/css/chat.css +221 -34
  637. package/src/renderer/src-web/css/sidebar-workspace.css +20 -0
  638. package/src/renderer/src-web/env.d.ts +14 -0
  639. package/src/renderer/src-web/index.css +15 -63
  640. package/src/renderer/src-web/tauri.ts +71 -13
  641. package/src/renderer/tests/browserArtifacts.browser.html +1 -0
  642. package/src/renderer/tests/browserArtifacts.browser.tsx +68 -0
  643. package/src/renderer/tests/chatEscape.browser.html +1 -0
  644. package/src/renderer/tests/chatEscape.browser.tsx +25 -0
  645. package/src/renderer/tests/chatPerformance.browser.html +1 -1
  646. package/src/renderer/tests/collapsedPaste.browser.html +1 -1
  647. package/src/renderer/tests/composerMenus.browser.html +3 -3
  648. package/src/renderer/tests/contextCompaction.browser.html +1 -1
  649. package/src/renderer/tests/errorRecovery.browser.html +1 -1
  650. package/src/renderer/tests/fixtures/preview.webm +0 -0
  651. package/src/renderer/tests/glideSelect.browser.html +1 -2
  652. package/src/renderer/tests/glideSelect.preview.html +1 -1
  653. package/src/renderer/tests/library.browser.tsx +1 -1
  654. package/src/renderer/tests/liveOrb.browser.html +1 -1
  655. package/src/renderer/tests/mediaFixtures.ts +32 -0
  656. package/src/renderer/tests/modInput.browser.html +1 -1
  657. package/src/renderer/tests/sessionSources.browser.tsx +76 -15
  658. package/src/renderer/tests/toolsPanel.browser.tsx +5 -5
  659. package/src/renderer/tests/viewedImages.browser.tsx +3 -3
  660. package/src/renderer/tests/voiceDictation.browser.html +101 -0
  661. package/src/renderer/tests/voicePill.browser.html +3 -3
  662. package/src/renderer/tests/voicePill.preview.html +1 -1
  663. package/src/renderer/tests/webSources.browser.tsx +2 -98
  664. package/src/renderer/tests/workspaceDrop.browser.html +1 -0
  665. package/src/renderer/tests/workspaceDrop.browser.tsx +183 -0
  666. package/src/renderer/tests/workspaceExpansion.browser.html +1 -0
  667. package/src/renderer/tests/workspaceExpansion.browser.tsx +66 -0
  668. package/src/renderer/tests/workspaceRemoval.browser.html +66 -0
  669. package/src/renderer/tests/workspaceUndo.browser.html +10 -2
  670. package/src-tauri/src/app/lifecycle.rs +44 -1
  671. package/src-tauri/src/commands/conversation.rs +99 -73
  672. package/src-tauri/src/commands/integrations.rs +7 -1
  673. package/src-tauri/src/commands/media.rs +7 -0
  674. package/src-tauri/src/commands/workspace.rs +38 -0
  675. package/tsconfig.json +15 -1
  676. package/vite.config.ts +2 -1
  677. package/vite.config.web.ts +2 -0
  678. package/out/web/assets/CliSessionsView-D7hw0Mgj.js +0 -1
  679. package/out/web/assets/CodeReviewPage-C7bEOJfd.js +0 -4
  680. package/out/web/assets/CodeReviewPage-Dte9uLiL.css +0 -1
  681. package/out/web/assets/CommandPalette-0RrF-AOT.js +0 -1
  682. package/out/web/assets/ImageStudioPanel-CdxkAf_r.js +0 -1
  683. package/out/web/assets/LibraryPage--Qfisp6D.js +0 -2
  684. package/out/web/assets/LinkedFoldersView-2nfZbDgN.js +0 -1
  685. package/out/web/assets/McpRegistryPicker-h9uS8_wT.js +0 -1
  686. package/out/web/assets/McpServersView-slfQJzNB.js +0 -1
  687. package/out/web/assets/MintDashboard-BSR5XpXh.js +0 -25
  688. package/out/web/assets/MintDashboard-CWUcCGhd.css +0 -1
  689. package/out/web/assets/PluginsView-l7LSm503.js +0 -1
  690. package/out/web/assets/ScheduledTasksView-CttmLbq1.js +0 -1
  691. package/out/web/assets/SettingsWindow-BCMLYvEV.js +0 -4
  692. package/out/web/assets/SettingsWindow-DcMVmU9u.css +0 -1
  693. package/out/web/assets/SkillsView-rNs1qr_U.js +0 -2
  694. package/out/web/assets/ToolSurfacePage-B9DzEPWN.js +0 -37
  695. package/out/web/assets/ToolSurfacePage-CTfgggF2.css +0 -1
  696. package/out/web/assets/VeoStudioPanel-DiJs_Cg2.js +0 -4
  697. package/out/web/assets/WorkspacePanel-CbJ1PFoZ.js +0 -1
  698. package/out/web/assets/WorkspaceSelector-B2xIp04D.js +0 -1
  699. package/out/web/assets/WorkspaceSelector-Ca8uJOsS.css +0 -1
  700. package/out/web/assets/abnfDiagram-VCTEODGH-CD0CjoGl.js +0 -1
  701. package/out/web/assets/architecture-7GRP2DOG-RKV83OeZ.js +0 -1
  702. package/out/web/assets/architectureDiagram-5GKGNRK7-nN_HAFct.js +0 -36
  703. package/out/web/assets/c4Diagram-UCG6FXSJ-DTdV8_zE.js +0 -38
  704. package/out/web/assets/chunk-2Q5K7J3B-Dmqrq8Tp.js +0 -1
  705. package/out/web/assets/chunk-75Z2AOVW-_M0z5olV.js +0 -2
  706. package/out/web/assets/chunk-CKBBP62Z-BpQEgeHF.js +0 -2
  707. package/out/web/assets/chunk-CLGD4ZFX-D54yGvGS.js +0 -1
  708. package/out/web/assets/chunk-CacB07dV.js +0 -1
  709. package/out/web/assets/chunk-DSNCTWBM-C-gvT2ru.js +0 -2
  710. package/out/web/assets/chunk-DU6HZSFF-CnFngIhW.js +0 -128
  711. package/out/web/assets/chunk-F27PBJKO-BqtWrnEO.js +0 -1
  712. package/out/web/assets/chunk-FOHPRMQF-BaVC1uA7.js +0 -161
  713. package/out/web/assets/chunk-G27WJ6UU-Ckoq5mi2.js +0 -231
  714. package/out/web/assets/chunk-JQ64N6SF-CF8T7GiZ.js +0 -1
  715. package/out/web/assets/chunk-JWPE2WC7-BwtYOHqU.js +0 -1
  716. package/out/web/assets/chunk-LNGE3PJU-AdBoOWw2.js +0 -34
  717. package/out/web/assets/chunk-OBVCFTLP-CRIkunUB.js +0 -1
  718. package/out/web/assets/chunk-P2QGCYS3-UFEU6BxZ.js +0 -1
  719. package/out/web/assets/chunk-POPQ4Y6H-CQcrNbjr.js +0 -1
  720. package/out/web/assets/chunk-PWAF6VOD-Cc2uVDsG.js +0 -1
  721. package/out/web/assets/chunk-R7TYR2AO-DiCxzdAY.js +0 -10
  722. package/out/web/assets/chunk-RHFEMEQ7-b7hnPmrR.js +0 -168
  723. package/out/web/assets/chunk-XXDRQBXY-DnJkbUaw.js +0 -1
  724. package/out/web/assets/chunk-Y2CYZVJY-C9o-s6OY.js +0 -1
  725. package/out/web/assets/classDiagram-DTDB5LWJ-RnC2mYO4.js +0 -1
  726. package/out/web/assets/classDiagram-v2-JRS7N3AN-RnC2mYO4.js +0 -1
  727. package/out/web/assets/config-CnvCChUM.js +0 -2
  728. package/out/web/assets/config-DM6oIVO3.css +0 -1
  729. package/out/web/assets/core-DsKkQ7ig.js +0 -1
  730. package/out/web/assets/cose-bilkent-JH36ORCC--UN4aw5-.js +0 -1
  731. package/out/web/assets/cynefin-OW5HDTMX-CnzQfOGp.js +0 -1
  732. package/out/web/assets/cynefinDiagram-5FMLGOSQ-DVtQnfpm.js +0 -62
  733. package/out/web/assets/cytoscape.esm-Df1UN4Y1.js +0 -321
  734. package/out/web/assets/dagre-3AP2YEHR-DG76_k5_.js +0 -4
  735. package/out/web/assets/dagre-BWadQu2F.js +0 -1
  736. package/out/web/assets/diagram-S7CK7UJ4-CaouUoze.js +0 -30
  737. package/out/web/assets/diagram-UQ7AKVKN-B4bEc26B.js +0 -41
  738. package/out/web/assets/diagram-VX7I27RA-7hH5IPYf.js +0 -24
  739. package/out/web/assets/diagram-Z3DM3KII-CCM4clo8.js +0 -24
  740. package/out/web/assets/dist-BoTOASLF.js +0 -1
  741. package/out/web/assets/dist-js-BkYNznHX.js +0 -1
  742. package/out/web/assets/ebnfDiagram-PWID7BFC-Da7WAM3k.js +0 -1
  743. package/out/web/assets/event-Cdt7Byyj.js +0 -1
  744. package/out/web/assets/eventmodeling-NTZA5JFV-xcfsA0XD.js +0 -1
  745. package/out/web/assets/flowDiagram-A5DVABFB-JdtH1673.js +0 -1
  746. package/out/web/assets/ganttDiagram-EL5Y4UJY-B3ClFGmL.js +0 -292
  747. package/out/web/assets/gitGraph-4MIJSDKK-BZ_y_cDU.js +0 -1
  748. package/out/web/assets/gitGraphDiagram-WWUBYQGX-drhRSYm3.js +0 -106
  749. package/out/web/assets/graphlib-CTR5ZhLf.js +0 -1
  750. package/out/web/assets/index-BZ9xgmMP.css +0 -1
  751. package/out/web/assets/index-Ca8cCS4h.js +0 -168
  752. package/out/web/assets/info-A6RAGUB7-B7I3K0F1.js +0 -1
  753. package/out/web/assets/infoDiagram-RXCK75RN-deX_1MPh.js +0 -2
  754. package/out/web/assets/journeyDiagram-EYS64GPL-CZn2kB8b.js +0 -139
  755. package/out/web/assets/jsx-runtime-DN4NhQUK.js +0 -1
  756. package/out/web/assets/katex-O3jvqgnU.js +0 -257
  757. package/out/web/assets/markdown-CMhYIcWB.js +0 -39
  758. package/out/web/assets/mermaid-parser.core-Whu2rlJC.js +0 -7
  759. package/out/web/assets/mermaid.core-CKyPo8VH.js +0 -11
  760. package/out/web/assets/modelManager-CUaGWMWu.js +0 -2
  761. package/out/web/assets/oauthManager-DlNhXJr6.js +0 -1
  762. package/out/web/assets/packet-AYTQ26CC-CEeIRKRG.js +0 -1
  763. package/out/web/assets/pegDiagram-XKGWAZYB-BYadI-KO.js +0 -1
  764. package/out/web/assets/pie-WAS4IAKB-D8uf4dh5.js +0 -1
  765. package/out/web/assets/pieDiagram-E7YTZNPT-CjSDy4hO.js +0 -39
  766. package/out/web/assets/radar-RG4KPBEZ-DZJxnokY.js +0 -1
  767. package/out/web/assets/railroad-74A4TZTK-DBysUiUi.js +0 -1
  768. package/out/web/assets/railroad-abnf-HS5TGJTU-CHWxoJYg.js +0 -1
  769. package/out/web/assets/railroad-ebnf-LZEXJU2U-DDv7X6bY.js +0 -1
  770. package/out/web/assets/railroad-peg-WCYAUIDC-DpfcYYNJ.js +0 -1
  771. package/out/web/assets/railroadDiagram-O6MQD6OU-CYtyv0t3.js +0 -1
  772. package/out/web/assets/rough.esm-DFbTUy8a.js +0 -1
  773. package/out/web/assets/sankeyDiagram-P5KCCOFB-Bn2x6C4Y.js +0 -40
  774. package/out/web/assets/sequenceDiagram-WJ2MYXX4-BvFLKtPd.js +0 -162
  775. package/out/web/assets/sizeCapture-X5ZJPWSS-DKeOCaN2.js +0 -1
  776. package/out/web/assets/src-DnfeXQPr.js +0 -1
  777. package/out/web/assets/stateDiagram-HBIQ2CUA-Bx0GWeaY.js +0 -1
  778. package/out/web/assets/stateDiagram-v2-4QOOHH4V--hol1yg_.js +0 -1
  779. package/out/web/assets/studio-B1mk40wD.js +0 -1
  780. package/out/web/assets/swimlanes-XN3QIQJK-CCma0T7L.js +0 -1
  781. package/out/web/assets/swimlanesDiagram-VK2B7HYN-BkohoVsU.js +0 -8
  782. package/out/web/assets/timeline-definition-24CTP7MA-iCRhhJ7C.js +0 -120
  783. package/out/web/assets/treeView-Q6P3EWNA-DZ-y08qp.js +0 -1
  784. package/out/web/assets/treemap-WGGIJYW6-De0CxzMx.js +0 -1
  785. package/out/web/assets/vennDiagram-4TSXK5OY-w_7aZ6xe.js +0 -34
  786. package/out/web/assets/wardley-WFR3VGLG-DT0y0xJ4.js +0 -1
  787. package/out/web/assets/window-BJCVtyET.js +0 -1
  788. package/src/renderer/shared/components/ChatPanel.test.tsx +0 -21
  789. package/src/renderer/shared/components/FormattedMessage.tsx +0 -11
  790. package/src/renderer/shared/components/GlideSelect.d.ts +0 -31
  791. package/src/renderer/shared/components/GlideSelect.jsx +0 -266
  792. package/src/renderer/shared/components/InlineThoughtNote.tsx +0 -27
  793. package/src/renderer/shared/components/ModSessionControls.tsx +0 -8
  794. package/src/renderer/shared/components/ModUi.tsx +0 -26
  795. package/src/renderer/shared/components/ProgressActivity.tsx +0 -17
  796. package/src/renderer/shared/components/ReviewHistory.tsx +0 -42
  797. package/src/renderer/shared/components/RunSummaryDashboard.tsx +0 -143
  798. package/src/renderer/shared/components/SelectField.tsx +0 -38
  799. package/src/renderer/shared/components/SessionSources.tsx +0 -48
  800. package/src/renderer/shared/components/SessionSourcesPopover.tsx +0 -61
  801. package/src/renderer/shared/components/ToolSurfacePage.test.tsx +0 -32
  802. package/src/renderer/shared/components/ViewedImages.tsx +0 -36
  803. package/src/renderer/shared/components/WorkspaceContextPopover.tsx +0 -138
  804. package/src/renderer/shared/components/ui/demo.tsx +0 -26
  805. package/src/renderer/shared/css/session-sources-popover.css +0 -9
  806. package/src/renderer/src/components/CalculationCard.tsx +0 -3
  807. package/src/renderer/src/components/ImageGenCard.tsx +0 -2
  808. package/src/renderer/src/components/ImageSearchCard.tsx +0 -2
  809. package/src/renderer/src/components/MermaidCard.tsx +0 -1
  810. package/src/renderer/src/components/PicturesLibrary.tsx +0 -2
  811. package/src/renderer/src/components/Settings/AgentsTab.tsx +0 -4
  812. package/src/renderer/src/components/Settings/AudioTab.tsx +0 -3
  813. package/src/renderer/src/components/Settings/AutomationTab.tsx +0 -3
  814. package/src/renderer/src/components/Settings/GeneralTab.tsx +0 -3
  815. package/src/renderer/src/components/Settings/MemoryTab.tsx +0 -3
  816. package/src/renderer/src/components/Settings/PluginsTab.tsx +0 -3
  817. package/src/renderer/src/components/Settings/ProfileTab.tsx +0 -3
  818. package/src/renderer/src/components/Settings/ShortcutsTab.tsx +0 -3
  819. package/src/renderer/src/components/Settings/ThemeTab.tsx +0 -3
  820. package/src/renderer/src/components/StockCard.tsx +0 -3
  821. package/src/renderer/src/components/WeatherCard.tsx +0 -3
  822. package/src/renderer/src/css/pictures.css +0 -2
  823. package/src/renderer/src/css/settings/base.css +0 -1266
  824. package/src/renderer/src-web/components/PicturesLibrary.tsx +0 -2
  825. package/src/renderer/src-web/components/Settings/AgentsTab.tsx +0 -4
  826. package/src/renderer/src-web/components/Settings/AudioTab.tsx +0 -3
  827. package/src/renderer/src-web/components/Settings/AutomationTab.tsx +0 -3
  828. package/src/renderer/src-web/components/Settings/GeneralTab.tsx +0 -3
  829. package/src/renderer/src-web/components/Settings/MemoryTab.tsx +0 -3
  830. package/src/renderer/src-web/components/Settings/PluginsTab.tsx +0 -3
  831. package/src/renderer/src-web/components/Settings/ProfileTab.tsx +0 -3
  832. package/src/renderer/src-web/components/Settings/ShortcutsTab.tsx +0 -3
  833. package/src/renderer/src-web/components/Settings/ThemeTab.tsx +0 -3
  834. package/src/renderer/src-web/css/pictures.css +0 -2
  835. package/src/renderer/src-web/css/spotlight.css +0 -102
  836. package/src/renderer/src-web/css/widget.css +0 -213
  837. /package/src/renderer/shared/components/{UiMockupWidget.tsx → cards/UiMockupWidget.tsx} +0 -0
  838. /package/src/renderer/shared/components/{ContextCompactionStatus.tsx → chat/ContextCompactionStatus.tsx} +0 -0
  839. /package/src/renderer/shared/components/{GeminiLiveOverlay.css → chat/GeminiLiveOverlay.css} +0 -0
  840. /package/src/renderer/shared/components/{GeminiLiveOverlay.test.tsx → chat/GeminiLiveOverlay.test.tsx} +0 -0
  841. /package/src/renderer/shared/components/{SlashSuggestions.test.tsx → chat/SlashSuggestions.test.tsx} +0 -0
  842. /package/src/renderer/shared/components/{VirtualChatHistory.tsx → chat/VirtualChatHistory.tsx} +0 -0
  843. /package/src/renderer/shared/components/{VoicePill.d.ts → chat/VoicePill.d.ts} +0 -0
  844. /package/src/renderer/shared/components/{VoicePill.test.tsx → chat/VoicePill.test.tsx} +0 -0
  845. /package/src/renderer/shared/components/{ScreenCaptureDialog.css → studio/ScreenCaptureDialog.css} +0 -0
  846. /package/src/renderer/shared/components/{ScreenCaptureDialog.tsx → studio/ScreenCaptureDialog.tsx} +0 -0
  847. /package/src/renderer/shared/components/{SelectField.test.tsx → ui/SelectField.test.tsx} +0 -0
  848. /package/src/renderer/shared/components/{background-terminals.css → workspace/background-terminals.css} +0 -0
@@ -0,0 +1,101 @@
1
+ <!doctype html><html><head><meta charset="utf-8"><title>Mint dictation regression checks</title></head>
2
+ <body><div id="root"></div><pre id="result">RUNNING</pre><script type="module">
3
+ import React from 'react'; import {createRoot} from 'react-dom/client';
4
+ import {useSpeechToText} from '../shared/utils/speech';
5
+ import {useNativeVoiceInput} from '../shared/utils/useNativeVoiceInput';
6
+ const wait=()=>new Promise(resolve=>setTimeout(resolve,30));
7
+ const assert=(ok,message)=>{if(!ok)throw Error(message)};
8
+ let root,voice,changeDraft,changeChat,recognition,transcript,finishTranscript;let endDelay=0;
9
+ const writes=[],sends=[],checks=[];
10
+ class Recognition {
11
+ constructor(){recognition=this;this.results=[]}
12
+ start(){setTimeout(()=>this.onstart?.(),0)}
13
+ stop(){setTimeout(()=>this.onend?.(),endDelay)}
14
+ abort(){}
15
+ result(text,final=true,index=this.results.length){
16
+ const result=[{transcript:text}];result.isFinal=final;this.results[index]=result;
17
+ this.onresult?.({resultIndex:index,results:this.results});
18
+ }
19
+ }
20
+ window.SpeechRecognition=Recognition;
21
+ function Web(){
22
+ const [message,setMessage]=React.useState('Existing');changeDraft=setMessage;const [chatId,setChatId]=React.useState('chat-a');changeChat=setChatId;
23
+ voice=useSpeechToText({chatId,message,sending:false,isSpeaking:false,onSetMessage:text=>{writes.push(text);setMessage(text)},onSendVoiceMessage:async text=>sends.push(text)});
24
+ return null;
25
+ }
26
+ function Native(){
27
+ const [message,setMessage]=React.useState('Existing');changeDraft=setMessage;const [chatId,setChatId]=React.useState('chat-a');changeChat=setChatId;
28
+ voice=useNativeVoiceInput({chatId,message,onSetMessage:text=>{writes.push(text);setMessage(text)},onSendVoiceMessage:async text=>sends.push(text),
29
+ startRecording:async()=>{},cancelRecording:async()=>{},stopRecordingAndTranscribe:()=>transcript});
30
+ return null;
31
+ }
32
+ async function mount(Component){
33
+ if(root){root.unmount();await wait()}
34
+ writes.length=0;sends.length=0;root=createRoot(document.getElementById('root'));
35
+ root.render(React.createElement(Component));await wait();
36
+ }
37
+ async function check(name,run){try{await run();checks.push('PASS '+name)}catch(error){checks.push('FAIL '+name+': '+error.message)}}
38
+ window.runVoiceDictationChecks=async()=>{
39
+ await check('web retains every final phrase and never sends',async()=>{
40
+ await mount(Web);await voice.startRecognition();await wait();
41
+ recognition.result('First sentence. ');recognition.result('Second sentence.');
42
+ assert(writes.length===0&&sends.length===0,'must wait for stop');
43
+ voice.stopRecognition();await wait();
44
+ assert(writes.join('|')==='Existing First sentence. Second sentence.',JSON.stringify({writes,sends}));
45
+ assert(sends.length===0,'dictation sent a chat message');
46
+ });
47
+ await check('web replaces interim results without duplicating final results',async()=>{
48
+ await mount(Web);await voice.startRecognition();await wait();
49
+ recognition.result('hello ',true);recognition.result('worl',false);
50
+ recognition.result('world',true,1);recognition.result('world',true,1);
51
+ changeDraft('Edited draft');await wait();voice.stopRecognition();await wait();
52
+ assert(writes.join('|')==='Edited draft hello world',JSON.stringify(writes));
53
+ assert(sends.length===0,'dictation sent a chat message');
54
+ });
55
+ await check('web cancel discards all recognized phrases',async()=>{
56
+ await mount(Web);await voice.startRecognition();await wait();recognition.result('discard');
57
+ voice.cancelRecognition();await wait();assert(writes.length===0&&sends.length===0,'canceled text was applied');
58
+ });
59
+ await check('desktop stop appends to latest draft and never sends',async()=>{
60
+ await mount(Native);transcript=new Promise(resolve=>{finishTranscript=resolve});
61
+ await voice.startRecognition();await wait();const stop=voice.stopRecognition();
62
+ changeDraft('Edited while transcribing');await wait();finishTranscript(' Native words ');await stop;await wait();
63
+ assert(writes.join('|')==='Edited while transcribing Native words',JSON.stringify({writes,sends}));
64
+ assert(sends.length===0,'desktop sent a chat message');
65
+ });
66
+ await check('desktop cancellation during transcription leaves draft alone',async()=>{
67
+ await mount(Native);transcript=new Promise(resolve=>{finishTranscript=resolve});
68
+ await voice.startRecognition();await wait();const stop=voice.stopRecognition();
69
+ const cancel=voice.cancelRecognition();finishTranscript('discard');await stop;await cancel;await wait();
70
+ assert(writes.length===0&&sends.length===0,'canceled text was applied');
71
+ });
72
+ await check('desktop empty transcript leaves draft alone',async()=>{
73
+ await mount(Native);transcript=Promise.resolve(' ');await voice.startRecognition();await wait();
74
+ await voice.stopRecognition();await wait();assert(writes.length===0&&sends.length===0,'empty text changed the draft');
75
+ });
76
+ await check('desktop discards delayed transcript after switching chats',async()=>{
77
+ await mount(Native);transcript=new Promise(resolve=>{finishTranscript=resolve});await voice.startRecognition();await wait();
78
+ const stopping=voice.stopRecognition();changeChat('chat-b');changeDraft('Other chat draft');await wait();
79
+ finishTranscript('private words from chat A');await stopping;await wait();
80
+ assert(writes.length===0&&sends.length===0,'old transcript was inserted into the new chat');
81
+ });
82
+ await check('web discards pending recognition after switching chats',async()=>{
83
+ await mount(Web);await voice.startRecognition();await wait();recognition.result('private words from chat A');
84
+ endDelay=80;voice.stopRecognition();changeChat('chat-b');changeDraft('Other chat draft');await wait();await new Promise(resolve=>setTimeout(resolve,100));endDelay=0;
85
+ assert(writes.length===0&&sends.length===0,'old recognition was inserted into the new chat');
86
+ });
87
+ await check('unsupported browser shows popup and leaves draft alone',async()=>{
88
+ await mount(Web);const original=window.SpeechRecognition,webkit=window.webkitSpeechRecognition,alert=window.alert;const popups=[];
89
+ try{
90
+ window.SpeechRecognition=undefined;window.webkitSpeechRecognition=undefined;window.alert=text=>popups.push(text);
91
+ const started=await voice.startRecognition();await wait();
92
+ assert(started===false&&!voice.isRecording&&!voice.voiceMode,'unsupported browser entered recording mode');
93
+ assert(popups.length===1&&popups[0].includes('Chrome or Edge'),'unsupported popup missing');
94
+ assert(writes.length===0&&sends.length===0,'unsupported microphone changed the draft');
95
+ }finally{window.SpeechRecognition=original;window.webkitSpeechRecognition=webkit;window.alert=alert}
96
+ });
97
+ root.unmount();root=null;
98
+ document.getElementById('result').textContent=checks.join('\n');
99
+ return checks;
100
+ }
101
+ </script></body></html>
@@ -2,7 +2,7 @@
2
2
  <body style="background:#18181b;color:#f5f5f5;font-family:system-ui;margin:32px"><h1>Mint VoicePill</h1><div id="root" style="padding:24px 140px"></div><pre id="result">RUNNING</pre>
3
3
  <script type="module">
4
4
  import React from 'react';import {createRoot} from 'react-dom/client';
5
- import VoicePill from '../shared/components/VoicePill';
5
+ import VoicePill from '../shared/components/chat/VoicePill';
6
6
  import {useNativeVoiceInput} from '../shared/utils/useNativeVoiceInput';
7
7
  import {useSpeechToText} from '../shared/utils/speech';
8
8
  const wait=(ms=60)=>new Promise(done=>setTimeout(done,ms));const lines=[];
@@ -44,7 +44,7 @@ try {
44
44
  const calls=[];let ready;
45
45
  function NativeFixture(){
46
46
  const voice=useNativeVoiceInput({startRecording:()=>new Promise(resolve=>{calls.push('start');ready=resolve}),
47
- cancelRecording:async()=>{calls.push('discard')},stopRecordingAndTranscribe:async()=>{calls.push('transcribe');return 'Native words'},onSendVoiceMessage:async text=>calls.push('send:'+text)});
47
+ cancelRecording:async()=>{calls.push('discard')},stopRecordingAndTranscribe:async()=>{calls.push('transcribe');return 'Native words'},message:'Existing',onSetMessage:text=>calls.push('draft:'+text),onSendVoiceMessage:async text=>calls.push('send:'+text)});
48
48
  return React.createElement(VoicePill,{active:voice.isRecording,onStart:voice.startRecognition,
49
49
  onStop:e=>['tap','release','key'].includes(e.reason)?voice.stopRecognition():voice.cancelRecognition()});
50
50
  }
@@ -54,7 +54,7 @@ try {
54
54
  assert(calls.join(',')==='start,discard'&&button().getAttribute('aria-pressed')==='false','native pending-start cancellation discards without transcription');
55
55
  pointer('pointerdown');await wait();ready();await wait();pointer('pointerup');await wait();
56
56
  assert(button().getAttribute('aria-pressed')==='true','native success opens listening capsule');
57
- await tap();await wait();assert(calls.at(-2)==='transcribe'&&calls.at(-1)==='send:Native words','normal native stop sends one transcript');
57
+ await tap();await wait();assert(calls.at(-2)==='transcribe'&&calls.at(-1)==='draft:Existing Native words'&&!calls.some(call=>call.startsWith('send:')),'normal native stop appends transcript to composer without sending');
58
58
  root.render(React.createElement('div'));await wait();
59
59
  const instances=[],messages=[],sends=[];let denied=false;
60
60
  class Recognition {
@@ -1,7 +1,7 @@
1
1
  <!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Mint VoicePill composer preview</title></head>
2
2
  <body><div id="root"></div><pre id="result">PREVIEW</pre><script type="module">
3
3
  import React from 'react';import {createRoot} from 'react-dom/client';
4
- import VoicePill from '../shared/components/VoicePill';
4
+ import VoicePill from '../shared/components/chat/VoicePill';
5
5
  import '../shared/theme/tokens.css';import '../src-web/css/chat.css';
6
6
  if(location.search.includes('mobile')) await import('../src-web/css/mobile.css');
7
7
  const frames=new Map();let id=0;
@@ -1,98 +1,2 @@
1
- import React, { useState } from 'react'
2
- import { createRoot } from 'react-dom/client'
3
- import ChatPanel from '../shared/components/ChatPanel'
4
- import { chatPanelFixture } from './chatPanelFixture'
5
- import { installRendererPlatform, installWorkspacePlatform } from '../shared/platform'
6
- import * as webAdapter from '../src-web/tauri'
7
- import type { AgentProgress, ConversationSources } from '../shared/types'
8
- import '../shared/theme/tokens.css'
9
- import '../src-web/css/app-shell.css'
10
- import '../src-web/css/chat.css'
11
- import '../src-web/css/mobile.css'
12
-
13
- const image = 'data:image/svg+xml;base64,' + btoa('<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40"><rect width="40" height="40" fill="#73d6b0"/></svg>')
14
- const search = (url: string): AgentProgress => ({ type: 'ToolEnd', data: { action: 'web_search', input: {}, result: `1. Source reference\nURL: ${url}\nReference` } })
15
- const data: ConversationSources = { attachments: [
16
- { id: 1, interactionId: 2, libraryItemId: 'reference', name: 'reference.png', kind: 'image', mimeType: 'image/png', thumbnailDataUri: image },
17
- { id: 2, interactionId: 2, libraryItemId: 'notes', name: 'notes.pdf', kind: 'file', mimeType: 'application/pdf', thumbnailDataUri: null },
18
- ], webSearchProgress: [search('https://example.com/reference')] }
19
- const requests: string[] = []
20
- let fail = false, deferA = false
21
- let resolveA: ((data: ConversationSources) => void) | undefined
22
- installRendererPlatform({ ...webAdapter,
23
- getConversationSources: async chatId => { requests.push(chatId); if (fail) throw new Error('Offline'); if (chatId === 'A' && deferA) return new Promise(resolve => { resolveA = resolve }); return chatId === 'A' ? data : { attachments: [], webSearchProgress: [] } },
24
- modsOperation: async () => ({ mods: [] }), fetchProviderModels: async () => [],
25
- })
26
- installWorkspacePlatform({ getGitBranchInfo: async () => ({ isRepository: false, currentBranch: null, branches: [], remoteBranches: [], detachedHead: null, isDirty: false }) } as any)
27
- const originalFetch = window.fetch.bind(window)
28
- window.fetch = (input, options) => String(input).includes('localhost:11434') ? Promise.resolve(new Response('{"models":[]}')) : originalFetch(input, options)
29
- let selectChat = (_id: string) => {}, addLiveSearch = () => {}, setRunning = (_running: boolean) => {}
30
- let cancellations = 0
31
- function Fixture() {
32
- const props = chatPanelFixture()
33
- const [chatId, setChatId] = useState('A')
34
- const [draft, setDraft] = useState('Keep my draft')
35
- const [live, setLive] = useState<AgentProgress[]>([])
36
- const [running, changeRunning] = useState(false)
37
- setRunning = changeRunning
38
- selectChat = id => { setChatId(id); setLive([]) }
39
- addLiveSearch = () => setLive([search('https://example.com/live')])
40
- return <>
41
- <style>{`html,body,#root{margin:0;height:100%;width:100%;background:var(--bg-overlay);color:var(--text-main);font-family:Arial,sans-serif}*{box-sizing:border-box}#root{display:flex;flex-direction:column}.fixture-controls{padding:6px;flex:0 0 auto}.assistant-workspace{flex:1;min-height:0;min-width:0;display:flex}#qa-results{position:fixed;bottom:0;left:0;max-width:100vw;font-size:9px;white-space:pre-wrap;overflow-wrap:anywhere;pointer-events:none;z-index:900}`}</style>
42
- <div className="fixture-controls">Real Web ChatPanel · Sources fixture</div>
43
- <main className="assistant-workspace chat-only"><ChatPanel {...props as any} conversation={{ ...props.conversation, chatId, message: draft, sending: running, agentProgress: live, workspacePath: '/workspace/a-very-long-project-name' }} actions={{ ...props.actions, onSetMessage: setDraft, onCancelMessage: () => { cancellations++ } }} showSessionSources /></main>
44
- <pre id="qa-results">Running…</pre>
45
- </>
46
- }
47
- createRoot(document.getElementById('root')!).render(<Fixture />)
48
- const delay = (ms = 50) => new Promise(resolve => setTimeout(resolve, ms))
49
- async function waitFor(check: () => boolean, name: string) { for (let i = 0; i < 100; i++) { if (check()) return; await delay() } throw new Error(name) }
50
- const results: string[] = []
51
- const check = (value: unknown, name: string) => { if (!value) throw new Error(name); results.push(`PASS ${name}`) }
52
- const click = (selector: string) => { const element = document.querySelector<HTMLElement>(selector); if (!element) throw new Error(`Missing ${selector}`); element.focus(); element.click() }
53
- async function run() {
54
- await waitFor(() => Boolean(document.querySelector('.session-sources-toggle')), 'Sources entry appears')
55
- check(requests.length === 0, 'closed Sources does not fetch')
56
- const actions = document.querySelector('.chat-header-actions')!
57
- check(actions.firstElementChild?.classList.contains('session-sources-toggle'), 'Sources sits beside Tools in the real chat header')
58
- check(actions.getBoundingClientRect().right <= innerWidth, 'header actions fit the viewport')
59
- click('.session-sources-toggle')
60
- await waitFor(() => document.querySelectorAll('.session-source-row').length === 3, 'Session sources load')
61
- check(requests[0] === 'A', 'Web fetches the current conversation')
62
- check(document.querySelector('.session-sources-heading')?.textContent?.includes('This session'), 'panel identifies its session scope')
63
- const bounds = document.querySelector('.session-sources-popover')!.getBoundingClientRect()
64
- check(bounds.left >= 0 && bounds.right <= innerWidth && bounds.bottom <= innerHeight, 'Sources panel fits the viewport')
65
- check(Boolean(document.querySelector('.session-source-icon.is-web img, .session-source-icon.is-web svg')), 'website sources retain their favicon or fallback')
66
- addLiveSearch(); await waitFor(() => document.querySelectorAll('.session-source-row').length === 4, 'Live source updates')
67
- check(true, 'live search sources appear without reopening')
68
- if (location.search.includes('preview')) { document.getElementById('qa-results')!.textContent = ''; return }
69
- setRunning(true); await delay()
70
- window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
71
- await waitFor(() => !document.querySelector('.session-sources-popover'), 'Escape closes Sources')
72
- check(document.activeElement === document.querySelector('.session-sources-toggle'), 'Escape restores focus to Sources')
73
- check(cancellations === 0, 'closing Sources with Escape does not cancel the running agent')
74
- window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
75
- check(cancellations === 1, 'Escape still cancels the agent when Sources is closed')
76
- setRunning(false); await delay()
77
- const closedCount = requests.length; await delay(2200)
78
- check(requests.length === closedCount, 'closing Sources stops its polling')
79
- deferA = true; click('.session-sources-toggle'); await waitFor(() => Boolean(resolveA), 'Deferred A request')
80
- selectChat('B'); await waitFor(() => Boolean(document.querySelector('.session-sources-empty')), 'Session B is empty')
81
- resolveA!(data); await delay()
82
- check(document.querySelectorAll('.session-source-row').length === 0, 'late A response cannot leak into B')
83
- fail = true; deferA = false; selectChat('A'); await waitFor(() => Boolean(document.querySelector('.session-sources-error')), 'Source error')
84
- fail = false; click('.session-sources-error button'); await waitFor(() => document.querySelectorAll('.session-source-row').length === 3, 'Retry loads saved sources')
85
- check(true, 'Sources retries a failed request')
86
- let navigated = false
87
- const onNavigate = () => { navigated = true }; window.addEventListener('popstate', onNavigate)
88
- click('.session-source-row[href^="/library"]'); await waitFor(() => !document.querySelector('.session-sources-popover'), 'Library navigation closes Sources')
89
- check(navigated && location.pathname === '/library', 'source link opens Library through SPA navigation')
90
- check(document.querySelector<HTMLTextAreaElement>('#chat-input')?.value === 'Keep my draft', 'opening a source preserves the composer draft')
91
- window.removeEventListener('popstate', onNavigate)
92
- click('.session-sources-toggle'); await waitFor(() => Boolean(document.querySelector('.session-sources-popover')), 'Sources reopens')
93
- document.body.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }))
94
- await waitFor(() => !document.querySelector('.session-sources-popover'), 'Outside click closes')
95
- check(true, 'outside click closes Sources')
96
- document.getElementById('qa-results')!.textContent = results.join('\n') + '\nALL PASSED'
97
- }
98
- run().catch(error => { document.getElementById('qa-results')!.textContent = results.join('\n') + `\nFAIL ${error.message}` })
1
+ // Desktop and Web share the same Sources-in-Tools integration checks.
2
+ import './sessionSources.browser'
@@ -0,0 +1 @@
1
+ <!doctype html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"></head><body><div id="root"></div><pre id="result">RUNNING</pre><script type="module" src="./workspaceDrop.browser.tsx"></script></body></html>
@@ -0,0 +1,183 @@
1
+ import React, { useRef, useState } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import WorkspacePanel from '../src/components/WorkspacePanel'
4
+ import ToolSurfacePage, { type ToolSurface } from '../shared/components/workspace/ToolSurfacePage'
5
+ import { installRendererPlatform, installWorkspacePlatform, runtimePlatform, workspacePlatform } from '../shared/platform'
6
+ import { createWorkspacePreviewOpener } from '../shared/utils/workspacePreview'
7
+ import { WORKSPACE_FILE_MIME, workspacePreviewId } from '../shared/utils/workspaceDrag'
8
+ import { samplePdf, sampleWav } from './mediaFixtures'
9
+ import videoUrl from './fixtures/preview.webm?url'
10
+ import { PreviewObjectUrls } from '../shared/utils/previewObjectUrls'
11
+ import '../shared/theme/tokens.css'
12
+ import '../src/css/sidebar-workspace.css'
13
+
14
+ const roots = ['/tmp/mint-drop-a', '/tmp/mint-drop-b']
15
+ const names = ['photo.png', 'notes.md', 'main.py', 'archive.zip', 'broken.txt', 'index.html', 'guide.pdf', 'tone.wav', 'clip.webm', 'broken.wav', 'broken.webm']
16
+ const calls: string[] = []
17
+ const revoked: string[] = []
18
+ const originalRevoke = URL.revokeObjectURL.bind(URL)
19
+ URL.revokeObjectURL = url => { revoked.push(url); originalRevoke(url) }
20
+ let failRead = true
21
+ let externalTarget = ''
22
+ ;(window as any).__TAURI_INTERNALS__ = { invoke: async (command: string, args: any) => {
23
+ if (command !== 'run_desktop_action') throw Error(`Unexpected native call: ${command}`)
24
+ externalTarget = args.action.target
25
+ return { success: true }
26
+ } }
27
+ const image = 'data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="400" height="260"><rect width="400" height="260" fill="#0e6551"/><text x="80" y="140" fill="white" font-size="36">Workspace image</text></svg>')
28
+ installRendererPlatform({
29
+ isTauriRuntime: () => false,
30
+ readWorkspaceMedia: async (path: string, root: string) => {
31
+ calls.push(`media:${root}:${path}`)
32
+ if (path.startsWith('broken.') && path !== 'broken.txt') { const blob = new Blob(['invalid media'], { type: path.endsWith('.wav') ? 'audio/wav' : 'video/webm' }); return { url: URL.createObjectURL(blob), mimeType: blob.type, objectUrl: true } }
33
+ if (path === 'clip.webm') return { url: videoUrl, mimeType: 'video/webm' }
34
+ const blob = new Blob([path === 'guide.pdf' ? samplePdf() : sampleWav()], { type: path === 'guide.pdf' ? 'application/pdf' : 'audio/wav' })
35
+ return { url: URL.createObjectURL(blob), mimeType: blob.type, objectUrl: true, byteLength: blob.size }
36
+ },
37
+ readWorkspaceImage: async (path: string, root: string) => { calls.push(`image:${root}:${path}`); return image },
38
+ readWorkspaceFile: async (path: string, root: string) => { calls.push(`read:${root}:${path}`); if (path === 'broken.txt' && failRead) throw Error('File unavailable'); return path.endsWith('.md') ? '# Preview heading\n\nMarkdown content' : 'print("Hello from Workspace")' },
39
+ } as any)
40
+ installWorkspacePlatform({
41
+ listWorkspaceHistory: async () => [],
42
+ getWorkspaceSnapshot: async ({ root }: { root: string }) => ({ path: root, revision: 1, git: { isRepository: false, branches: [], remoteBranches: [], isDirty: false }, tree: { name: root.split('/').at(-1), path: '.', kind: 'directory', children: [
43
+ ...names.map(name => ({ name, path: name, kind: 'file', children: [] })),
44
+ { name: 'folder', path: 'folder', kind: 'directory', children: [] },
45
+ ] } }),
46
+ startHtmlPreview: async (root: string, path: string) => { calls.push(`serve:${root}:${path}`); await new Promise(r => setTimeout(r, 30)); return { url: path === 'index.html' ? 'data:text/html,<h1>HTML preview</h1>' : image, jobId: 'preview' } },
47
+ } as any)
48
+ const noop = () => {}
49
+ function Fixture() {
50
+ const [root, setRoot] = useState(roots[0])
51
+ const [surfaces, setSurfaces] = useState<ToolSurface[]>([])
52
+ const [active, setActive] = useState<string | null>(null)
53
+ const current = useRef(surfaces); current.current = surfaces
54
+ const owner = useRef(new PreviewObjectUrls())
55
+ React.useEffect(() => { owner.current.update(surfaces.flatMap(tab => tab.kind === 'preview' ? [tab.artifact] : [])) }, [surfaces])
56
+ const opener = useRef<ReturnType<typeof createWorkspacePreviewOpener> | null>(null)
57
+ opener.current ??= createWorkspacePreviewOpener({
58
+ readWorkspaceFile: (path, root) => runtimePlatform.readWorkspaceFile(path, root),
59
+ readWorkspaceImage: (path, root) => runtimePlatform.readWorkspaceImage(path, root),
60
+ readWorkspaceMedia: (path, root) => runtimePlatform.readWorkspaceMedia(path, root),
61
+ startHtmlPreview: (root, path) => workspacePlatform.startHtmlPreview(root, path),
62
+ selectIfOpen: id => { if (!current.current.some(tab => tab.id === id)) return false; setActive(id); return true },
63
+ open: artifact => { owner.current.accept(artifact); const id = workspacePreviewId(artifact.workspacePath!, artifact.path); setSurfaces(tabs => [...tabs, { id, kind: 'preview', title: artifact.path, artifact }]); setActive(id) },
64
+ })
65
+ return <>
66
+ <style>{`*{box-sizing:border-box}html,body,#root{margin:0;height:100%;overflow:hidden;background:var(--bg-overlay);color:var(--text-main);font-family:Arial,sans-serif}.fixture-header{height:40px;padding:6px}.app-body{position:relative;height:calc(100% - 40px);display:flex}.fixture-workspace{width:320px;overflow:auto}.assistant-workspace{flex:1;min-width:0;padding:20px}#result{position:fixed;bottom:0;left:0;max-width:40%;font-size:9px;white-space:pre-wrap;pointer-events:none;z-index:900}`}</style>
67
+ <header className="fixture-header"><button id="switch-root" onClick={() => setRoot(value => value === roots[0] ? roots[1] : roots[0])}>Switch workspace</button></header>
68
+ <div className="app-body tool-surface-active" style={{ '--tool-surface-width': '480px' } as React.CSSProperties}>
69
+ <div className="fixture-workspace"><WorkspacePanel workspacePath={root} agentMode sending={false} onEnableAgentMode={noop} onSetMessage={noop} onWorkspaceReady={noop} /></div>
70
+ <main className="assistant-workspace"><h1>Conversation</h1><textarea defaultValue="Keep my draft" /></main>
71
+ <ToolSurfacePage surfaces={surfaces} activeSurfaceId={active} workspacePath={root} terminalSize={480} desktopTools onDropWorkspaceFile={file => opener.current!(file.root, file.path)}
72
+ onSelect={setActive} onClose={id => { setSurfaces(tabs => tabs.filter(tab => tab.id !== id)); setActive(null) }} onCloseAll={noop} onDuplicate={noop} onRename={noop} onCloseOthers={noop} onResizeTerminal={noop} onResizePanel={noop}
73
+ onOpenSources={noop} onOpenTerminal={noop} onOpenBrowser={noop} onOpenReview={noop} onOpenFiles={noop} onOpenMods={noop} onOpenBackgroundTasks={noop} onModsPanelTarget={noop} onBackgroundPanelTarget={noop} onClosePanel={noop} />
74
+ </div>
75
+ </>
76
+ }
77
+ createRoot(document.getElementById('root')!).render(<Fixture />)
78
+ const delay = (ms = 40) => new Promise(resolve => setTimeout(resolve, ms))
79
+ async function until(check: () => unknown) { for (let i = 0; i < 100; i++) { if (check()) return; await delay() } throw Error('Timed out') }
80
+ const results: string[] = []
81
+ function check(value: unknown, name: string) { if (!value) throw Error(name); results.push(name) }
82
+ const tools = () => document.querySelector<HTMLElement>('.tool-surface-page')!
83
+ async function begin(path: string) {
84
+ const row = document.querySelector<HTMLElement>(`.workspace-tree-row[title="${path}"]`)!
85
+ const dataTransfer = new DataTransfer()
86
+ row.dispatchEvent(new DragEvent('dragstart', { bubbles: true, cancelable: true, dataTransfer }))
87
+ await delay()
88
+ return dataTransfer
89
+ }
90
+ async function drop(path: string) {
91
+ const dataTransfer = await begin(path)
92
+ tools().dispatchEvent(new DragEvent('dragenter', { bubbles: true, cancelable: true, dataTransfer }))
93
+ tools().dispatchEvent(new DragEvent('dragover', { bubbles: true, cancelable: true, dataTransfer }))
94
+ await delay()
95
+ tools().dispatchEvent(new DragEvent('drop', { bubbles: true, cancelable: true, dataTransfer }))
96
+ await delay()
97
+ }
98
+ async function run() {
99
+ await until(() => document.querySelector('.workspace-tree-row[title="photo.png"]'))
100
+ const drag = await begin('photo.png')
101
+ check(JSON.parse(drag.getData(WORKSPACE_FILE_MIME)).root === roots[0], 'real Workspace drag includes its source root')
102
+ check(drag.getData('text/plain') === '@photo.png', 'dragging into chat keeps the existing file mention payload')
103
+ check(document.querySelector('.tool-surface-drag-shield'), 'internal file drags protect the drop target above iframe previews')
104
+ tools().dispatchEvent(new DragEvent('dragenter', { bubbles: true, dataTransfer: drag }))
105
+ await delay()
106
+ check(document.querySelector('.tool-surface-drop-overlay')?.textContent?.includes('Drop to preview'), 'dragging over Tools shows the Mint drop overlay')
107
+ tools().dispatchEvent(new DragEvent('drop', { bubbles: true, cancelable: true, dataTransfer: drag }))
108
+ await until(() => document.querySelector<HTMLImageElement>('.artifact-preview-panel img')?.naturalWidth)
109
+ check(!document.querySelector('.tool-surface-drop-overlay'), 'dropping clears the drag overlay')
110
+ check(calls.filter(call => call.startsWith('serve:')).length === 0 && calls.filter(call => call.startsWith('image:')).length === 1, 'image reads directly without starting any background preview service')
111
+ check(!document.querySelector('[aria-label="Open in Mint Browser (Mint Auto)"]'), 'direct images do not offer an HTTP-only browser action')
112
+ await drop('notes.md'); await until(() => document.querySelector('.artifact-preview-panel')?.textContent?.includes('Preview heading') && !document.querySelector('.artifact-preview-panel')?.textContent?.includes('# Preview heading'))
113
+ check(true, 'Markdown opens rendered content')
114
+ await drop('main.py'); await until(() => document.querySelector('.artifact-preview-panel')?.textContent?.includes('Hello from Workspace'))
115
+ check(true, 'code opens readable content')
116
+ let before = calls.length
117
+ await drop('photo.png'); await until(() => document.querySelector<HTMLImageElement>('.artifact-preview-panel img')?.naturalWidth)
118
+ check(calls.length === before && document.querySelectorAll('[role="tab"]').length === 3, 'dropping an open file selects its existing tab without reloading')
119
+ document.querySelector<HTMLButtonElement>('[title="Reload content from file"]')!.click()
120
+ await until(() => calls.length === before + 1)
121
+ await until(() => document.querySelector<HTMLImageElement>('.artifact-preview-panel img')?.naturalWidth)
122
+ check(calls.at(-1) === `image:${roots[0]}:photo.png` && !calls.some(call => call.startsWith('serve:')), 'Reload rereads the image directly without a service')
123
+ before = calls.length
124
+ await drop('archive.zip'); await until(() => document.querySelector('.workspace-file-info'))
125
+ check(document.querySelector('.workspace-file-info')?.textContent?.includes('ZIP') && calls.length === before, 'unsupported files show details without decoding binary content')
126
+ document.querySelector<HTMLButtonElement>('.workspace-file-info button')!.click()
127
+ await until(() => externalTarget)
128
+ check(externalTarget === 'file:///tmp/mint-drop-a/archive.zip', 'external-app button opens the original local file through the native boundary')
129
+ await drop('broken.txt'); await until(() => document.querySelector('.tool-surface-drop-error'))
130
+ check(document.querySelectorAll('[role="tab"]').length === 4, 'a failed preview leaves existing tabs intact')
131
+ failRead = false; await drop('broken.txt'); await until(() => document.querySelectorAll('[role="tab"]').length === 5)
132
+ check(!document.querySelector('.tool-surface-drop-error'), 'failed drops can be retried')
133
+ await drop('index.html'); await until(() => document.querySelector('.artifact-preview-panel iframe'))
134
+ const nextDrag = await begin('photo.png')
135
+ check(document.querySelector('.tool-surface-drag-shield'), 'a drop shield remains available when the active preview is an iframe')
136
+ tools().dispatchEvent(new DragEvent('dragenter', { bubbles: true, dataTransfer: nextDrag }))
137
+ await delay(); window.dispatchEvent(new DragEvent('dragend'))
138
+ await delay()
139
+ check(!document.querySelector('.tool-surface-drag-shield') && !document.querySelector('.tool-surface-drop-overlay'), 'cancelling a drag clears all drag feedback')
140
+ const folder = await begin('folder')
141
+ check(!folder.types.includes(WORKSPACE_FILE_MIME) && !document.querySelector('.tool-surface-drag-shield'), 'folders are not treated as previewable files')
142
+ window.dispatchEvent(new DragEvent('dragend'))
143
+ document.querySelector<HTMLButtonElement>('#switch-root')!.click()
144
+ await until(() => document.querySelector('.workspace-root-row')?.textContent?.includes('mint-drop-b'))
145
+ await drop('photo.png'); await until(() => document.querySelectorAll('[role="tab"]').length === 7)
146
+ check(calls.includes('image:/tmp/mint-drop-b:photo.png'), 'same filename from another Workspace opens its own pinned preview')
147
+ check(document.querySelector<HTMLTextAreaElement>('textarea')?.value === 'Keep my draft', 'preview drops preserve the chat draft')
148
+ const serverCalls = calls.filter(call => call.startsWith('serve:')).length
149
+ await drop('guide.pdf')
150
+ await until(() => document.querySelector<HTMLCanvasElement>('.workspace-pdf-preview canvas')?.width && document.querySelector('.workspace-pdf-controls')?.textContent?.includes('1 / 2') && !document.querySelector('.workspace-pdf-pages [role="status"]'))
151
+ check(!document.querySelector('.workspace-pdf-pages [role="alert"]'), 'PDF renders inside Tools with the bundled viewer')
152
+ document.querySelector<HTMLButtonElement>('[aria-label="Next PDF page"]')!.click()
153
+ await until(() => document.querySelector('.workspace-pdf-controls')?.textContent?.includes('2 / 2') && !document.querySelector('.workspace-pdf-pages [role="status"]'))
154
+ check(true, 'PDF next-page navigation renders the second page')
155
+ document.querySelector<HTMLButtonElement>('[aria-label="Zoom PDF in"]')!.click()
156
+ await until(() => document.querySelector('.workspace-pdf-controls')?.textContent?.includes('125%'))
157
+ check(true, 'PDF zoom controls work')
158
+ await drop('tone.wav')
159
+ await until(() => document.querySelector<HTMLAudioElement>('audio')?.readyState! >= 1)
160
+ const audio = document.querySelector<HTMLAudioElement>('audio')!
161
+ check(audio.controls && !audio.autoplay && audio.duration > 0, 'audio decodes with controls and does not autoplay')
162
+ const audioBlob = audio.querySelector('source')!.src
163
+ audio.currentTime = .25
164
+ await until(() => audio.currentTime >= .2)
165
+ check(true, 'audio can seek within the file')
166
+ await drop('clip.webm')
167
+ await until(() => document.querySelector<HTMLVideoElement>('video')?.readyState! >= 1)
168
+ const video = document.querySelector<HTMLVideoElement>('video')!
169
+ check(video.controls && !video.autoplay && video.videoWidth > 0, 'video decodes with native controls and does not autoplay')
170
+ check(audio.paused && !audio.querySelector('source')?.getAttribute('src'), 'switching tabs stops and releases the old media element')
171
+ check(calls.filter(call => call.startsWith('serve:')).length === serverCalls, 'PDF, audio and video do not start preview services')
172
+ document.querySelector<HTMLButtonElement>('[aria-label="Close tone.wav"]')!.click()
173
+ await until(() => revoked.includes(audioBlob))
174
+ check(true, 'closing the last media tab releases its Blob URL')
175
+ for (const name of ['broken.wav', 'broken.webm']) {
176
+ await drop(name)
177
+ await until(() => document.querySelector('.workspace-media-error') && document.querySelector('.workspace-file-info button'))
178
+ check(true, `${name} falls back to file details and an external-app button`)
179
+ }
180
+ if (location.search.includes('preview')) { document.getElementById('result')!.textContent = ''; return }
181
+ document.getElementById('result')!.textContent = JSON.stringify({ status: 'PASS', checks: results })
182
+ }
183
+ run().catch(error => { document.getElementById('result')!.textContent = JSON.stringify({ status: 'FAIL', error: String(error), checks: results }) })
@@ -0,0 +1 @@
1
+ <!doctype html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"></head><body><div id="root"></div><pre id="result">RUNNING</pre><script type="module" src="./workspaceExpansion.browser.tsx"></script></body></html>
@@ -0,0 +1,66 @@
1
+ import React, { useState } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import WorkspacePanel from '../src/components/WorkspacePanel'
4
+ import { installWorkspacePlatform } from '../shared/platform'
5
+ import type { WorkspaceSnapshot } from '../shared/types'
6
+
7
+ const roots = ['/tmp/mint-expansion-a', '/tmp/mint-expansion-b']
8
+ for (const root of roots) localStorage.removeItem(`mint:workspace-expanded-folders:${encodeURIComponent(root)}`)
9
+ const snapshot = (root: string): WorkspaceSnapshot => ({ path: root, revision: 1,
10
+ tree: { name: root.split('/').at(-1)!, path: '.', kind: 'directory', children: [
11
+ { name: 'docs', path: 'docs', kind: 'directory', children: [
12
+ { name: 'nested', path: 'docs/nested', kind: 'directory', children: [
13
+ { name: 'note.txt', path: 'docs/nested/note.txt', kind: 'file', children: [] },
14
+ ] },
15
+ ] },
16
+ ] },
17
+ git: { isRepository: false, currentBranch: null, isDirty: false, branches: [], remoteBranches: [], detachedHead: null },
18
+ })
19
+ installWorkspacePlatform({
20
+ getWorkspaceSnapshot: async operation => snapshot(operation.root),
21
+ listWorkspaceHistory: async () => [],
22
+ } as any)
23
+ const noop = () => {}
24
+ function Fixture() {
25
+ const [root, setRoot] = useState(roots[0])
26
+ const [mounted, setMounted] = useState(true)
27
+ return <>
28
+ <button id="switch" onClick={() => setRoot(value => value === roots[0] ? roots[1] : roots[0])}>Switch workspace</button>
29
+ <button id="mount" onClick={() => setMounted(value => !value)}>Toggle view</button>
30
+ {mounted && <WorkspacePanel workspacePath={root} agentMode sending={false} onEnableAgentMode={noop} onSetMessage={noop} onWorkspaceReady={noop} />}
31
+ </>
32
+ }
33
+ createRoot(document.getElementById('root')!).render(<Fixture />)
34
+ const delay = () => new Promise(resolve => setTimeout(resolve, 30))
35
+ async function until(check: () => boolean) { for (let i = 0; i < 100; i++) { if (check()) return; await delay() } throw Error('Timed out') }
36
+ const row = (path: string) => document.querySelector<HTMLButtonElement>(`.workspace-tree-row[title="${path}"]`)
37
+ async function click(selector: string) { document.querySelector<HTMLButtonElement>(selector)!.click(); await delay() }
38
+ const checks: string[] = []
39
+ function check(value: unknown, name: string) { if (!value) throw Error(name); checks.push(name) }
40
+ try {
41
+ await until(() => Boolean(row('docs')))
42
+ check(row('docs')?.getAttribute('aria-expanded') === 'false' && !row('docs/nested'), 'first visit starts with every child folder collapsed')
43
+ await click('[title="docs"]')
44
+ check(row('docs/nested')?.getAttribute('aria-expanded') === 'false' && !row('docs/nested/note.txt'), 'opening a parent keeps unvisited descendants collapsed')
45
+ await click('[title="docs/nested"]')
46
+ check(row('docs/nested/note.txt'), 'nested folder can be expanded')
47
+ await click('[title="docs"]'); await click('[title="docs"]')
48
+ check(row('docs/nested/note.txt'), 'collapsing a parent preserves its nested expansion state')
49
+ await click('#switch')
50
+ await until(() => document.querySelector('.workspace-root-row')?.textContent?.includes('mint-expansion-b') === true)
51
+ check(!row('docs/nested'), 'another workspace with the same relative paths starts collapsed')
52
+ await click('[title="docs"]')
53
+ await click('#switch')
54
+ await until(() => document.querySelector('.workspace-root-row')?.textContent?.includes('mint-expansion-a') === true)
55
+ check(row('docs/nested/note.txt'), 'returning to a workspace restores its own expanded folders')
56
+ await click('#mount'); await click('#mount')
57
+ await until(() => Boolean(row('docs')))
58
+ check(row('docs/nested/note.txt'), 'reopening Workspace restores saved expansion')
59
+ await click('[title="docs/nested"]')
60
+ await click('#mount'); await click('#mount')
61
+ await until(() => Boolean(row('docs/nested')))
62
+ check(!row('docs/nested/note.txt'), 'reopening also restores an explicitly collapsed folder')
63
+ await click('[aria-label="Refresh workspace"]')
64
+ check(!row('docs/nested/note.txt'), 'snapshot refresh preserves expansion choices')
65
+ document.getElementById('result')!.textContent = JSON.stringify({ status: 'PASS', checks })
66
+ } catch (error) { document.getElementById('result')!.textContent = JSON.stringify({ status: 'FAIL', error: String(error), checks }) }
@@ -0,0 +1,66 @@
1
+ <!doctype html><html lang="th"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Workspace list removal checks</title>
2
+ <style>*{box-sizing:border-box}body{margin:16px;background:#101012;color:#eee;font-family:system-ui}#chat{display:flex;align-items:flex-end;height:430px}#code{margin-top:24px}pre{white-space:pre-wrap;overflow-wrap:anywhere}</style></head>
3
+ <body><div id="chat"></div><div id="code"></div><pre id="result">RUNNING</pre><script type="module">
4
+ import React from 'react';import {createRoot} from 'react-dom/client';
5
+ import '/shared/theme/tokens.css';
6
+ import WorkspaceSelector from '/shared/components/WorkspaceSelector.tsx';
7
+ import CliSessionsView from '/shared/components/CliSessionsView.tsx';
8
+ import {workspaceListPreferences} from '/shared/utils/workspaceListPreferences';
9
+ const current='/projects/Current workspace', other='/projects/Long workspace name with Thai ภาษาไทย/other';
10
+ const wait=ms=>new Promise(resolve=>setTimeout(resolve,ms));const checks=[];
11
+ const assert=(condition,message)=>{if(!condition)throw Error(message);checks.push(message)};
12
+ async function until(predicate){for(let i=0;i<100;i++){if(predicate())return;await wait(20)}throw Error('Timed out waiting for UI')}
13
+ const chat=document.getElementById('chat'),code=document.getElementById('code');
14
+ const rootChat=createRoot(chat),rootCode=createRoot(code);let selectionCalls=0,deletedSessions=0,folderCalls=0;
15
+ const session={id:'cli::kept',kind:'cli',workspacePath:current,title:'Existing session',createdAt:'2026-10-17T00:00:00Z',messageCount:1};
16
+ const render=()=>{
17
+ rootChat.render(React.createElement(WorkspaceSelector,{currentPath:current,recentPaths:[other,current],onSelectWorkspace:()=>selectionCalls++}));
18
+ rootCode.render(React.createElement(CliSessionsView,{chatSessions:[session],workspacePath:current,recentWorkspacePaths:[other,current],activeConversationId:'conversation',
19
+ onSelectSession:()=>selectionCalls++,onDeleteSession:()=>deletedSessions++,onRenameSession:()=>{},onSelectFolder:async()=>{folderCalls++;return current}}));
20
+ };
21
+ const options=host=>[...host.querySelectorAll('.workspace-select-option')].map(button=>button.title);
22
+ const open=async host=>{host.querySelector('.workspace-select-btn').click();await until(()=>host.querySelector('.workspace-select-menu'))};
23
+ const remove=async(host,path)=>{
24
+ const row=[...host.querySelectorAll('.workspace-select-row')].find(row=>row.querySelector('.workspace-select-option').title===path);
25
+ const more=row.querySelector('.workspace-select-more');more.click();await until(()=>document.querySelector('[role="menuitem"]'));
26
+ assert(document.activeElement===document.querySelector('[role="menuitem"]'),'action menu receives keyboard focus');
27
+ document.querySelector('[role="menuitem"]').click();await until(()=>!options(host).includes(path));
28
+ };
29
+ window.runWorkspaceRemovalChecks=async()=>{
30
+ try{
31
+ workspaceListPreferences.restore(current);workspaceListPreferences.restore(other);render();await until(()=>code.querySelector('.code-session-row'));
32
+ await open(chat);await open(code);
33
+ assert(options(chat).join('|')===options(code).join('|'),'both pickers start with the same paths');
34
+ const firstMore=chat.querySelector('.workspace-select-more');const rowHeight=firstMore.closest('.workspace-select-row').getBoundingClientRect().height;firstMore.click();await until(()=>document.querySelector('[role="menuitem"]'));
35
+ const actions=document.querySelector('.workspace-select-row-menu');
36
+ assert(!chat.contains(actions)&&firstMore.closest('.workspace-select-row').getBoundingClientRect().height===rowHeight,'actions open as a floating dropdown without moving workspace rows');
37
+ assert(actions.textContent.includes('Remove from list')&&!/[\u0E00-\u0E7F]/.test(actions.textContent),'workspace dropdown uses English only');
38
+ actions.querySelector('button').dispatchEvent(new MouseEvent('mousedown',{bubbles:true}));await wait(0);
39
+ assert(!!chat.querySelector('.workspace-select-menu')&&!!document.querySelector('[role="menuitem"]'),'pointer down inside floating dropdown does not dismiss it before click');
40
+ document.querySelector('[role="menuitem"]').dispatchEvent(new KeyboardEvent('keydown',{key:'Escape',bubbles:true}));
41
+ await until(()=>!document.querySelector('[role="menuitem"]'));
42
+ assert(document.activeElement===firstMore&&!!chat.querySelector('.workspace-select-menu'),'Escape closes row actions and restores focus without closing picker');
43
+ if(!code.querySelector('.workspace-select-menu'))await open(code);
44
+ await remove(chat,current);
45
+ await until(()=>!options(code).includes(current));
46
+ assert(selectionCalls===0&&deletedSessions===0,'removal never selects a project or deletes a session');
47
+ assert(chat.querySelector('.workspace-select-btn').title===current&&code.querySelector('.workspace-select-btn').title===current,'removing active workspace keeps both active selections');
48
+ assert(code.querySelectorAll('.code-session-row').length===1,'active project sessions remain visible');
49
+ assert(document.activeElement===chat.querySelector('input'),'removal returns focus to search');
50
+ render();await wait(50);
51
+ assert(!options(chat).includes(current)&&!options(code).includes(current),'session references and rerenders do not reintroduce a removed path');
52
+ code.querySelector('.workspace-select-open-folder').click();await until(()=>folderCalls===1);await wait(50);
53
+ assert(options(chat).includes(current),'Open folder restores a removed workspace in the other picker');
54
+ await open(code);await remove(code,other);await until(()=>!options(chat).includes(other));
55
+ assert(selectionCalls===0&&deletedSessions===0,'removal from Code sessions also leaves project and session data intact');
56
+ assert(document.documentElement.scrollWidth<=innerWidth,'workspace controls fit the viewport');
57
+ workspaceListPreferences.restore(other);
58
+ const more=chat.querySelector('.workspace-select-more');more.click();await until(()=>document.querySelector('[role="menuitem"]'));
59
+ const bounds=chat.querySelector('.workspace-select-menu').getBoundingClientRect();
60
+ assert(bounds.left>=0&&bounds.right<=innerWidth,'workspace menu stays inside the viewport');
61
+ const dropdown=document.querySelector('.workspace-select-row-menu').getBoundingClientRect();
62
+ assert(dropdown.left>=0&&dropdown.right<=document.documentElement.clientWidth&&dropdown.top>=0&&dropdown.bottom<=innerHeight,'action dropdown stays inside the viewport');
63
+ document.getElementById('result').textContent='PASS\n'+checks.join('\n');
64
+ }catch(error){document.getElementById('result').textContent='FAIL\n'+error.stack+'\n'+checks.join('\n')}
65
+ };
66
+ </script></body></html>