@pheem49/mint 1.14.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (585) hide show
  1. package/CLAUDE.md +1 -1
  2. package/Cargo.lock +291 -11
  3. package/Cargo.toml +1 -1
  4. package/README.md +71 -9
  5. package/ROADMAP.md +30 -0
  6. package/Release_Note.md +579 -465
  7. package/crates/mint-cli/Cargo.toml +3 -1
  8. package/crates/mint-cli/src/agent/approval_prompts.rs +16 -3
  9. package/crates/mint-cli/src/agent/live_status.rs +367 -118
  10. package/crates/mint-cli/src/agent/markdown_render.rs +601 -61
  11. package/crates/mint-cli/src/agent.rs +452 -215
  12. package/crates/mint-cli/src/commands/agent.rs +16 -21
  13. package/crates/mint-cli/src/commands/eval.rs +9 -5
  14. package/crates/mint-cli/src/commands/git.rs +204 -0
  15. package/crates/mint-cli/src/commands/integrations.rs +28 -0
  16. package/crates/mint-cli/src/commands/knowledge.rs +1 -0
  17. package/crates/mint-cli/src/commands/mod.rs +37 -2
  18. package/crates/mint-cli/src/commands/tailnet_web.rs +235 -0
  19. package/crates/mint-cli/src/image.rs +26 -3
  20. package/crates/mint-cli/src/interactive/chat_tui.rs +4742 -0
  21. package/crates/mint-cli/src/interactive/command_ui.rs +477 -0
  22. package/crates/mint-cli/src/interactive/format.rs +8 -0
  23. package/crates/mint-cli/src/interactive/input_box.rs +38 -2
  24. package/crates/mint-cli/src/interactive/picker.rs +180 -37
  25. package/crates/mint-cli/src/interactive/resume_picker.rs +686 -0
  26. package/crates/mint-cli/src/interactive/slash_commands.rs +868 -450
  27. package/crates/mint-cli/src/interactive/thought_viewer.rs +286 -0
  28. package/crates/mint-cli/src/interactive.rs +400 -136
  29. package/crates/mint-cli/src/main.rs +84 -23
  30. package/crates/mint-cli/src/markdown.rs +12 -5
  31. package/crates/mint-cli/src/onboard.rs +32 -30
  32. package/crates/mint-cli/src/plugins_cli.rs +8 -5
  33. package/crates/mint-cli/src/setup.rs +10 -8
  34. package/crates/mint-cli/src/terminal_theme.rs +187 -0
  35. package/crates/mint-cli/src/updater.rs +56 -21
  36. package/crates/mint-core/src/agent/agent_loop.rs +1 -0
  37. package/crates/mint-core/src/agent/chat.rs +843 -177
  38. package/crates/mint-core/src/agent/code_tools.rs +83 -2
  39. package/crates/mint-core/src/agent/memory.rs +658 -20
  40. package/crates/mint-core/src/agent/skills.rs +1 -1
  41. package/crates/mint-core/src/api_server/routes/chat.rs +31 -5
  42. package/crates/mint-core/src/api_server/routes/linked_folders.rs +118 -3
  43. package/crates/mint-core/src/api_server/routes/misc.rs +10 -14
  44. package/crates/mint-core/src/api_server/routes/sessions.rs +44 -0
  45. package/crates/mint-core/src/api_server.rs +22 -3
  46. package/crates/mint-core/src/avatar_bridge.rs +2 -0
  47. package/crates/mint-core/src/browser/cdp.rs +74 -83
  48. package/crates/mint-core/src/browser/evidence.rs +260 -0
  49. package/crates/mint-core/src/browser/input.rs +1 -1
  50. package/crates/mint-core/src/browser/interact.rs +98 -124
  51. package/crates/mint-core/src/browser/lifecycle.rs +75 -4
  52. package/crates/mint-core/src/browser/mod.rs +16 -2
  53. package/crates/mint-core/src/browser/navigate.rs +27 -19
  54. package/crates/mint-core/src/browser/observe.js +40 -0
  55. package/crates/mint-core/src/browser/session.rs +1558 -0
  56. package/crates/mint-core/src/git/branches.rs +348 -0
  57. package/crates/mint-core/src/git/checkpoint.rs +40 -0
  58. package/crates/mint-core/src/git/diff.rs +206 -0
  59. package/crates/mint-core/src/git/mod.rs +10 -2
  60. package/crates/mint-core/src/integrations/channels.rs +1 -0
  61. package/crates/mint-core/src/lib.rs +22 -14
  62. package/crates/mint-core/src/live_sync.rs +28 -9
  63. package/crates/mint-core/src/media/auto_shorts.rs +1 -0
  64. package/crates/mint-core/src/media/gemini_live.rs +12 -1
  65. package/crates/mint-core/src/media/mic_transcribe.rs +1 -0
  66. package/crates/mint-core/src/media/subtitle.rs +1 -0
  67. package/crates/mint-core/src/orchestration/context_render.rs +1 -0
  68. package/crates/mint-core/src/orchestration/memory_skill.rs +6 -1
  69. package/crates/mint-core/src/orchestration/mod.rs +1024 -271
  70. package/crates/mint-core/src/orchestration/tools/browser.rs +16 -139
  71. package/crates/mint-core/src/orchestration/tools/misc.rs +2 -1
  72. package/crates/mint-core/src/orchestration/tools/web.rs +1 -1
  73. package/crates/mint-core/src/prompts/agent.rs +58 -29
  74. package/crates/mint-core/src/prompts/chat.rs +1 -1
  75. package/crates/mint-core/src/prompts/persona.rs +1 -1
  76. package/crates/mint-core/src/prompts/tool_catalog.rs +93 -25
  77. package/crates/mint-core/src/search/linked_folders/index.rs +732 -0
  78. package/crates/mint-core/src/search/linked_folders.rs +391 -130
  79. package/crates/mint-core/src/slash/mod.rs +470 -22
  80. package/crates/mint-core/src/slash/model_fetcher.rs +12 -3
  81. package/crates/mint-core/src/slash/models.rs +66 -10
  82. package/crates/mint-core/src/system/config.rs +230 -0
  83. package/crates/mint-core/src/system/workspace.rs +228 -0
  84. package/crates/mint-core/src/system.rs +1 -0
  85. package/crates/mint-core/tests/memory_persistence.rs +39 -0
  86. package/mint-presentation-demo.mp4 +0 -0
  87. package/out/web/assets/CliSessionsView-BxUVWEEL.js +1 -0
  88. package/out/web/assets/CliSessionsView-CBDTXuQv.css +1 -0
  89. package/out/web/assets/CodeReviewPage-DkMgfcos.css +1 -0
  90. package/out/web/assets/CodeReviewPage-jKlmLJwT.js +3 -0
  91. package/out/web/assets/CommandPalette-DnwPA5hy.js +1 -0
  92. package/out/web/assets/ImageStudioPanel-BR1XFwhR.js +1 -0
  93. package/out/web/assets/ImageStudioPanel-D0lnhQV5.css +1 -0
  94. package/out/web/assets/LinkedFoldersView-bi-CWQ-I.js +1 -0
  95. package/out/web/assets/McpRegistryPicker-D5tEFnyq.js +1 -0
  96. package/out/web/assets/McpServersView-BGG1dhFM.js +1 -0
  97. package/out/web/assets/MintDashboard-BIglDEWX.js +20 -0
  98. package/out/web/assets/MintDashboard-DSMywSgs.css +1 -0
  99. package/out/web/assets/ModelPanel-CbJ1PFoZ.js +1 -0
  100. package/out/web/assets/PicturesLibrary-CQP0fLP1.css +1 -0
  101. package/out/web/assets/PicturesLibrary-DoYN7T1p.js +1 -0
  102. package/out/web/assets/PluginsView-CU1HWXGk.js +1 -0
  103. package/out/web/assets/ScheduledTasksView-Bnl36y2N.js +1 -0
  104. package/out/web/assets/SettingsWindow-DhWLAn9T.css +1 -0
  105. package/out/web/assets/SettingsWindow-Dw8L01pw.js +2 -0
  106. package/out/web/assets/SkillsView-cnl8aY5p.js +2 -0
  107. package/out/web/assets/ToolSurfacePage-CgsQw6l5.css +1 -0
  108. package/out/web/assets/ToolSurfacePage-Cz2VJAPZ.js +37 -0
  109. package/out/web/assets/VeoStudioPanel-D4JnERWR.js +4 -0
  110. package/out/web/assets/VeoStudioPanel-DOj7_WR3.css +1 -0
  111. package/out/web/assets/WorkspacePanel-CbJ1PFoZ.js +1 -0
  112. package/out/web/assets/{abnfDiagram-VCTEODGH-DAOBA7ZG.js → abnfDiagram-VCTEODGH-ByMyfanq.js} +1 -1
  113. package/out/web/assets/{architecture-7GRP2DOG-CgSwQOPQ.js → architecture-7GRP2DOG-CLq2kEOB.js} +1 -1
  114. package/out/web/assets/{architectureDiagram-5GKGNRK7-CYp3yupP.js → architectureDiagram-5GKGNRK7-6PoVSmNG.js} +1 -1
  115. package/out/web/assets/{blockDiagram-NRAW4CY4-CyWybDWr.js → blockDiagram-NRAW4CY4-cKw9mAKi.js} +1 -1
  116. package/out/web/assets/{c4Diagram-UCG6FXSJ-BvY3U709.js → c4Diagram-UCG6FXSJ-Cqy8N5Ge.js} +1 -1
  117. package/out/web/assets/{chunk-75Z2AOVW-TLXCoZYv.js → chunk-75Z2AOVW-3qybijF5.js} +1 -1
  118. package/out/web/assets/chunk-CKBBP62Z-cIrXq6jN.js +2 -0
  119. package/out/web/assets/{chunk-CLGD4ZFX-xjsKtNS7.js → chunk-CLGD4ZFX-CndDQkww.js} +1 -1
  120. package/out/web/assets/chunk-DSNCTWBM-Cc4NxvgD.js +2 -0
  121. package/out/web/assets/chunk-DU6HZSFF-drzh6GsU.js +128 -0
  122. package/out/web/assets/{chunk-F27PBJKO-BFpgF55A.js → chunk-F27PBJKO-FiY35l4v.js} +1 -1
  123. package/out/web/assets/{chunk-G27WJ6UU-DfF7qW-C.js → chunk-G27WJ6UU-Bjt9Il4A.js} +1 -1
  124. package/out/web/assets/{chunk-GMAD6QVW-C-558kh_.js → chunk-GMAD6QVW-Bppi3Ctd.js} +1 -1
  125. package/out/web/assets/{chunk-JQ64N6SF-wJmeGKAw.js → chunk-JQ64N6SF-DGg5kcEV.js} +1 -1
  126. package/out/web/assets/{chunk-LCL6LL3I-C1wHD8Ie.js → chunk-LCL6LL3I-CCYcjd7p.js} +1 -1
  127. package/out/web/assets/{chunk-OBVCFTLP-BsRTPBqs.js → chunk-OBVCFTLP-DJeNil5M.js} +1 -1
  128. package/out/web/assets/{chunk-P2QGCYS3-HZIiM7Ni.js → chunk-P2QGCYS3-lRzkRjBB.js} +1 -1
  129. package/out/web/assets/{chunk-POPQ4Y6H-Dk9wvVb0.js → chunk-POPQ4Y6H-DouASMBW.js} +1 -1
  130. package/out/web/assets/{chunk-PWAF6VOD-BmjYLNbq.js → chunk-PWAF6VOD-DMmD1vVf.js} +1 -1
  131. package/out/web/assets/{chunk-R7TYR2AO-CaHIf-lK.js → chunk-R7TYR2AO-CYLA5UC5.js} +1 -1
  132. package/out/web/assets/{chunk-RHFEMEQ7-_T561hOU.js → chunk-RHFEMEQ7-BiXwEcUT.js} +1 -1
  133. package/out/web/assets/{chunk-SVP7TREG-CM-GGYoY.js → chunk-SVP7TREG-BV-zPslF.js} +1 -1
  134. package/out/web/assets/{chunk-TEH6E4GO-K2A8Vg2C.js → chunk-TEH6E4GO-B2RGEohZ.js} +1 -1
  135. package/out/web/assets/classDiagram-DTDB5LWJ-Dq0smRWk.js +1 -0
  136. package/out/web/assets/classDiagram-v2-JRS7N3AN-Dq0smRWk.js +1 -0
  137. package/out/web/assets/config-C-ZFtipU.css +1 -0
  138. package/out/web/assets/config-eEDngJXO.js +1 -0
  139. package/out/web/assets/core-hQ2VA9Ti.js +1 -0
  140. package/out/web/assets/{cynefin-OW5HDTMX-ClzaB6cc.js → cynefin-OW5HDTMX-Cas4csHM.js} +1 -1
  141. package/out/web/assets/{cynefinDiagram-5FMLGOSQ-D_JzZBzf.js → cynefinDiagram-5FMLGOSQ-Bbpj66Y3.js} +1 -1
  142. package/out/web/assets/{dagre-3AP2YEHR-BDuUeMHj.js → dagre-3AP2YEHR-B0-2RDEd.js} +1 -1
  143. package/out/web/assets/{diagram-S7CK7UJ4-DgtcfE8P.js → diagram-S7CK7UJ4-BdzEjUyH.js} +1 -1
  144. package/out/web/assets/{diagram-UQ7AKVKN-DTLoEYti.js → diagram-UQ7AKVKN-CJDwyPxF.js} +1 -1
  145. package/out/web/assets/{diagram-VSXAHHWV-ChGl9pXz.js → diagram-VSXAHHWV-BxaG1r_B.js} +1 -1
  146. package/out/web/assets/{diagram-VX7I27RA-Be8DWz0S.js → diagram-VX7I27RA-BMmUqm8f.js} +1 -1
  147. package/out/web/assets/{diagram-Z3DM3KII-BMXjRTOF.js → diagram-Z3DM3KII-CFtd03eE.js} +1 -1
  148. package/out/web/assets/dist-js-Bf2bhoku.js +1 -0
  149. package/out/web/assets/{ebnfDiagram-PWID7BFC-8Q9pl1CJ.js → ebnfDiagram-PWID7BFC-DwAen1hO.js} +1 -1
  150. package/out/web/assets/{erDiagram-SSCWMZ5O-DjH8Lnkn.js → erDiagram-SSCWMZ5O-BCZSHACj.js} +1 -1
  151. package/out/web/assets/event-ChBVpRy0.js +1 -0
  152. package/out/web/assets/{eventmodeling-NTZA5JFV-BKUH_DOp.js → eventmodeling-NTZA5JFV-XHStE4E_.js} +1 -1
  153. package/out/web/assets/fira-code-latin-600-normal-BmSSHshu.woff +0 -0
  154. package/out/web/assets/fira-code-latin-600-normal-CvYZpPHg.woff2 +0 -0
  155. package/out/web/assets/fira-code-symbols2-600-normal-Dvq6IQE5.woff +0 -0
  156. package/out/web/assets/flowDiagram-A5DVABFB-BLg7nEcd.js +1 -0
  157. package/out/web/assets/{ganttDiagram-EL5Y4UJY-D7fZKJNM.js → ganttDiagram-EL5Y4UJY-BAEu1Cql.js} +1 -1
  158. package/out/web/assets/{gitGraph-4MIJSDKK-BypWaaBU.js → gitGraph-4MIJSDKK-r32Vyper.js} +1 -1
  159. package/out/web/assets/{gitGraphDiagram-WWUBYQGX-DWiw_3bq.js → gitGraphDiagram-WWUBYQGX-z9o9qt6V.js} +1 -1
  160. package/out/web/assets/index-Btsf4L8M.css +1 -0
  161. package/out/web/assets/index-D8D9MeRA.js +11 -0
  162. package/out/web/assets/{info-A6RAGUB7-KkAUxT4j.js → info-A6RAGUB7-BvLaC2cw.js} +1 -1
  163. package/out/web/assets/{infoDiagram-RXCK75RN-BNb6E48y.js → infoDiagram-RXCK75RN-Be6WAXXw.js} +1 -1
  164. package/out/web/assets/{ishikawaDiagram-5VMMS53U-Caa-JoAK.js → ishikawaDiagram-5VMMS53U-DZjoHJHC.js} +1 -1
  165. package/out/web/assets/{journeyDiagram-EYS64GPL-DOrmFGz6.js → journeyDiagram-EYS64GPL-CtVkjkGm.js} +1 -1
  166. package/out/web/assets/{kanban-definition-3QL26DDD-BOWCYcK0.js → kanban-definition-3QL26DDD-CW5FMv1w.js} +1 -1
  167. package/out/web/assets/lucide-react-Ip3L6Jtn.js +1 -0
  168. package/out/web/assets/markdown-BSeeUbJH.js +38 -0
  169. package/out/web/assets/{mermaid-parser.core-BQqjCkS_.js → mermaid-parser.core-aUgCqsZ5.js} +3 -3
  170. package/out/web/assets/mermaid.core-D57sEiSL.js +11 -0
  171. package/out/web/assets/{mindmap-definition-FBJOCRG2-jTceWpr0.js → mindmap-definition-FBJOCRG2-DAmSpM3a.js} +1 -1
  172. package/out/web/assets/modelManager-tMVmJVAW.js +2 -0
  173. package/out/web/assets/oauthManager-9jxicDWJ.js +1 -0
  174. package/out/web/assets/{packet-AYTQ26CC-CJ5RXgol.js → packet-AYTQ26CC-DJ27iIoJ.js} +1 -1
  175. package/out/web/assets/{pegDiagram-XKGWAZYB-y8wMtd0y.js → pegDiagram-XKGWAZYB-Bj3ii-gS.js} +1 -1
  176. package/out/web/assets/{pie-WAS4IAKB-72fTBbl4.js → pie-WAS4IAKB-DG5mCUbc.js} +1 -1
  177. package/out/web/assets/{pieDiagram-E7YTZNPT-e0O02qWq.js → pieDiagram-E7YTZNPT-BrJLPnDA.js} +1 -1
  178. package/out/web/assets/prompt-latin-700-normal-BfbftDSq.woff +0 -0
  179. package/out/web/assets/prompt-latin-700-normal-I2gc831J.woff2 +0 -0
  180. package/out/web/assets/prompt-thai-700-normal-Cb5ilR-c.woff +0 -0
  181. package/out/web/assets/prompt-thai-700-normal-Cg4aQ0Nn.woff2 +0 -0
  182. package/out/web/assets/{quadrantDiagram-AXDQQJYC-C9phYLom.js → quadrantDiagram-AXDQQJYC-3x_TmF3j.js} +1 -1
  183. package/out/web/assets/{radar-RG4KPBEZ-BAU2hzUT.js → radar-RG4KPBEZ-CrXaTTuV.js} +1 -1
  184. package/out/web/assets/{railroad-74A4TZTK-B0bCAVHC.js → railroad-74A4TZTK-BpqMH9BE.js} +1 -1
  185. package/out/web/assets/{railroad-abnf-HS5TGJTU-WhxO7ndE.js → railroad-abnf-HS5TGJTU-DHI0uLlV.js} +1 -1
  186. package/out/web/assets/{railroad-ebnf-LZEXJU2U-BkA0m7-F.js → railroad-ebnf-LZEXJU2U-CQCb316y.js} +1 -1
  187. package/out/web/assets/{railroad-peg-WCYAUIDC-BsVpHIaj.js → railroad-peg-WCYAUIDC-Ph1giKkH.js} +1 -1
  188. package/out/web/assets/{railroadDiagram-O6MQD6OU-CyOLN65Q.js → railroadDiagram-O6MQD6OU-BRq6wIxx.js} +1 -1
  189. package/out/web/assets/{requirementDiagram-EFPCY7ZU-DQXJ7Dud.js → requirementDiagram-EFPCY7ZU-DIJj6G1g.js} +1 -1
  190. package/out/web/assets/{sankeyDiagram-P5KCCOFB-B2XLyIIc.js → sankeyDiagram-P5KCCOFB-DZajSryq.js} +1 -1
  191. package/out/web/assets/{sequenceDiagram-WJ2MYXX4-DGQY4wwm.js → sequenceDiagram-WJ2MYXX4-DxJCWyZS.js} +1 -1
  192. package/out/web/assets/{stateDiagram-HBIQ2CUA-DHZpDwNy.js → stateDiagram-HBIQ2CUA-k6voi8Vf.js} +1 -1
  193. package/out/web/assets/stateDiagram-v2-4QOOHH4V-DeEc0lGZ.js +1 -0
  194. package/out/web/assets/studio-B1mk40wD.js +1 -0
  195. package/out/web/assets/{swimlanes-XN3QIQJK-Bn_jcZz-.js → swimlanes-XN3QIQJK-igYhTjXB.js} +1 -1
  196. package/out/web/assets/swimlanesDiagram-VK2B7HYN-DpVik9v7.js +8 -0
  197. package/out/web/assets/{timeline-definition-24CTP7MA-CdTERuJZ.js → timeline-definition-24CTP7MA-Dke2p93p.js} +1 -1
  198. package/out/web/assets/{treeView-Q6P3EWNA-TKBKQG6R.js → treeView-Q6P3EWNA-hNELnXUs.js} +1 -1
  199. package/out/web/assets/{treemap-WGGIJYW6-BP7gQoiC.js → treemap-WGGIJYW6-D2B6wDsx.js} +1 -1
  200. package/out/web/assets/{vennDiagram-4TSXK5OY-BHUmxDuK.js → vennDiagram-4TSXK5OY-CDkW7rUP.js} +1 -1
  201. package/out/web/assets/{wardley-WFR3VGLG-9bct5AAN.js → wardley-WFR3VGLG-BECdXETi.js} +1 -1
  202. package/out/web/assets/{wardleyDiagram-VM6X3IG4-BfJwDDso.js → wardleyDiagram-VM6X3IG4-B5BycpQ4.js} +1 -1
  203. package/out/web/assets/window-5qYXKoW7.js +1 -0
  204. package/out/web/assets/{xychartDiagram-S5SC5T6Z-Dqd9Mvpo.js → xychartDiagram-S5SC5T6Z-CtJS3b--.js} +1 -1
  205. package/out/web/index-web.html +3 -4
  206. package/out/web/index.html +3 -4
  207. package/package.json +17 -6
  208. package/skills-lock.json +36 -0
  209. package/slash-commands.json +9 -0
  210. package/src/renderer/index-web.html +1 -0
  211. package/src/renderer/index.html +1 -0
  212. package/src/renderer/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  213. package/src/renderer/shared/agentProgress.ts +168 -3
  214. package/src/renderer/shared/components/AgentActivityDrawer.tsx +6 -6
  215. package/src/renderer/shared/components/AgentActivityTable.tsx +192 -132
  216. package/src/renderer/shared/components/ArtifactPreviewPanel.tsx +4 -4
  217. package/src/renderer/shared/components/AuthGate.tsx +4 -9
  218. package/src/renderer/shared/components/CalculationCard.tsx +41 -15
  219. package/src/renderer/shared/components/ChatMessageItem.tsx +20 -21
  220. package/src/renderer/shared/components/ChatPanel.tsx +432 -193
  221. package/src/renderer/shared/components/ChunkErrorBoundary.tsx +198 -49
  222. package/src/renderer/shared/components/CliSessionsView.tsx +495 -0
  223. package/src/renderer/shared/components/CodeReviewPage.tsx +565 -0
  224. package/src/renderer/shared/components/CommandPalette.tsx +8 -8
  225. package/src/renderer/shared/components/DashboardSidebar.tsx +862 -125
  226. package/src/renderer/shared/components/DesktopTitlebar.tsx +345 -0
  227. package/src/renderer/shared/components/DiffReviewModal.tsx +3 -3
  228. package/src/renderer/shared/components/GitBranchSelector.tsx +442 -0
  229. package/src/renderer/shared/components/ImageGenCard.tsx +31 -12
  230. package/src/renderer/shared/components/ImageSearchCard.tsx +59 -38
  231. package/src/renderer/shared/components/ImageStudioPanel.tsx +40 -41
  232. package/src/renderer/shared/components/InlineThoughtNote.tsx +27 -0
  233. package/src/renderer/shared/components/LinkedFoldersView.tsx +365 -46
  234. package/src/renderer/shared/components/McpRegistryPicker.tsx +1 -1
  235. package/src/renderer/shared/components/McpServersView.tsx +24 -22
  236. package/src/renderer/shared/components/MermaidCard.tsx +14 -8
  237. package/src/renderer/shared/components/MintDashboard.tsx +1141 -508
  238. package/src/renderer/shared/components/ModelSelectorPopover.tsx +535 -214
  239. package/src/renderer/shared/components/PlanChecklistWidget.tsx +1 -1
  240. package/src/renderer/shared/components/PluginsView.tsx +1 -1
  241. package/src/renderer/shared/components/RewindModal.tsx +6 -6
  242. package/src/renderer/shared/components/RunSummaryDashboard.tsx +3 -3
  243. package/src/renderer/shared/components/ScheduledTasksView.tsx +4 -4
  244. package/src/renderer/shared/components/ScreenCaptureDialog.css +221 -0
  245. package/src/renderer/shared/components/ScreenCaptureDialog.tsx +199 -0
  246. package/src/renderer/shared/components/Settings/AgentsTab.tsx +34 -39
  247. package/src/renderer/shared/components/Settings/AudioTab.tsx +8 -8
  248. package/src/renderer/shared/components/Settings/AutomationTab.tsx +8 -58
  249. package/src/renderer/shared/components/Settings/AvatarCropModal.tsx +368 -0
  250. package/src/renderer/shared/components/Settings/GeneralTab.tsx +335 -81
  251. package/src/renderer/shared/components/Settings/MemoryTab.tsx +3 -3
  252. package/src/renderer/shared/components/Settings/PluginsTab.tsx +20 -12
  253. package/src/renderer/shared/components/Settings/ProfileTab.tsx +29 -5
  254. package/src/renderer/shared/components/Settings/SearchableModelCombobox.tsx +411 -0
  255. package/src/renderer/shared/components/Settings/ThemeTab.tsx +401 -158
  256. package/src/renderer/shared/components/SkillsView.tsx +41 -16
  257. package/src/renderer/shared/components/SlashSuggestions.tsx +3 -2
  258. package/src/renderer/shared/components/SourcesBlock.tsx +44 -32
  259. package/src/renderer/shared/components/StockCard.tsx +58 -24
  260. package/src/renderer/shared/components/SubagentDagView.tsx +4 -4
  261. package/src/renderer/shared/components/TerminalDock.tsx +241 -0
  262. package/src/renderer/shared/components/ThinkingBlock.tsx +14 -8
  263. package/src/renderer/shared/components/ToolSurfacePage.tsx +520 -0
  264. package/src/renderer/shared/components/UiFeatureCard.tsx +267 -0
  265. package/src/renderer/shared/components/UiGridCard.tsx +188 -0
  266. package/src/renderer/shared/components/UiMockupWidget.tsx +149 -0
  267. package/src/renderer/shared/components/VeoStudioPanel.tsx +13 -29
  268. package/src/renderer/shared/components/WeatherCard.tsx +3 -3
  269. package/src/renderer/shared/components/WorkspaceContextPopover.tsx +133 -0
  270. package/src/renderer/shared/components/WorkspaceSelector.tsx +149 -0
  271. package/src/renderer/shared/constants/config.ts +28 -3
  272. package/src/renderer/shared/constants/models.ts +189 -2
  273. package/src/renderer/shared/conversation/coordinator.test.ts +27 -0
  274. package/src/renderer/shared/conversation/coordinator.ts +82 -0
  275. package/src/renderer/shared/conversation/syncView.test.ts +46 -0
  276. package/src/renderer/shared/conversation/syncView.ts +43 -0
  277. package/src/renderer/shared/conversation/useConversationCoordinator.ts +106 -0
  278. package/src/renderer/shared/css/agent-observability.css +35 -3
  279. package/src/renderer/shared/css/auth-gate.css +2 -2
  280. package/src/renderer/shared/css/chat-ui-cards.css +495 -0
  281. package/src/renderer/shared/css/code-review.css +823 -0
  282. package/src/renderer/shared/css/code-sessions.css +452 -0
  283. package/src/renderer/shared/css/file-changes.css +132 -0
  284. package/src/renderer/shared/css/image-studio.css +16 -16
  285. package/src/renderer/shared/css/management-views.css +277 -27
  286. package/src/renderer/shared/css/model-selector.css +442 -42
  287. package/src/renderer/shared/css/settings/agents.css +1 -1
  288. package/src/renderer/shared/css/settings/automation.css +13 -13
  289. package/src/renderer/shared/css/settings/general.css +526 -5
  290. package/src/renderer/shared/css/settings/plugins.css +5 -5
  291. package/src/renderer/shared/css/settings/profile.css +331 -1
  292. package/src/renderer/shared/css/settings/theme.css +651 -3
  293. package/src/renderer/shared/css/veo-studio.css +16 -15
  294. package/src/renderer/shared/fonts.ts +19 -37
  295. package/src/renderer/shared/platform.test.ts +34 -0
  296. package/src/renderer/shared/platform.ts +173 -6
  297. package/src/renderer/shared/theme/themeManager.ts +144 -0
  298. package/src/renderer/shared/theme/themes.ts +116 -0
  299. package/src/renderer/shared/theme/tokens.css +318 -0
  300. package/src/renderer/shared/types.ts +82 -1
  301. package/src/renderer/shared/utils/agentActivity.ts +126 -5
  302. package/src/renderer/shared/utils/cardJson.test.ts +35 -0
  303. package/src/renderer/shared/utils/cardJson.ts +30 -0
  304. package/src/renderer/shared/utils/fileIcons.ts +1 -1
  305. package/src/renderer/shared/utils/markdown.tsx +329 -80
  306. package/src/renderer/shared/utils/markdown.webImages.test.tsx +40 -0
  307. package/src/renderer/shared/utils/providers.ts +8 -3
  308. package/src/renderer/shared/utils/screenCapture.ts +43 -0
  309. package/src/renderer/shared/utils/slashCommandProcessor.ts +4 -1
  310. package/src/renderer/shared/utils/ui.ts +4 -64
  311. package/src/renderer/src/App.tsx +7 -0
  312. package/src/renderer/src/components/BrowserShell.tsx +108 -0
  313. package/src/renderer/src/components/BrowserSuggestionsPopup.tsx +91 -0
  314. package/src/renderer/src/components/Live2DStage.tsx +32 -9
  315. package/src/renderer/src/components/MintDashboard.tsx +4 -2
  316. package/src/renderer/src/components/ModelPanel.tsx +2 -1
  317. package/src/renderer/src/components/PicturesLibrary.tsx +3 -2
  318. package/src/renderer/src/components/ScreenPicker.css +190 -0
  319. package/src/renderer/src/components/ScreenPicker.tsx +185 -540
  320. package/src/renderer/src/components/SettingsWindow.tsx +40 -2
  321. package/src/renderer/src/components/SpotlightWindow.tsx +1 -0
  322. package/src/renderer/src/components/WidgetWindow.tsx +27 -3
  323. package/src/renderer/src/components/WorkspacePanel.tsx +61 -43
  324. package/src/renderer/src/components/browser-shell.css +185 -0
  325. package/src/renderer/src/components/browser-suggestions-popup.css +55 -0
  326. package/src/renderer/src/components/liveTranslateFrames.test.ts +23 -0
  327. package/src/renderer/src/components/liveTranslateFrames.ts +34 -0
  328. package/src/renderer/src/css/app-shell.css +394 -113
  329. package/src/renderer/src/css/chat.css +1926 -380
  330. package/src/renderer/src/css/dashboard.css +11 -0
  331. package/src/renderer/src/css/desktop-tools.css +730 -0
  332. package/src/renderer/src/css/misc.css +19 -22
  333. package/src/renderer/src/css/model.css +49 -48
  334. package/src/renderer/src/css/pictures.css +144 -136
  335. package/src/renderer/src/css/settings/base.css +357 -123
  336. package/src/renderer/src/css/sidebar-workspace.css +930 -291
  337. package/src/renderer/src/css/spotlight.css +15 -26
  338. package/src/renderer/src/css/tool-surfaces.css +728 -0
  339. package/src/renderer/src/css/widget.css +35 -7
  340. package/src/renderer/src/env.d.ts +3 -0
  341. package/src/renderer/src/hooks/useProviderModels.ts +2 -9
  342. package/src/renderer/src/index.css +53 -46
  343. package/src/renderer/src/main.tsx +11 -0
  344. package/src/renderer/src/tauri.ts +201 -30
  345. package/src/renderer/src-web/App.tsx +40 -0
  346. package/src/renderer/src-web/components/MintDashboard.tsx +4 -2
  347. package/src/renderer/src-web/components/PicturesLibrary.tsx +3 -2
  348. package/src/renderer/src-web/components/PullToRefresh.tsx +107 -0
  349. package/src/renderer/src-web/components/SettingsWindow.tsx +28 -2
  350. package/src/renderer/src-web/css/app-shell.css +174 -96
  351. package/src/renderer/src-web/css/chat.css +1519 -316
  352. package/src/renderer/src-web/css/dashboard.css +11 -0
  353. package/src/renderer/src-web/css/misc.css +17 -17
  354. package/src/renderer/src-web/css/mobile.css +678 -0
  355. package/src/renderer/src-web/css/model.css +46 -46
  356. package/src/renderer/src-web/css/pictures.css +81 -34
  357. package/src/renderer/src-web/css/pull-to-refresh.css +54 -0
  358. package/src/renderer/src-web/css/settings/base.css +316 -100
  359. package/src/renderer/src-web/css/settings/mobile.css +320 -0
  360. package/src/renderer/src-web/css/sidebar-workspace.css +545 -100
  361. package/src/renderer/src-web/css/spotlight.css +9 -26
  362. package/src/renderer/src-web/css/widget.css +0 -5
  363. package/src/renderer/src-web/env.d.ts +3 -0
  364. package/src/renderer/src-web/hooks/useProviderModels.ts +2 -9
  365. package/src/renderer/src-web/index.css +53 -96
  366. package/src/renderer/src-web/main.tsx +11 -0
  367. package/src/renderer/src-web/tauri.ts +200 -30
  368. package/vite.config.web.ts +1 -0
  369. package/out/web/assets/MintDashboard-DWSqucgb.js +0 -57
  370. package/out/web/assets/SettingsWindow-DFM2aj5B.js +0 -2
  371. package/out/web/assets/chunk-CKBBP62Z-nr1uKPj9.js +0 -2
  372. package/out/web/assets/chunk-DSNCTWBM-Dtj8Rqsd.js +0 -2
  373. package/out/web/assets/chunk-DU6HZSFF-2tv5K1wT.js +0 -128
  374. package/out/web/assets/classDiagram-DTDB5LWJ-BdSFArgw.js +0 -1
  375. package/out/web/assets/classDiagram-v2-JRS7N3AN-BdSFArgw.js +0 -1
  376. package/out/web/assets/core-DImejIUG.js +0 -1
  377. package/out/web/assets/dist-js-BxuKEVWM.js +0 -1
  378. package/out/web/assets/event-BNl8Zahw.js +0 -1
  379. package/out/web/assets/fira-code-cyrillic-400-normal-UC0NFL4U.woff2 +0 -0
  380. package/out/web/assets/fira-code-cyrillic-400-normal-dc1q3VD7.woff +0 -0
  381. package/out/web/assets/fira-code-cyrillic-500-normal-Bu7VCL72.woff +0 -0
  382. package/out/web/assets/fira-code-cyrillic-500-normal-CX35h3Mg.woff2 +0 -0
  383. package/out/web/assets/fira-code-cyrillic-ext-400-normal-Buh61xzB.woff +0 -0
  384. package/out/web/assets/fira-code-cyrillic-ext-400-normal-txZ9Fk_1.woff2 +0 -0
  385. package/out/web/assets/fira-code-cyrillic-ext-500-normal-CYRspHgm.woff2 +0 -0
  386. package/out/web/assets/fira-code-cyrillic-ext-500-normal-CwtLmSFD.woff +0 -0
  387. package/out/web/assets/fira-code-greek-400-normal-B2Gh_Y8s.woff2 +0 -0
  388. package/out/web/assets/fira-code-greek-400-normal-DobhaxvF.woff +0 -0
  389. package/out/web/assets/fira-code-greek-500-normal-CVO0IRNt.woff2 +0 -0
  390. package/out/web/assets/fira-code-greek-500-normal-DEXIWiey.woff +0 -0
  391. package/out/web/assets/fira-code-greek-ext-400-normal-DR7mBgIM.woff2 +0 -0
  392. package/out/web/assets/fira-code-greek-ext-400-normal-DSPUheWg.woff +0 -0
  393. package/out/web/assets/fira-code-greek-ext-500-normal-BO3iq16n.woff2 +0 -0
  394. package/out/web/assets/fira-code-greek-ext-500-normal-CMiNLXER.woff +0 -0
  395. package/out/web/assets/fira-code-latin-ext-400-normal-DG73JjOf.woff +0 -0
  396. package/out/web/assets/fira-code-latin-ext-400-normal-KSMg0QLl.woff2 +0 -0
  397. package/out/web/assets/fira-code-latin-ext-500-normal-CaANqXjI.woff +0 -0
  398. package/out/web/assets/fira-code-latin-ext-500-normal-Crd9e_oI.woff2 +0 -0
  399. package/out/web/assets/flowDiagram-A5DVABFB-BpnHUSU7.js +0 -1
  400. package/out/web/assets/index-CVRg270z.css +0 -1
  401. package/out/web/assets/index-DxZQr9yD.js +0 -10
  402. package/out/web/assets/inter-cyrillic-400-normal-HOLc17fK.woff +0 -0
  403. package/out/web/assets/inter-cyrillic-400-normal-obahsSVq.woff2 +0 -0
  404. package/out/web/assets/inter-cyrillic-500-normal-BasfLYem.woff2 +0 -0
  405. package/out/web/assets/inter-cyrillic-500-normal-CxZf_p3X.woff +0 -0
  406. package/out/web/assets/inter-cyrillic-600-normal-4D_pXhcN.woff +0 -0
  407. package/out/web/assets/inter-cyrillic-600-normal-CWCymEST.woff2 +0 -0
  408. package/out/web/assets/inter-cyrillic-ext-400-normal-BQZuk6qB.woff2 +0 -0
  409. package/out/web/assets/inter-cyrillic-ext-400-normal-DQukG94-.woff +0 -0
  410. package/out/web/assets/inter-cyrillic-ext-500-normal-B0yAr1jD.woff2 +0 -0
  411. package/out/web/assets/inter-cyrillic-ext-500-normal-BmqWE9Dz.woff +0 -0
  412. package/out/web/assets/inter-cyrillic-ext-600-normal-Bcila6Z-.woff +0 -0
  413. package/out/web/assets/inter-cyrillic-ext-600-normal-Dfes3d0z.woff2 +0 -0
  414. package/out/web/assets/inter-greek-400-normal-B4URO6DV.woff2 +0 -0
  415. package/out/web/assets/inter-greek-400-normal-q2sYcFCs.woff +0 -0
  416. package/out/web/assets/inter-greek-500-normal-BIZE56-Y.woff2 +0 -0
  417. package/out/web/assets/inter-greek-500-normal-Xzm54t5V.woff +0 -0
  418. package/out/web/assets/inter-greek-600-normal-BZpKdvQh.woff +0 -0
  419. package/out/web/assets/inter-greek-600-normal-plRanbMR.woff2 +0 -0
  420. package/out/web/assets/inter-greek-ext-400-normal-DGGRlc-M.woff2 +0 -0
  421. package/out/web/assets/inter-greek-ext-400-normal-KugGGMne.woff +0 -0
  422. package/out/web/assets/inter-greek-ext-500-normal-2j5mBUwD.woff +0 -0
  423. package/out/web/assets/inter-greek-ext-500-normal-C4iEst2y.woff2 +0 -0
  424. package/out/web/assets/inter-greek-ext-600-normal-B8X0CLgF.woff +0 -0
  425. package/out/web/assets/inter-greek-ext-600-normal-DRtmH8MT.woff2 +0 -0
  426. package/out/web/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  427. package/out/web/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
  428. package/out/web/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
  429. package/out/web/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  430. package/out/web/assets/inter-latin-600-normal-CiBQ2DWP.woff +0 -0
  431. package/out/web/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
  432. package/out/web/assets/inter-latin-ext-400-normal-77YHD8bZ.woff +0 -0
  433. package/out/web/assets/inter-latin-ext-400-normal-C1nco2VV.woff2 +0 -0
  434. package/out/web/assets/inter-latin-ext-500-normal-BxGbmqWO.woff +0 -0
  435. package/out/web/assets/inter-latin-ext-500-normal-CV4jyFjo.woff2 +0 -0
  436. package/out/web/assets/inter-latin-ext-600-normal-CIVaiw4L.woff +0 -0
  437. package/out/web/assets/inter-latin-ext-600-normal-D2bJ5OIk.woff2 +0 -0
  438. package/out/web/assets/inter-vietnamese-400-normal-Bbgyi5SW.woff +0 -0
  439. package/out/web/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
  440. package/out/web/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
  441. package/out/web/assets/inter-vietnamese-500-normal-mJboJaSs.woff +0 -0
  442. package/out/web/assets/inter-vietnamese-600-normal-BuLX-rYi.woff +0 -0
  443. package/out/web/assets/inter-vietnamese-600-normal-Cc8MFFhd.woff2 +0 -0
  444. package/out/web/assets/kanit-latin-400-normal-BUlsQXH3.woff2 +0 -0
  445. package/out/web/assets/kanit-latin-400-normal-HVZWrfev.woff +0 -0
  446. package/out/web/assets/kanit-latin-500-normal-CX_4XcKi.woff2 +0 -0
  447. package/out/web/assets/kanit-latin-500-normal-qBha86O4.woff +0 -0
  448. package/out/web/assets/kanit-latin-600-normal-0lS78yAd.woff2 +0 -0
  449. package/out/web/assets/kanit-latin-600-normal-DlacpeTg.woff +0 -0
  450. package/out/web/assets/kanit-latin-ext-400-normal-B2xPf58u.woff2 +0 -0
  451. package/out/web/assets/kanit-latin-ext-400-normal-CHvNKHHD.woff +0 -0
  452. package/out/web/assets/kanit-latin-ext-500-normal-BFdWrG22.woff +0 -0
  453. package/out/web/assets/kanit-latin-ext-500-normal-EHs3suD6.woff2 +0 -0
  454. package/out/web/assets/kanit-latin-ext-600-normal-BBDzoLaj.woff +0 -0
  455. package/out/web/assets/kanit-latin-ext-600-normal-DAX3wtuq.woff2 +0 -0
  456. package/out/web/assets/kanit-thai-400-normal-D2nliXKa.woff +0 -0
  457. package/out/web/assets/kanit-thai-400-normal-D80Pglro.woff2 +0 -0
  458. package/out/web/assets/kanit-thai-500-normal-BB8gri04.woff2 +0 -0
  459. package/out/web/assets/kanit-thai-500-normal-Iy_w0a80.woff +0 -0
  460. package/out/web/assets/kanit-thai-600-normal-Bj6oiaDc.woff2 +0 -0
  461. package/out/web/assets/kanit-thai-600-normal-wbTlPO7I.woff +0 -0
  462. package/out/web/assets/kanit-vietnamese-400-normal-DRI8YWyb.woff2 +0 -0
  463. package/out/web/assets/kanit-vietnamese-400-normal-dow6Bnto.woff +0 -0
  464. package/out/web/assets/kanit-vietnamese-500-normal-BzTrpCM3.woff2 +0 -0
  465. package/out/web/assets/kanit-vietnamese-500-normal-T1ndT7MF.woff +0 -0
  466. package/out/web/assets/kanit-vietnamese-600-normal-Bi7fw3I4.woff2 +0 -0
  467. package/out/web/assets/kanit-vietnamese-600-normal-DXCRAa_8.woff +0 -0
  468. package/out/web/assets/mali-latin-400-normal-ByPcZ8Gx.woff +0 -0
  469. package/out/web/assets/mali-latin-400-normal-Cuc6Ykl8.woff2 +0 -0
  470. package/out/web/assets/mali-latin-500-normal-B01M-LP6.woff2 +0 -0
  471. package/out/web/assets/mali-latin-500-normal-Thgqw_9f.woff +0 -0
  472. package/out/web/assets/mali-latin-600-normal-B9TiUNpT.woff2 +0 -0
  473. package/out/web/assets/mali-latin-600-normal-CycpQCwU.woff +0 -0
  474. package/out/web/assets/mali-latin-ext-400-normal-DUVdJQO4.woff +0 -0
  475. package/out/web/assets/mali-latin-ext-400-normal-iCG1ALuJ.woff2 +0 -0
  476. package/out/web/assets/mali-latin-ext-500-normal-BfJE4UMZ.woff2 +0 -0
  477. package/out/web/assets/mali-latin-ext-500-normal-FoLEyOKS.woff +0 -0
  478. package/out/web/assets/mali-latin-ext-600-normal-BTvIfiCp.woff2 +0 -0
  479. package/out/web/assets/mali-latin-ext-600-normal-DAQcLVmD.woff +0 -0
  480. package/out/web/assets/mali-thai-400-normal-BO7A3bLZ.woff2 +0 -0
  481. package/out/web/assets/mali-thai-400-normal-CX9VrjTn.woff +0 -0
  482. package/out/web/assets/mali-thai-500-normal-Cph2qha9.woff +0 -0
  483. package/out/web/assets/mali-thai-500-normal-D89rMT77.woff2 +0 -0
  484. package/out/web/assets/mali-thai-600-normal-DPgXT6rZ.woff +0 -0
  485. package/out/web/assets/mali-thai-600-normal-DlTx3OsB.woff2 +0 -0
  486. package/out/web/assets/mali-vietnamese-400-normal-DUKxzXaz.woff2 +0 -0
  487. package/out/web/assets/mali-vietnamese-400-normal-gFDLvsOK.woff +0 -0
  488. package/out/web/assets/mali-vietnamese-500-normal--OY07q2c.woff +0 -0
  489. package/out/web/assets/mali-vietnamese-500-normal-KDrNRwfW.woff2 +0 -0
  490. package/out/web/assets/mali-vietnamese-600-normal-CtTMUU7T.woff +0 -0
  491. package/out/web/assets/mali-vietnamese-600-normal-DFlJr66u.woff2 +0 -0
  492. package/out/web/assets/mermaid.core-DYGGlqOf.js +0 -11
  493. package/out/web/assets/mitr-latin-400-normal-Cb18vPmZ.woff +0 -0
  494. package/out/web/assets/mitr-latin-400-normal-CwbkLQ4a.woff2 +0 -0
  495. package/out/web/assets/mitr-latin-500-normal-B4JOhzAi.woff +0 -0
  496. package/out/web/assets/mitr-latin-500-normal-BmClOow2.woff2 +0 -0
  497. package/out/web/assets/mitr-latin-ext-400-normal-B3CPG7Yo.woff2 +0 -0
  498. package/out/web/assets/mitr-latin-ext-400-normal-DTx65hiC.woff +0 -0
  499. package/out/web/assets/mitr-latin-ext-500-normal-B_Diajz1.woff2 +0 -0
  500. package/out/web/assets/mitr-latin-ext-500-normal-DYOsVaVT.woff +0 -0
  501. package/out/web/assets/mitr-thai-400-normal-CS4Do6aM.woff +0 -0
  502. package/out/web/assets/mitr-thai-400-normal-CXWaAdVj.woff2 +0 -0
  503. package/out/web/assets/mitr-thai-500-normal-CVdBrEVH.woff2 +0 -0
  504. package/out/web/assets/mitr-thai-500-normal-CW_B5D-i.woff +0 -0
  505. package/out/web/assets/mitr-vietnamese-400-normal-CPMGWyoC.woff2 +0 -0
  506. package/out/web/assets/mitr-vietnamese-400-normal-Z6XhIpdY.woff +0 -0
  507. package/out/web/assets/mitr-vietnamese-500-normal-CDrv0585.woff2 +0 -0
  508. package/out/web/assets/mitr-vietnamese-500-normal-CMQWyq-Z.woff +0 -0
  509. package/out/web/assets/noto-sans-thai-latin-400-normal-BaWBrqFP.woff2 +0 -0
  510. package/out/web/assets/noto-sans-thai-latin-400-normal-Dh_FJjOB.woff +0 -0
  511. package/out/web/assets/noto-sans-thai-latin-500-normal-BC04jsmm.woff +0 -0
  512. package/out/web/assets/noto-sans-thai-latin-500-normal-fyBKClF1.woff2 +0 -0
  513. package/out/web/assets/noto-sans-thai-latin-600-normal-CemcjnVR.woff2 +0 -0
  514. package/out/web/assets/noto-sans-thai-latin-600-normal-Dbc-dNO6.woff +0 -0
  515. package/out/web/assets/noto-sans-thai-latin-ext-400-normal-B-1H0YkH.woff +0 -0
  516. package/out/web/assets/noto-sans-thai-latin-ext-400-normal-nBP59pVw.woff2 +0 -0
  517. package/out/web/assets/noto-sans-thai-latin-ext-500-normal-B-ZWb8SZ.woff2 +0 -0
  518. package/out/web/assets/noto-sans-thai-latin-ext-500-normal-CrEHO7C8.woff +0 -0
  519. package/out/web/assets/noto-sans-thai-latin-ext-600-normal-PkMZo0xa.woff +0 -0
  520. package/out/web/assets/noto-sans-thai-latin-ext-600-normal-maHHBsez.woff2 +0 -0
  521. package/out/web/assets/noto-sans-thai-thai-400-normal-BEOmKAI1.woff2 +0 -0
  522. package/out/web/assets/noto-sans-thai-thai-400-normal-Dxb_unuU.woff +0 -0
  523. package/out/web/assets/noto-sans-thai-thai-500-normal-BOGXO2tw.woff +0 -0
  524. package/out/web/assets/noto-sans-thai-thai-500-normal-CU_X86GQ.woff2 +0 -0
  525. package/out/web/assets/noto-sans-thai-thai-600-normal-CmgB8_JK.woff +0 -0
  526. package/out/web/assets/noto-sans-thai-thai-600-normal-Cs73sVjl.woff2 +0 -0
  527. package/out/web/assets/oauthManager-DNiwM8Rn.js +0 -2
  528. package/out/web/assets/oauthManager-DuamS1Av.css +0 -1
  529. package/out/web/assets/outfit-latin-300-normal-AWLfuCom.woff +0 -0
  530. package/out/web/assets/outfit-latin-300-normal-CRYTwY6m.woff2 +0 -0
  531. package/out/web/assets/outfit-latin-400-normal-BGsTXAXT.woff2 +0 -0
  532. package/out/web/assets/outfit-latin-400-normal-DMwTpYkH.woff +0 -0
  533. package/out/web/assets/outfit-latin-500-normal-ClnHRwRh.woff +0 -0
  534. package/out/web/assets/outfit-latin-500-normal-DKnIMDSk.woff2 +0 -0
  535. package/out/web/assets/outfit-latin-600-normal-B7SfZ07L.woff2 +0 -0
  536. package/out/web/assets/outfit-latin-600-normal-BEfTtDA7.woff +0 -0
  537. package/out/web/assets/outfit-latin-ext-300-normal-BYS6Dpvq.woff2 +0 -0
  538. package/out/web/assets/outfit-latin-ext-300-normal-CMIMshEd.woff +0 -0
  539. package/out/web/assets/outfit-latin-ext-400-normal-5tcqmc2S.woff2 +0 -0
  540. package/out/web/assets/outfit-latin-ext-400-normal-DHm7mdGe.woff +0 -0
  541. package/out/web/assets/outfit-latin-ext-500-normal-DrCvqoFD.woff +0 -0
  542. package/out/web/assets/outfit-latin-ext-500-normal-zeox_O30.woff2 +0 -0
  543. package/out/web/assets/outfit-latin-ext-600-normal-B85nYjL1.woff2 +0 -0
  544. package/out/web/assets/outfit-latin-ext-600-normal-CWJcPgd7.woff +0 -0
  545. package/out/web/assets/preload-helper-D0uHx7FM.js +0 -1
  546. package/out/web/assets/prompt-latin-ext-400-normal-1pHbN9uy.woff +0 -0
  547. package/out/web/assets/prompt-latin-ext-400-normal-DdSafGZ9.woff2 +0 -0
  548. package/out/web/assets/prompt-latin-ext-500-normal--EZ1um7s.woff2 +0 -0
  549. package/out/web/assets/prompt-latin-ext-500-normal-D-lI1EVT.woff +0 -0
  550. package/out/web/assets/prompt-latin-ext-600-normal-C8b50x67.woff +0 -0
  551. package/out/web/assets/prompt-latin-ext-600-normal-Cg9L7iJU.woff2 +0 -0
  552. package/out/web/assets/prompt-vietnamese-400-normal-BCPzsgPT.woff2 +0 -0
  553. package/out/web/assets/prompt-vietnamese-400-normal-D4pLyeNK.woff +0 -0
  554. package/out/web/assets/prompt-vietnamese-500-normal-DmzxmPwa.woff2 +0 -0
  555. package/out/web/assets/prompt-vietnamese-500-normal-w_sS_j2F.woff +0 -0
  556. package/out/web/assets/prompt-vietnamese-600-normal-1dyohtNh.woff +0 -0
  557. package/out/web/assets/prompt-vietnamese-600-normal-7QWjJBsF.woff2 +0 -0
  558. package/out/web/assets/sarabun-latin-400-normal-DmguIS-7.woff +0 -0
  559. package/out/web/assets/sarabun-latin-400-normal-URPBxl-K.woff2 +0 -0
  560. package/out/web/assets/sarabun-latin-500-normal-BjUTcdxu.woff2 +0 -0
  561. package/out/web/assets/sarabun-latin-500-normal-CJexTAnl.woff +0 -0
  562. package/out/web/assets/sarabun-latin-600-normal-9FonlkKx.woff +0 -0
  563. package/out/web/assets/sarabun-latin-600-normal-DMD3TROr.woff2 +0 -0
  564. package/out/web/assets/sarabun-latin-ext-400-normal-BbP7GpLL.woff2 +0 -0
  565. package/out/web/assets/sarabun-latin-ext-400-normal-BsmTn0SS.woff +0 -0
  566. package/out/web/assets/sarabun-latin-ext-500-normal-Cot16Bd2.woff +0 -0
  567. package/out/web/assets/sarabun-latin-ext-500-normal-DE1LysqI.woff2 +0 -0
  568. package/out/web/assets/sarabun-latin-ext-600-normal-0tXu9x_i.woff +0 -0
  569. package/out/web/assets/sarabun-latin-ext-600-normal-BRxjKUQ6.woff2 +0 -0
  570. package/out/web/assets/sarabun-thai-400-normal-C2DaJlKK.woff2 +0 -0
  571. package/out/web/assets/sarabun-thai-400-normal-CH-UbWgg.woff +0 -0
  572. package/out/web/assets/sarabun-thai-500-normal-BVssjame.woff2 +0 -0
  573. package/out/web/assets/sarabun-thai-500-normal-C3iDLEzi.woff +0 -0
  574. package/out/web/assets/sarabun-thai-600-normal-3dIAQ-_s.woff2 +0 -0
  575. package/out/web/assets/sarabun-thai-600-normal-DWKeTe6a.woff +0 -0
  576. package/out/web/assets/sarabun-vietnamese-400-normal-DPfkSCMy.woff +0 -0
  577. package/out/web/assets/sarabun-vietnamese-400-normal-igdrzAGY.woff2 +0 -0
  578. package/out/web/assets/sarabun-vietnamese-500-normal-CpRVvGRU.woff +0 -0
  579. package/out/web/assets/sarabun-vietnamese-500-normal-Dpe7Br9m.woff2 +0 -0
  580. package/out/web/assets/sarabun-vietnamese-600-normal-BMbOgAW-.woff +0 -0
  581. package/out/web/assets/sarabun-vietnamese-600-normal-DkxrOlLB.woff2 +0 -0
  582. package/out/web/assets/stateDiagram-v2-4QOOHH4V-s6P9g2_b.js +0 -1
  583. package/out/web/assets/swimlanesDiagram-VK2B7HYN-CV9fOLrV.js +0 -8
  584. package/out/web/assets/tauri-CNrHQ2Gb.js +0 -3
  585. package/out/web/assets/window-DkIhgI7B.js +0 -1
@@ -1,7 +1,7 @@
1
- import React, { useState, useEffect } from 'react'
1
+ import React, { useState, useEffect, useRef } from 'react'
2
2
  import { renderLinkedFoldersSvgIcon, renderFolderIcon } from '../constants/plugins'
3
3
  import '../css/management-views.css'
4
- import type { LinkedFolder, LinkedFolderDraft } from '../types'
4
+ import type { LinkedFolder, LinkedFolderDraft, LinkedFolderNote, LinkedFolderStatus } from '../types'
5
5
 
6
6
  export type { LinkedFolder }
7
7
 
@@ -9,6 +9,12 @@ export interface LinkedFoldersViewProps {
9
9
  listLinkedFolders: () => Promise<Record<string, LinkedFolder>>
10
10
  addLinkedFolder: (draft: LinkedFolderDraft) => Promise<any>
11
11
  removeLinkedFolder: (name: string) => Promise<any>
12
+ linkedFolderStatus: (name: string) => Promise<LinkedFolderStatus>
13
+ refreshLinkedFolder: (name: string) => Promise<LinkedFolderStatus>
14
+ listLinkedFolderNotes: (name: string) => Promise<LinkedFolderNote[]>
15
+ readLinkedFolderNote: (name: string, id: string) => Promise<string>
16
+ openLinkedFolderNote: (name: string, id: string) => Promise<void>
17
+ canOpenNote: boolean
12
18
  /** Opens a native folder picker and resolves the chosen path, or null if
13
19
  * cancelled. Only passed in on the desktop app — browsers can't expose a
14
20
  * real filesystem path from a folder picker, so omitting this prop hides
@@ -17,7 +23,7 @@ export interface LinkedFoldersViewProps {
17
23
  }
18
24
 
19
25
  export const LinkedFoldersView: React.FC<LinkedFoldersViewProps> = React.memo(
20
- function LinkedFoldersView({ listLinkedFolders, addLinkedFolder, removeLinkedFolder, selectFolder }) {
26
+ function LinkedFoldersView({ listLinkedFolders, addLinkedFolder, removeLinkedFolder, linkedFolderStatus, refreshLinkedFolder, listLinkedFolderNotes, readLinkedFolderNote, openLinkedFolderNote, canOpenNote, selectFolder }) {
21
27
  const [folders, setFolders] = useState<LinkedFolder[]>([])
22
28
  const [loading, setLoading] = useState(false)
23
29
  const [error, setError] = useState('')
@@ -28,7 +34,27 @@ export const LinkedFoldersView: React.FC<LinkedFoldersViewProps> = React.memo(
28
34
  const [newDescription, setNewDescription] = useState('')
29
35
  const [adding, setAdding] = useState(false)
30
36
  const [showAddModal, setShowAddModal] = useState(false)
37
+ const [formErrors, setFormErrors] = useState<{ name?: string; path?: string; form?: string }>({})
38
+ const [nameFromPicker, setNameFromPicker] = useState(false)
39
+ const nameInputRef = useRef<HTMLInputElement>(null)
40
+ const addOpenerRef = useRef<HTMLElement | null>(null)
41
+ const addDialogRef = useRef<HTMLDivElement>(null)
42
+ const detailOpenerRef = useRef<HTMLElement | null>(null)
43
+ const detailCloseRef = useRef<HTMLButtonElement>(null)
44
+ const detailDialogRef = useRef<HTMLDivElement>(null)
31
45
  const [detailFolder, setDetailFolder] = useState<LinkedFolder | null>(null)
46
+ const [status, setStatus] = useState<LinkedFolderStatus | null>(null)
47
+ const [notes, setNotes] = useState<LinkedFolderNote[]>([])
48
+ const [preview, setPreview] = useState('')
49
+ const [previewNoteId, setPreviewNoteId] = useState<string | null>(null)
50
+ const [previewLoading, setPreviewLoading] = useState(false)
51
+ const previewRequestRef = useRef(0)
52
+ const [detailError, setDetailError] = useState('')
53
+ const [refreshing, setRefreshing] = useState(false)
54
+ const [rowRefreshing, setRowRefreshing] = useState<string | null>(null)
55
+ const [folderStatuses, setFolderStatuses] = useState<Record<string, LinkedFolderStatus>>({})
56
+ const [folderNotes, setFolderNotes] = useState<Record<string, LinkedFolderNote[]>>({})
57
+ const [folderErrors, setFolderErrors] = useState<Record<string, string>>({})
32
58
 
33
59
  const fetchFolders = async () => {
34
60
  setLoading(true)
@@ -48,9 +74,194 @@ export const LinkedFoldersView: React.FC<LinkedFoldersViewProps> = React.memo(
48
74
  fetchFolders()
49
75
  }, [])
50
76
 
77
+ const folderKey = folders.map((folder) => `${folder.name}\u0000${folder.path}`).join('\u0001')
78
+
79
+ const keepTabInDialog = (event: KeyboardEvent, dialog: HTMLDivElement | null) => {
80
+ if (event.key !== 'Tab' || !dialog) return
81
+ const controls = Array.from(dialog.querySelectorAll<HTMLElement>('button:not(:disabled), input:not(:disabled), textarea:not(:disabled), [tabindex]:not([tabindex="-1"])'))
82
+ if (controls.length === 0) return
83
+ const first = controls[0]
84
+ const last = controls[controls.length - 1]
85
+ if (event.shiftKey && (document.activeElement === first || !dialog.contains(document.activeElement))) {
86
+ event.preventDefault()
87
+ last.focus()
88
+ } else if (!event.shiftKey && (document.activeElement === last || !dialog.contains(document.activeElement))) {
89
+ event.preventDefault()
90
+ first.focus()
91
+ }
92
+ }
93
+
94
+ useEffect(() => {
95
+ if (folders.length === 0) return
96
+ let active = true
97
+ let busy = false
98
+ const loadSummaries = async () => {
99
+ if (busy) return
100
+ busy = true
101
+ try {
102
+ const results = await Promise.all(folders.map(async (folder) => {
103
+ const [statusResult, notesResult] = await Promise.allSettled([
104
+ linkedFolderStatus(folder.name), listLinkedFolderNotes(folder.name)
105
+ ])
106
+ return { name: folder.name, statusResult, notesResult }
107
+ }))
108
+ if (!active) return
109
+ const nextStatuses: Record<string, LinkedFolderStatus> = {}
110
+ const nextNotes: Record<string, LinkedFolderNote[]> = {}
111
+ const nextErrors: Record<string, string> = {}
112
+ for (const result of results) {
113
+ if (result.statusResult.status === 'fulfilled') nextStatuses[result.name] = result.statusResult.value
114
+ else nextErrors[result.name] = 'Could not load folder status'
115
+ if (result.notesResult.status === 'fulfilled') nextNotes[result.name] = result.notesResult.value
116
+ else nextErrors[result.name] = 'Could not load recent notes'
117
+ }
118
+ setFolderStatuses(nextStatuses)
119
+ setFolderNotes(nextNotes)
120
+ setFolderErrors(nextErrors)
121
+ } finally {
122
+ busy = false
123
+ }
124
+ }
125
+ void loadSummaries()
126
+ const timer = window.setInterval(loadSummaries, 15000)
127
+ return () => { active = false; window.clearInterval(timer) }
128
+ }, [folderKey, linkedFolderStatus, listLinkedFolderNotes])
129
+
130
+ useEffect(() => {
131
+ if (!showAddModal) return
132
+ nameInputRef.current?.focus()
133
+ }, [showAddModal])
134
+
135
+ useEffect(() => {
136
+ if (!showAddModal) return
137
+ const onKeyDown = (event: KeyboardEvent) => {
138
+ if (event.key === 'Escape' && !adding) closeAddModal()
139
+ keepTabInDialog(event, addDialogRef.current)
140
+ }
141
+ window.addEventListener('keydown', onKeyDown)
142
+ return () => window.removeEventListener('keydown', onKeyDown)
143
+ }, [showAddModal, adding])
144
+
145
+ const openAddModal = () => {
146
+ addOpenerRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null
147
+ setFormErrors({})
148
+ setShowAddModal(true)
149
+ }
150
+
151
+ const closeAddModal = () => {
152
+ setShowAddModal(false)
153
+ setFormErrors({})
154
+ window.requestAnimationFrame(() => addOpenerRef.current?.focus())
155
+ }
156
+
157
+ const openDetailModal = (folder: LinkedFolder) => {
158
+ detailOpenerRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null
159
+ setDetailError('')
160
+ setDetailFolder(folder)
161
+ }
162
+
163
+ const closeDetailModal = () => {
164
+ setDetailFolder(null)
165
+ window.requestAnimationFrame(() => detailOpenerRef.current?.focus())
166
+ }
167
+
168
+ useEffect(() => {
169
+ if (!detailFolder) return
170
+ detailCloseRef.current?.focus()
171
+ const onKeyDown = (event: KeyboardEvent) => {
172
+ if (event.key === 'Escape') closeDetailModal()
173
+ keepTabInDialog(event, detailDialogRef.current)
174
+ }
175
+ window.addEventListener('keydown', onKeyDown)
176
+ return () => window.removeEventListener('keydown', onKeyDown)
177
+ }, [detailFolder?.name])
178
+
179
+ useEffect(() => {
180
+ if (!detailFolder) return
181
+ setStatus(null)
182
+ setNotes([])
183
+ setPreview('')
184
+ setPreviewNoteId(null)
185
+ setPreviewLoading(false)
186
+ previewRequestRef.current += 1
187
+ let active = true
188
+ const load = async () => {
189
+ try {
190
+ const [nextStatus, nextNotes] = await Promise.all([
191
+ linkedFolderStatus(detailFolder.name), listLinkedFolderNotes(detailFolder.name)
192
+ ])
193
+ if (active) { setStatus(nextStatus); setNotes(nextNotes); setDetailError('') }
194
+ } catch (err: any) {
195
+ if (active) setDetailError(err?.message || 'Failed to load linked folder details')
196
+ }
197
+ }
198
+ void load()
199
+ const timer = window.setInterval(load, 10000)
200
+ return () => { active = false; window.clearInterval(timer) }
201
+ }, [detailFolder?.name, linkedFolderStatus, listLinkedFolderNotes])
202
+
203
+ const handleRefresh = async () => {
204
+ if (!detailFolder) return
205
+ setRefreshing(true)
206
+ try {
207
+ const nextStatus = await refreshLinkedFolder(detailFolder.name)
208
+ setStatus(nextStatus)
209
+ setFolderStatuses((current) => ({ ...current, [detailFolder.name]: nextStatus }))
210
+ setDetailError('')
211
+ }
212
+ catch (err: any) { setDetailError(err?.message || 'Could not refresh folder') }
213
+ finally { setRefreshing(false) }
214
+ }
215
+
216
+ const handlePreview = async (note: LinkedFolderNote) => {
217
+ if (previewNoteId === note.id) {
218
+ previewRequestRef.current += 1
219
+ setPreviewNoteId(null)
220
+ setPreview('')
221
+ setPreviewLoading(false)
222
+ return
223
+ }
224
+ const request = ++previewRequestRef.current
225
+ setPreviewNoteId(note.id)
226
+ setPreview('')
227
+ setPreviewLoading(true)
228
+ try {
229
+ const content = await readLinkedFolderNote(note.folder, note.id)
230
+ if (request === previewRequestRef.current) { setPreview(content); setDetailError('') }
231
+ } catch (err: any) {
232
+ if (request === previewRequestRef.current) setDetailError(err?.message || 'Could not read note')
233
+ } finally {
234
+ if (request === previewRequestRef.current) setPreviewLoading(false)
235
+ }
236
+ }
237
+
238
+ const handleCopyPath = async (path: string) => {
239
+ try {
240
+ if (navigator.clipboard?.writeText) {
241
+ await navigator.clipboard.writeText(path)
242
+ } else {
243
+ const input = document.createElement('textarea')
244
+ input.value = path
245
+ input.style.position = 'fixed'
246
+ input.style.opacity = '0'
247
+ document.body.appendChild(input)
248
+ input.select()
249
+ const copied = document.execCommand('copy')
250
+ input.remove()
251
+ if (!copied) throw new Error('Could not copy path')
252
+ }
253
+ setDetailError('')
254
+ } catch (err: any) { setDetailError(err?.message || 'Could not copy path') }
255
+ }
256
+
51
257
  const handleAddFolder = async (e: React.FormEvent) => {
52
258
  e.preventDefault()
53
- if (!newName.trim() || !newPath.trim()) return
259
+ const errors: typeof formErrors = {}
260
+ if (!newName.trim()) errors.name = 'Enter a name for this folder.'
261
+ else if (folders.some((folder) => folder.name === newName.trim())) errors.name = 'This name is already linked. Choose another name.'
262
+ if (!newPath.trim()) errors.path = 'Choose or enter a folder path.'
263
+ if (Object.keys(errors).length) { setFormErrors(errors); return }
264
+ setFormErrors({})
54
265
  setAdding(true)
55
266
  try {
56
267
  await addLinkedFolder({
@@ -61,11 +272,12 @@ export const LinkedFoldersView: React.FC<LinkedFoldersViewProps> = React.memo(
61
272
  setNewName('')
62
273
  setNewPath('')
63
274
  setNewDescription('')
64
- setShowAddModal(false)
65
- fetchFolders()
275
+ setNameFromPicker(false)
276
+ closeAddModal()
277
+ await fetchFolders()
66
278
  } catch (err: any) {
67
279
  console.error('Failed to add linked folder:', err)
68
- alert(err?.message || 'Error linking folder. Check the path is allowed and exists.')
280
+ setFormErrors({ form: err?.message || 'Could not link folder. Check that the path exists and Mint can access it.' })
69
281
  } finally {
70
282
  setAdding(false)
71
283
  }
@@ -75,9 +287,32 @@ export const LinkedFoldersView: React.FC<LinkedFoldersViewProps> = React.memo(
75
287
  if (!selectFolder) return
76
288
  try {
77
289
  const picked = await selectFolder()
78
- if (picked) setNewPath(picked)
290
+ if (picked) {
291
+ setNewPath(picked)
292
+ setFormErrors((current) => ({ ...current, path: undefined, form: undefined }))
293
+ if (!newName.trim() || nameFromPicker) {
294
+ const basename = picked.replace(/[\\/]+$/, '').split(/[\\/]/).pop() || ''
295
+ setNewName(basename)
296
+ setNameFromPicker(true)
297
+ setFormErrors((current) => ({ ...current, name: undefined }))
298
+ }
299
+ }
79
300
  } catch (err: any) {
80
301
  console.error('Failed to open folder picker:', err)
302
+ setFormErrors((current) => ({ ...current, path: err?.message || 'Could not open folder picker.' }))
303
+ }
304
+ }
305
+
306
+ const handleRowRefresh = async (name: string) => {
307
+ setRowRefreshing(name)
308
+ try {
309
+ const nextStatus = await refreshLinkedFolder(name)
310
+ setFolderStatuses((current) => ({ ...current, [name]: nextStatus }))
311
+ setFolderErrors((current) => ({ ...current, [name]: '' }))
312
+ } catch (err: any) {
313
+ setFolderErrors((current) => ({ ...current, [name]: err?.message || 'Could not refresh folder.' }))
314
+ } finally {
315
+ setRowRefreshing(null)
81
316
  }
82
317
  }
83
318
 
@@ -85,7 +320,7 @@ export const LinkedFoldersView: React.FC<LinkedFoldersViewProps> = React.memo(
85
320
  if (!window.confirm(`Unlink folder "${name}"? (The folder and its notes are not deleted.)`)) return
86
321
  try {
87
322
  await removeLinkedFolder(name)
88
- setDetailFolder((current) => (current?.name === name ? null : current))
323
+ if (detailFolder?.name === name) closeDetailModal()
89
324
  fetchFolders()
90
325
  } catch (err: any) {
91
326
  console.error('Failed to remove linked folder:', err)
@@ -110,13 +345,13 @@ export const LinkedFoldersView: React.FC<LinkedFoldersViewProps> = React.memo(
110
345
  <span className="management-title-icon" style={{ display: 'inline-flex', alignItems: 'center' }}>
111
346
  {renderLinkedFoldersSvgIcon(22, 'var(--accent)')}
112
347
  </span>
113
- Linked Folders
348
+ Linked folders
114
349
  </h1>
115
350
  <p className="management-subtitle">
116
- Mint drops a note into <code>mint-notes/</code> when a chat matches a linked folder's topic.
351
+ Mint reads linked folder files to find relevant chats and saves useful notes into <code>mint-notes/</code>.
117
352
  </p>
118
353
  </div>
119
- <button type="button" className="management-primary-btn" onClick={() => setShowAddModal(true)}>
354
+ <button type="button" className="management-primary-btn" onClick={openAddModal}>
120
355
  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
121
356
  <line x1="12" y1="5" x2="12" y2="19" />
122
357
  <line x1="5" y1="12" x2="19" y2="12" />
@@ -125,11 +360,12 @@ export const LinkedFoldersView: React.FC<LinkedFoldersViewProps> = React.memo(
125
360
  </button>
126
361
  </div>
127
362
 
128
- <div className="management-control-bar">
363
+ {folders.length > 0 && <div className="management-control-bar">
129
364
  <div className="management-search-wrapper">
130
365
  <input
131
366
  type="text"
132
367
  className="management-search-input"
368
+ aria-label="Search linked folders"
133
369
  placeholder="Search linked folders..."
134
370
  value={searchQuery}
135
371
  onChange={(e) => setSearchQuery(e.target.value)}
@@ -147,47 +383,81 @@ export const LinkedFoldersView: React.FC<LinkedFoldersViewProps> = React.memo(
147
383
  <line x1="21" y1="21" x2="16.65" y2="16.65" />
148
384
  </svg>
149
385
  </div>
150
- </div>
386
+ </div>}
151
387
 
152
- {error && <div className="management-error-banner">{error}</div>}
388
+ {error && folders.length > 0 && <div className="management-error-banner" role="alert">{error}</div>}
153
389
 
154
390
  {loading ? (
155
391
  <div className="mgmt-empty">Loading…</div>
156
- ) : filteredFolders.length === 0 ? (
157
- <div className="mgmt-empty">
158
- <p>{searchQuery ? 'No linked folders match your search.' : 'No linked folders yet.'}</p>
159
- {!searchQuery && <p>Link one above, or run <code>mint link add</code> in chat.</p>}
392
+ ) : error && folders.length === 0 ? (
393
+ <div className="linked-load-error" role="alert">
394
+ <p>Could not load linked folders.</p>
395
+ <button type="button" className="management-action-btn" onClick={() => void fetchFolders()}>Try again</button>
160
396
  </div>
397
+ ) : folders.length === 0 ? (
398
+ <section className="linked-empty" aria-labelledby="linked-empty-title">
399
+ <div className="linked-empty-icon" aria-hidden="true">{renderLinkedFoldersSvgIcon(30, 'var(--accent)')}</div>
400
+ <h2 id="linked-empty-title">Give a folder a place in your conversations</h2>
401
+ <p>Link a folder so Mint can use its supported files to find relevant context and save useful notes from your chats.</p>
402
+ <div className="linked-empty-steps" aria-label="How linked folders work">
403
+ <div><strong>1 · Choose a folder</strong><span>Mint reads supported files in it and its subfolders.</span></div>
404
+ <div><strong>2 · Chat as usual</strong><span>Mint uses relevant content when a conversation matches.</span></div>
405
+ <div><strong>3 · Find your notes</strong><span>Saved notes appear inside that folder’s <code>mint-notes/</code>.</span></div>
406
+ </div>
407
+ <button type="button" className="management-primary-btn" onClick={openAddModal}>Link a Folder</button>
408
+ <p className="linked-empty-cli">You can also run <code>mint link add</code> in your terminal.</p>
409
+ </section>
410
+ ) : filteredFolders.length === 0 ? (
411
+ <div className="mgmt-empty">No linked folders match your search.</div>
161
412
  ) : (
162
- <div className="mgmt-list">
163
- {filteredFolders.map((folder) => (
164
- <div
165
- key={folder.name}
166
- className="mgmt-row"
167
- onClick={() => setDetailFolder(folder)}
168
- >
413
+ <div className="mgmt-list linked-folder-list">
414
+ {filteredFolders.map((folder) => {
415
+ const folderStatus = folderStatuses[folder.name]
416
+ const latestNote = folderNotes[folder.name]?.find((note) => note.status === 'saved')
417
+ const rowError = folderErrors[folder.name] || folderStatus?.indexError
418
+ const stateLabel = rowError ? 'Needs attention' : !folderStatus ? 'Checking…' : !folderStatus.indexedAt ? 'Reading files…' : 'Ready'
419
+ return <div key={folder.name} className="mgmt-row linked-folder-row">
169
420
  <div className="mgmt-row-main">
170
- <div className="mgmt-row-title">{folder.name}</div>
171
- <div className="mgmt-row-sub">{folder.path}</div>
421
+ <div className="linked-folder-heading">
422
+ <span className="mgmt-row-title">{folder.name}</span>
423
+ <span className={`mgmt-status ${rowError ? 'failed' : folderStatus?.indexedAt ? 'ok' : 'running'}`} role="status">{stateLabel}</span>
424
+ </div>
425
+ <div className="mgmt-row-sub" title={folder.path}>{folder.path}</div>
426
+ {folder.description && <div className="linked-folder-description">{folder.description}</div>}
427
+ <div className="linked-folder-meta">
428
+ <span>{folderStatus ? `${folderStatus.indexedFiles} files indexed` : 'Checking files…'}</span>
429
+ <span aria-hidden="true">·</span>
430
+ <span>{latestNote ? `Last note ${new Date(latestNote.createdAt).toLocaleString()}` : 'No notes yet'}</span>
431
+ </div>
432
+ {latestNote && <p className="linked-folder-note-snippet">{latestNote.content.slice(0, 180)}</p>}
433
+ {rowError && <p className="linked-folder-error" role="alert">{rowError}</p>}
434
+ </div>
435
+ <div className="linked-folder-actions">
436
+ <button type="button" className="management-action-btn" onClick={() => openDetailModal(folder)}>View notes</button>
437
+ <button type="button" className="management-action-btn" disabled={rowRefreshing === folder.name} onClick={() => void handleRowRefresh(folder.name)}>
438
+ {rowRefreshing === folder.name ? 'Refreshing…' : 'Refresh'}
439
+ </button>
172
440
  </div>
173
441
  </div>
174
- ))}
442
+ })}
175
443
  </div>
176
444
  )}
177
445
 
178
446
  {/* Folder Detail */}
179
447
  {detailFolder && (
180
- <div className="management-modal-overlay" onClick={() => setDetailFolder(null)}>
181
- <div className="management-modal" onClick={(e) => e.stopPropagation()}>
448
+ <div className="management-modal-overlay" onClick={closeDetailModal}>
449
+ <div ref={detailDialogRef} className="management-modal linked-detail-modal" role="dialog" aria-modal="true" aria-labelledby="linked-detail-title" onClick={(e) => e.stopPropagation()}>
182
450
  <div className="management-modal-header">
183
451
  <div className="management-card-title-group">
184
452
  {renderFolderIcon(44)}
185
- <h2 className="management-modal-title">{detailFolder.name}</h2>
453
+ <h2 id="linked-detail-title" className="management-modal-title">{detailFolder.name}</h2>
186
454
  </div>
187
455
  <button
188
456
  type="button"
189
457
  className="management-modal-close"
190
- onClick={() => setDetailFolder(null)}
458
+ ref={detailCloseRef}
459
+ aria-label="Close folder details"
460
+ onClick={closeDetailModal}
191
461
  >
192
462
  ✕
193
463
  </button>
@@ -202,7 +472,37 @@ export const LinkedFoldersView: React.FC<LinkedFoldersViewProps> = React.memo(
202
472
  <code>{detailFolder.path}</code>
203
473
  <span>Notes</span>
204
474
  <code>{detailFolder.path.replace(/\/$/, '')}/mint-notes/</code>
475
+ <span>Indexed files</span>
476
+ <span>{status ? status.indexedFiles : 'Indexing…'}</span>
477
+ <span>Last indexed</span>
478
+ <span>{status?.indexedAt ? new Date(status.indexedAt).toLocaleString() : 'Pending'}</span>
479
+ <span>Background notes (all folders)</span>
480
+ <span>{status ? `${status.pendingJobs} pending · ${status.failedJobs} failed` : 'Loading…'}</span>
205
481
  </div>
482
+ {status?.indexError && <p role="status" className="management-error-banner">{status.indexError}</p>}
483
+ {status?.lastJobError && <p role="status" className="management-error-banner">Last note error: {status.lastJobError}</p>}
484
+ {detailError && <p role="alert" className="management-error-banner">{detailError}</p>}
485
+ <button type="button" className="management-action-btn" onClick={handleRefresh} disabled={refreshing}>
486
+ {refreshing ? 'Refreshing…' : 'Refresh file index'}
487
+ </button>
488
+ <h3>Recent notes</h3>
489
+ {notes.length === 0 ? <p>No notes saved yet.</p> : (
490
+ <div className="mgmt-list">
491
+ {notes.map((note) => <div className="mgmt-row linked-note-row" key={note.id}>
492
+ <div className="mgmt-row-main">
493
+ <div className="mgmt-row-title">{new Date(note.createdAt).toLocaleString()} · {note.status}</div>
494
+ <div className="mgmt-row-sub">{note.content.slice(0, 160)}</div>
495
+ {note.error && <p role="status">{note.error}</p>}
496
+ <button type="button" className="management-action-btn" disabled={note.status !== 'saved'} aria-expanded={previewNoteId === note.id} onClick={() => void handlePreview(note)}>{previewNoteId === note.id ? 'Hide note' : 'View note'}</button>
497
+ {canOpenNote && <button type="button" className="management-action-btn" disabled={note.status !== 'saved'} onClick={() => void openLinkedFolderNote(note.folder, note.id).catch((err) => setDetailError(String(err)))}>Open file</button>}
498
+ <button type="button" className="management-action-btn" onClick={() => void handleCopyPath(note.path)}>Copy path</button>
499
+ {previewNoteId === note.id && <div className="linked-note-preview" role="region" aria-label={`Note file for ${new Date(note.createdAt).toLocaleString()}`}>
500
+ {previewLoading ? <p>Loading note…</p> : preview ? <pre>{preview}</pre> : <p>Could not show this note.</p>}
501
+ </div>}
502
+ </div>
503
+ </div>)}
504
+ </div>
505
+ )}
206
506
  </div>
207
507
 
208
508
  <div className="management-modal-footer">
@@ -221,39 +521,53 @@ export const LinkedFoldersView: React.FC<LinkedFoldersViewProps> = React.memo(
221
521
 
222
522
  {showAddModal && (
223
523
  <div className="management-modal-overlay">
224
- <div className="management-modal">
524
+ <div ref={addDialogRef} className="management-modal linked-add-modal" role="dialog" aria-modal="true" aria-labelledby="linked-add-title">
225
525
  <div className="management-modal-header">
226
- <h2 className="management-modal-title">Link a Folder</h2>
227
- <button type="button" className="management-modal-close" onClick={() => setShowAddModal(false)}>
526
+ <h2 id="linked-add-title" className="management-modal-title">Link a Folder</h2>
527
+ <button type="button" className="management-modal-close" aria-label="Close" disabled={adding} onClick={closeAddModal}>
228
528
  ✕
229
529
  </button>
230
530
  </div>
231
531
 
232
- <form onSubmit={handleAddFolder}>
532
+ <form onSubmit={handleAddFolder} noValidate>
233
533
  <div className="management-modal-body">
234
534
  <div className="management-form-group">
235
- <label className="management-label">Name</label>
535
+ <label className="management-label" htmlFor="linked-folder-name">Name</label>
236
536
  <input
537
+ ref={nameInputRef}
538
+ id="linked-folder-name"
237
539
  type="text"
238
540
  className="management-input-field"
239
541
  placeholder="e.g. Food"
240
542
  value={newName}
241
- onChange={(e) => setNewName(e.target.value)}
543
+ aria-invalid={Boolean(formErrors.name)}
544
+ aria-describedby={formErrors.name ? 'linked-name-error' : undefined}
545
+ onChange={(e) => {
546
+ setNewName(e.target.value)
547
+ setNameFromPicker(false)
548
+ setFormErrors((current) => ({ ...current, name: undefined, form: undefined }))
549
+ }}
242
550
  required
243
551
  />
552
+ {formErrors.name && <span id="linked-name-error" className="linked-field-error" role="alert">{formErrors.name}</span>}
244
553
  </div>
245
554
 
246
555
  <div className="management-form-group">
247
- <label className="management-label">Folder path</label>
248
- <div style={{ display: 'flex', gap: '8px' }}>
556
+ <label className="management-label" htmlFor="linked-folder-path">Folder path</label>
557
+ <div className="linked-path-row">
249
558
  <input
559
+ id="linked-folder-path"
250
560
  type="text"
251
561
  className="management-input-field"
252
562
  placeholder="~/notes/food"
253
563
  value={newPath}
254
- onChange={(e) => setNewPath(e.target.value)}
564
+ aria-invalid={Boolean(formErrors.path)}
565
+ aria-describedby={formErrors.path ? 'linked-path-error' : undefined}
566
+ onChange={(e) => {
567
+ setNewPath(e.target.value)
568
+ setFormErrors((current) => ({ ...current, path: undefined, form: undefined }))
569
+ }}
255
570
  required
256
- style={{ flex: 1 }}
257
571
  />
258
572
  {selectFolder && (
259
573
  <button type="button" className="management-action-btn" onClick={handleBrowse}>
@@ -261,22 +575,27 @@ export const LinkedFoldersView: React.FC<LinkedFoldersViewProps> = React.memo(
261
575
  </button>
262
576
  )}
263
577
  </div>
578
+ {formErrors.path && <span id="linked-path-error" className="linked-field-error" role="alert">{formErrors.path}</span>}
264
579
  </div>
265
580
 
266
581
  <div className="management-form-group">
267
- <label className="management-label">Description (helps topic matching)</label>
582
+ <label className="management-label" htmlFor="linked-folder-description">What should Mint remember here? <span className="linked-optional">Optional</span></label>
268
583
  <textarea
584
+ id="linked-folder-description"
269
585
  className="management-textarea-field"
270
- placeholder="restaurant reviews and recipes"
586
+ placeholder="e.g. Restaurant reviews, recipes, and places I want to try"
271
587
  value={newDescription}
272
588
  onChange={(e) => setNewDescription(e.target.value)}
273
589
  rows={3}
274
590
  />
591
+ <p className="linked-field-hint">Describe the topics that belong in this folder. Mint uses this when deciding where a chat note belongs.</p>
275
592
  </div>
593
+ <p className="linked-scope-note">Mint reads supported files in this folder and its subfolders (such as Markdown, PDF, Word, spreadsheets and code), then saves useful chat notes in <code>mint-notes/</code> inside the folder.</p>
594
+ {formErrors.form && <p className="management-error-banner" role="alert">{formErrors.form}</p>}
276
595
  </div>
277
596
 
278
597
  <div className="management-modal-footer">
279
- <button type="button" className="management-action-btn" onClick={() => setShowAddModal(false)}>
598
+ <button type="button" className="management-action-btn" disabled={adding} onClick={closeAddModal}>
280
599
  Cancel
281
600
  </button>
282
601
  <button type="submit" disabled={adding} className="management-primary-btn">
@@ -4,7 +4,7 @@ import { MCP_REGISTRY, type McpRegistryEntry } from '../constants/mcpRegistry'
4
4
  import { renderMcpSvgIcon } from '../constants/plugins'
5
5
 
6
6
  /**
7
- * The "pick a known MCP server" list shown in the MCP Catalog modal (and inline
7
+ * The "pick a known MCP server" list shown in the MCP catalog modal (and inline
8
8
  * above the Settings › Plugins Add form). Selecting an entry prompts for any
9
9
  * `argInputs` it declares, then calls `onPick` with the entry and those values;
10
10
  * the host fills the Add form's command / args / env state. Styled with the