@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
@@ -11,6 +11,7 @@ import {
11
11
  IMAGE_STUDIO_MODELS,
12
12
  IMAGE_GEN_PROVIDER_MODELS,
13
13
  VEO_STUDIO_MODELS,
14
+ getModelMetadata,
14
15
  } from '../../constants/models'
15
16
  import type {
16
17
  CustomProviderConfig,
@@ -20,6 +21,47 @@ import type {
20
21
  import { setActiveModel } from '../../utils/modelManager'
21
22
  import { providerLabel as aiProviderLabel } from '../../utils/providers'
22
23
  import ApiKeyInput from './ApiKeyInput'
24
+ import SearchableModelCombobox from './SearchableModelCombobox'
25
+ import anthropicLogo from '@lobehub/icons-static-svg/icons/anthropic.svg?url'
26
+ import deepseekLogo from '@lobehub/icons-static-svg/icons/deepseek-color.svg?url'
27
+ import geminiLogo from '@lobehub/icons-static-svg/icons/gemini-color.svg?url'
28
+ import huggingFaceLogo from '@lobehub/icons-static-svg/icons/huggingface-color.svg?url'
29
+ import lmStudioLogo from '@lobehub/icons-static-svg/icons/lmstudio.svg?url'
30
+ import ollamaLogo from '@lobehub/icons-static-svg/icons/ollama.svg?url'
31
+ import openAiLogo from '@lobehub/icons-static-svg/icons/openai.svg?url'
32
+ import openRouterLogo from '@lobehub/icons-static-svg/icons/openrouter-color.svg?url'
33
+
34
+ const settingsProviderLogos: Record<string, { src: string; color?: string }> = {
35
+ anthropic: { src: anthropicLogo, color: '#d97757' },
36
+ deepseek: { src: deepseekLogo },
37
+ gemini: { src: geminiLogo },
38
+ huggingface: { src: huggingFaceLogo },
39
+ local_openai: { src: lmStudioLogo, color: '#8b5cf6' },
40
+ ollama: { src: ollamaLogo, color: '#f3f4f6' },
41
+ openai: { src: openAiLogo, color: '#10a37f' },
42
+ openrouter: { src: openRouterLogo },
43
+ }
44
+
45
+ function SettingsProviderLogo({ provider }: { provider: string }) {
46
+ const logo = settingsProviderLogos[provider]
47
+ if (!logo) return null
48
+
49
+ if (logo.color) {
50
+ return (
51
+ <span
52
+ className="settings-provider-logo is-monochrome"
53
+ aria-hidden="true"
54
+ style={{
55
+ '--provider-brand-color': logo.color,
56
+ maskImage: `url("${logo.src}")`,
57
+ WebkitMaskImage: `url("${logo.src}")`,
58
+ } as React.CSSProperties}
59
+ />
60
+ )
61
+ }
62
+
63
+ return <img className="settings-provider-logo" src={logo.src} alt="" aria-hidden="true" />
64
+ }
23
65
 
24
66
  // One card per image-gen provider (mirrors the chat "Provider & Model"
25
67
  // cards): a model dropdown plus either its own API-key field, or a note
@@ -144,6 +186,7 @@ export default function GeneralTab({
144
186
  onSaveWithoutClosing
145
187
  }: GeneralTabProps) {
146
188
  const [savedProviderId, setSavedProviderId] = React.useState<string | null>(null)
189
+ const [providerLogoErrors, setProviderLogoErrors] = React.useState<Record<string, string>>({})
147
190
  const [openSections, setOpenSections] = React.useState<Record<string, boolean>>({
148
191
  ai_routing: true,
149
192
  search: false,
@@ -180,6 +223,42 @@ export default function GeneralTab({
180
223
  }
181
224
  }
182
225
 
226
+ const handleProviderLogoChange = (providerId: string, file?: File) => {
227
+ if (!file) return
228
+ const supportedTypes = ['image/png', 'image/jpeg', 'image/webp']
229
+ if (!supportedTypes.includes(file.type)) {
230
+ setProviderLogoErrors(prev => ({ ...prev, [providerId]: 'Choose a PNG, JPEG, or WebP image.' }))
231
+ return
232
+ }
233
+ if (file.size > 256 * 1024) {
234
+ setProviderLogoErrors(prev => ({ ...prev, [providerId]: 'The logo must be 256 KB or smaller.' }))
235
+ return
236
+ }
237
+
238
+ const reader = new FileReader()
239
+ reader.onload = () => {
240
+ if (typeof reader.result !== 'string') {
241
+ setProviderLogoErrors(prev => ({ ...prev, [providerId]: 'Could not read this image.' }))
242
+ return
243
+ }
244
+ const provider = (config.customProviders ?? []).find(item => item.id === providerId)
245
+ if (!provider) return
246
+ const updated = (config.customProviders ?? []).map(item =>
247
+ item.id === providerId ? { ...item, logoDataUrl: reader.result as string } : item
248
+ )
249
+ updateField('customProviders', updated)
250
+ setProviderLogoErrors(prev => {
251
+ const next = { ...prev }
252
+ delete next[providerId]
253
+ return next
254
+ })
255
+ }
256
+ reader.onerror = () => {
257
+ setProviderLogoErrors(prev => ({ ...prev, [providerId]: 'Could not read this image.' }))
258
+ }
259
+ reader.readAsDataURL(file)
260
+ }
261
+
183
262
  const renderCollapsibleSection = (
184
263
  key: string,
185
264
  kicker: string,
@@ -238,8 +317,8 @@ export default function GeneralTab({
238
317
  <div className="tab-pane active">
239
318
  {/* Accordion Quick Control Bar */}
240
319
  <div className="accordion-controls">
241
- <button type="button" onClick={() => setAllSections(true)}>Expand All</button>
242
- <button type="button" onClick={() => setAllSections(false)}>Collapse All</button>
320
+ <button type="button" onClick={() => setAllSections(true)}>Expand all</button>
321
+ <button type="button" onClick={() => setAllSections(false)}>Collapse all</button>
243
322
  </div>
244
323
 
245
324
  {/* ── Section 1: AI Routing ── */}
@@ -251,8 +330,8 @@ export default function GeneralTab({
251
330
  <>
252
331
  <div className="form-grid compact">
253
332
  <div className="setting-row stacked">
254
- <label>Active Provider</label>
255
- <div className="pill-segmented" role="radiogroup" aria-label="Active Provider">
333
+ <label>Active provider</label>
334
+ <div className="pill-segmented" role="radiogroup" aria-label="Active provider">
256
335
  {[
257
336
  { id: 'gemini', label: aiProviderLabel('gemini'), title: 'Google Gemini (Cloud)' },
258
337
  { id: 'anthropic', label: aiProviderLabel('anthropic'), title: 'Anthropic Claude' },
@@ -289,7 +368,7 @@ export default function GeneralTab({
289
368
  const currentModel = (config.customModelSelections ?? {})[activeId] ?? cp.models[0]?.modelId ?? ''
290
369
  return (
291
370
  <div className="setting-row wide">
292
- <label>Active Model</label>
371
+ <label>Active model</label>
293
372
  <select
294
373
  value={currentModel}
295
374
  onChange={(e) => updateField('customModelSelections', {
@@ -413,10 +492,10 @@ export default function GeneralTab({
413
492
  }
414
493
 
415
494
  return (
416
- <div className="setting-row stacked" style={{ marginTop: '0.75rem', padding: '0.75rem', borderRadius: '8px', background: 'rgba(255, 255, 255, 0.03)', border: '1px solid rgba(255, 255, 255, 0.06)' }}>
495
+ <div className="setting-row stacked setting-feature-card">
417
496
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.35rem' }}>
418
497
  <label style={{ margin: 0, fontWeight: 600, display: 'flex', alignItems: 'baseline', gap: '0.45rem' }}>
419
- <span>Model Temperature</span>
498
+ <span>Model temperature</span>
420
499
  {modelDisplayName && (
421
500
  <span style={{ fontSize: '0.8rem', fontWeight: 500, color: 'var(--text-muted)' }}>
422
501
  · {modelDisplayName}
@@ -448,13 +527,13 @@ export default function GeneralTab({
448
527
  step="0.05"
449
528
  value={currentTemp}
450
529
  onChange={(e) => handleChange(parseFloat(e.target.value))}
451
- style={{ flex: 1, accentColor: 'var(--accent-color, #10b981)', cursor: 'pointer' }}
530
+ style={{ flex: 1, accentColor: 'var(--accent, #10b981)', cursor: 'pointer' }}
452
531
  />
453
532
  <span style={{ fontSize: '0.85rem', minWidth: '2.5rem', textAlign: 'right', fontFamily: 'monospace', fontWeight: 600 }}>
454
533
  {currentTemp.toFixed(2)}
455
534
  </span>
456
535
  </div>
457
- <span style={{ fontSize: '0.75rem', opacity: 0.75, marginTop: '0.35rem', lineHeight: 1.4 }}>
536
+ <span style={{ fontSize: '0.75rem', color: 'var(--text-muted)', marginTop: '0.35rem', lineHeight: 1.4 }}>
458
537
  Controls sampling entropy for <strong>{modelDisplayName || activeModelRaw}</strong>. {
459
538
  isReasoningOmit
460
539
  ? 'Reasoning models (o1/o3) automatically omit this parameter.'
@@ -468,6 +547,160 @@ export default function GeneralTab({
468
547
  </div>
469
548
  )
470
549
  })()}
550
+
551
+ {/* Thinking / Reasoning Configuration */}
552
+ {(() => {
553
+ const activeModelRaw = (() => {
554
+ if (config.aiProvider === 'gemini') return config.geminiModel || 'gemini-2.5-flash'
555
+ if (config.aiProvider === 'anthropic') return config.anthropicModel || 'claude-sonnet-5'
556
+ if (config.aiProvider === 'openai') return config.openaiModel || 'gpt-5.6-luna'
557
+ if (config.aiProvider === 'openrouter') return config.openrouterModel || 'openai/gpt-5.6-terra'
558
+ if (config.aiProvider === 'deepseek') return config.deepseekModel || 'deepseek-chat'
559
+ if (config.aiProvider === 'local_openai') return config.localModelName || 'local-model'
560
+ if (config.aiProvider === 'ollama') return config.ollamaModel || 'llama3'
561
+ if (config.aiProvider === 'huggingface') return config.hfModel || 'Qwen/Qwen3.6-27B'
562
+ return ''
563
+ })()
564
+
565
+ const meta = getModelMetadata(activeModelRaw, config.aiProvider)
566
+ const modelConfigs = (config.modelThinkingConfigs ?? {}) as Record<string, { enabled?: boolean; effort?: string }>
567
+ const customModelThinking = activeModelRaw ? modelConfigs[activeModelRaw] : undefined
568
+ const hasCustomModel = customModelThinking !== undefined
569
+
570
+ const isThinkingSupported = meta.supportsThinking
571
+ const currentEnabled = customModelThinking?.enabled !== undefined
572
+ ? customModelThinking.enabled
573
+ : (config.thinkingEnabled ?? true)
574
+
575
+ const currentEffort = (customModelThinking?.effort || config.thinkingEffort || 'medium').toLowerCase()
576
+
577
+ const handleResetThinking = () => {
578
+ if (activeModelRaw && modelConfigs[activeModelRaw] !== undefined) {
579
+ const updated = { ...modelConfigs }
580
+ delete updated[activeModelRaw]
581
+ updateField('modelThinkingConfigs', updated)
582
+ }
583
+ }
584
+
585
+ const handleToggleThinking = (enabled: boolean) => {
586
+ if (activeModelRaw) {
587
+ const updated = {
588
+ ...modelConfigs,
589
+ [activeModelRaw]: { enabled, effort: currentEffort },
590
+ }
591
+ updateField('modelThinkingConfigs', updated)
592
+ }
593
+ updateField('thinkingEnabled', enabled)
594
+ }
595
+
596
+ const handleEffortChange = (effort: string) => {
597
+ if (activeModelRaw) {
598
+ const updated = {
599
+ ...modelConfigs,
600
+ [activeModelRaw]: { enabled: currentEnabled, effort },
601
+ }
602
+ updateField('modelThinkingConfigs', updated)
603
+ }
604
+ updateField('thinkingEffort', effort)
605
+ }
606
+
607
+ const effortLabelMap: Record<string, string> = {
608
+ low: 'Low',
609
+ medium: 'Medium',
610
+ high: 'High',
611
+ extra_high: 'Extra High',
612
+ }
613
+
614
+ return (
615
+ <div className="setting-row stacked setting-feature-card">
616
+ <div className="thinking-card-header" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.5rem' }}>
617
+ <label className="thinking-card-title" style={{ margin: 0, fontWeight: 600, display: 'flex', alignItems: 'center', gap: '0.45rem' }}>
618
+ <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ color: 'var(--interactive-fg)' }}>
619
+ <path d="M12 2a7 7 0 0 1 7 7c0 2.38-1.19 4.47-3 5.74V17a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-2.26C6.19 13.47 5 11.38 5 9a7 7 0 0 1 7-7z" />
620
+ <path d="M9 21h6" />
621
+ </svg>
622
+ <span>Thinking / Reasoning</span>
623
+ {activeModelRaw && (
624
+ <span style={{ fontSize: '0.8rem', fontWeight: 500, color: 'var(--text-muted)' }}>
625
+ · {activeModelRaw.split('/').pop()}
626
+ </span>
627
+ )}
628
+ </label>
629
+ <div className="thinking-card-status" style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
630
+ <span className="section-current-badge" style={{ fontSize: '0.75rem' }}>
631
+ {currentEnabled
632
+ ? `Thinking ON (${effortLabelMap[currentEffort] || 'Medium'})${!isThinkingSupported ? ' · Force' : ''}`
633
+ : 'Thinking OFF'}
634
+ </span>
635
+ {hasCustomModel && (
636
+ <button
637
+ type="button"
638
+ className="btn-secondary btn-small"
639
+ style={{ padding: '0.15rem 0.45rem', fontSize: '0.75rem' }}
640
+ onClick={handleResetThinking}
641
+ title={`Reset ${activeModelRaw} thinking configuration`}
642
+ >
643
+ Reset
644
+ </button>
645
+ )}
646
+ </div>
647
+ </div>
648
+
649
+ {/* Toggle Row */}
650
+ <div className="thinking-card-toggle-row" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '0.4rem 0' }}>
651
+ <div>
652
+ <span style={{ fontSize: '0.82rem', fontWeight: 500 }}>Enable thinking</span>
653
+ <p style={{ margin: '2px 0 0 0', fontSize: '0.73rem', color: 'var(--text-muted)' }}>
654
+ {isThinkingSupported
655
+ ? 'Allow model to output chain-of-thought tokens.'
656
+ : currentEnabled
657
+ ? 'Chain-of-thought token generation enabled (force toggle).'
658
+ : 'Model not flagged as reasoning by default — toggle on to force enable.'}
659
+ </p>
660
+ </div>
661
+ <label className="settings-toggle-switch">
662
+ <input
663
+ type="checkbox"
664
+ checked={currentEnabled}
665
+ onChange={(e) => handleToggleThinking(e.target.checked)}
666
+ />
667
+ <span className="settings-toggle-slider"></span>
668
+ </label>
669
+ </div>
670
+
671
+ {/* Effort Level Row */}
672
+ {currentEnabled && (
673
+ <div style={{ marginTop: '0.5rem', paddingTop: '0.5rem', borderTop: '1px solid var(--border)' }}>
674
+ <div className="thinking-card-effort-row" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
675
+ <span style={{ fontSize: '0.78rem', fontWeight: 600, color: 'var(--text-muted)', textTransform: 'none', letterSpacing: '0.04em' }}>
676
+ Reasoning Effort
677
+ </span>
678
+ <div className="thinking-card-effort-options" style={{ display: 'flex', gap: '4px' }}>
679
+ {(['low', 'medium', 'high', 'extra_high'] as const).map((eff) => (
680
+ <button
681
+ key={eff}
682
+ type="button"
683
+ className={`btn-secondary btn-small ${currentEffort === eff ? 'active' : ''}`}
684
+ style={{
685
+ padding: '0.2rem 0.6rem',
686
+ fontSize: '0.75rem',
687
+ fontWeight: currentEffort === eff ? 600 : 400,
688
+ background: currentEffort === eff ? 'rgba(16, 185, 129, 0.15)' : undefined,
689
+ borderColor: currentEffort === eff ? 'var(--accent, #10b981)' : undefined,
690
+ color: currentEffort === eff ? 'var(--accent, #10b981)' : undefined,
691
+ }}
692
+ onClick={() => handleEffortChange(eff)}
693
+ >
694
+ {effortLabelMap[eff]}
695
+ </button>
696
+ ))}
697
+ </div>
698
+ </div>
699
+ </div>
700
+ )}
701
+ </div>
702
+ )
703
+ })()}
471
704
  </div>
472
705
 
473
706
  <div className="provider-cards-container">
@@ -475,9 +708,7 @@ export default function GeneralTab({
475
708
  <div className={`provider-card ${config.aiProvider === 'gemini' ? 'active-provider' : ''}`}>
476
709
  <div className="provider-card-header">
477
710
  <div className="provider-card-title">
478
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
479
- <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
480
- </svg>
711
+ <SettingsProviderLogo provider="gemini" />
481
712
  Google Gemini (Cloud)
482
713
  </div>
483
714
  <div className="provider-card-actions">
@@ -492,7 +723,7 @@ export default function GeneralTab({
492
723
  </div>
493
724
  <div className="provider-card-body">
494
725
  <div className="setting-row">
495
- <label>Gemini Model</label>
726
+ <label>Gemini model</label>
496
727
  <select
497
728
  value={dynamicGeminiModels.includes(config.geminiModel) ? config.geminiModel : 'custom'}
498
729
  onChange={(e) => updateField('geminiModel', e.target.value)}
@@ -505,7 +736,7 @@ export default function GeneralTab({
505
736
  </div>
506
737
  {(!dynamicGeminiModels.includes(config.geminiModel) || config.geminiModel === 'custom') && (
507
738
  <div className="setting-row">
508
- <label>Custom Gemini Model</label>
739
+ <label>Custom Gemini model</label>
509
740
  <input
510
741
  type="text"
511
742
  value={customGemini}
@@ -529,10 +760,7 @@ export default function GeneralTab({
529
760
  <div className={`provider-card ${config.aiProvider === 'anthropic' ? 'active-provider' : ''}`}>
530
761
  <div className="provider-card-header">
531
762
  <div className="provider-card-title">
532
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
533
- <path d="M4.5 16.5c-1.5 1.26-2.5 3.19-2.5 5.5h20c0-2.31-1-4.24-2.5-5.5"></path>
534
- <path d="M12 2L2 22h20L12 2z"></path>
535
- </svg>
763
+ <SettingsProviderLogo provider="anthropic" />
536
764
  Anthropic Claude
537
765
  </div>
538
766
  <div className="provider-card-actions">
@@ -547,7 +775,7 @@ export default function GeneralTab({
547
775
  </div>
548
776
  <div className="provider-card-body">
549
777
  <div className="setting-row">
550
- <label>Anthropic Model</label>
778
+ <label>Anthropic model</label>
551
779
  <select
552
780
  value={dynamicAnthropicModels.includes(config.anthropicModel) ? config.anthropicModel : 'custom'}
553
781
  onChange={(e) => updateField('anthropicModel', e.target.value)}
@@ -560,7 +788,7 @@ export default function GeneralTab({
560
788
  </div>
561
789
  {(!dynamicAnthropicModels.includes(config.anthropicModel) || config.anthropicModel === 'custom') && (
562
790
  <div className="setting-row">
563
- <label>Custom Anthropic Model</label>
791
+ <label>Custom Anthropic model</label>
564
792
  <input
565
793
  type="text"
566
794
  value={customAnthropic}
@@ -584,11 +812,7 @@ export default function GeneralTab({
584
812
  <div className={`provider-card ${config.aiProvider === 'openai' ? 'active-provider' : ''}`}>
585
813
  <div className="provider-card-header">
586
814
  <div className="provider-card-title">
587
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
588
- <circle cx="12" cy="12" r="10"></circle>
589
- <line x1="12" y1="2" x2="12" y2="22"></line>
590
- <path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path>
591
- </svg>
815
+ <SettingsProviderLogo provider="openai" />
592
816
  OpenAI
593
817
  </div>
594
818
  <div className="provider-card-actions">
@@ -616,7 +840,7 @@ export default function GeneralTab({
616
840
  </div>
617
841
  {(!dynamicOpenAIModels.includes(config.openaiModel) || config.openaiModel === 'custom') && (
618
842
  <div className="setting-row">
619
- <label>Custom OpenAI Model</label>
843
+ <label>Custom OpenAI model</label>
620
844
  <input
621
845
  type="text"
622
846
  value={customOpenAI}
@@ -640,13 +864,7 @@ export default function GeneralTab({
640
864
  <div className={`provider-card ${config.aiProvider === 'openrouter' ? 'active-provider' : ''}`}>
641
865
  <div className="provider-card-header">
642
866
  <div className="provider-card-title">
643
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
644
- <polyline points="16 3 21 3 21 8"></polyline>
645
- <line x1="4" y1="20" x2="21" y2="3"></line>
646
- <polyline points="21 16 21 21 16 21"></polyline>
647
- <line x1="15" y1="15" x2="21" y2="21"></line>
648
- <line x1="4" y1="4" x2="9" y2="9"></line>
649
- </svg>
867
+ <SettingsProviderLogo provider="openrouter" />
650
868
  OpenRouter
651
869
  </div>
652
870
  <div className="provider-card-actions">
@@ -662,19 +880,21 @@ export default function GeneralTab({
662
880
  <div className="provider-card-body">
663
881
  <div className="setting-row">
664
882
  <label>OpenRouter Model</label>
665
- <select
883
+ <SearchableModelCombobox
666
884
  value={dynamicOpenRouterModels.includes(config.openrouterModel) ? config.openrouterModel : 'custom'}
667
- onChange={(e) => updateField('openrouterModel', e.target.value)}
668
- >
669
- {dynamicOpenRouterModels.map(model => (
670
- <option key={model} value={model}>{model}</option>
671
- ))}
672
- <option value="custom">Custom...</option>
673
- </select>
885
+ models={dynamicOpenRouterModels}
886
+ onChange={(val) => updateField('openrouterModel', val)}
887
+ onCustomChange={(val) => {
888
+ setCustomOpenRouter(val)
889
+ updateField('openrouterModel', 'custom')
890
+ }}
891
+ customValue={customOpenRouter}
892
+ placeholder="Select or search OpenRouter model..."
893
+ />
674
894
  </div>
675
895
  {(!dynamicOpenRouterModels.includes(config.openrouterModel) || config.openrouterModel === 'custom') && (
676
896
  <div className="setting-row">
677
- <label>Custom OpenRouter Model</label>
897
+ <label>Custom OpenRouter model</label>
678
898
  <input
679
899
  type="text"
680
900
  value={customOpenRouter}
@@ -698,10 +918,7 @@ export default function GeneralTab({
698
918
  <div className={`provider-card ${config.aiProvider === 'deepseek' ? 'active-provider' : ''}`}>
699
919
  <div className="provider-card-header">
700
920
  <div className="provider-card-title">
701
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
702
- <circle cx="11" cy="11" r="8"></circle>
703
- <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
704
- </svg>
921
+ <SettingsProviderLogo provider="deepseek" />
705
922
  DeepSeek
706
923
  </div>
707
924
  <div className="provider-card-actions">
@@ -729,7 +946,7 @@ export default function GeneralTab({
729
946
  </div>
730
947
  {(!dynamicDeepSeekModels.includes(config.deepseekModel) || config.deepseekModel === 'custom') && (
731
948
  <div className="setting-row">
732
- <label>Custom DeepSeek Model</label>
949
+ <label>Custom DeepSeek model</label>
733
950
  <input
734
951
  type="text"
735
952
  value={customDeepSeek}
@@ -753,12 +970,7 @@ export default function GeneralTab({
753
970
  <div className={`provider-card ${config.aiProvider === 'huggingface' ? 'active-provider' : ''}`}>
754
971
  <div className="provider-card-header">
755
972
  <div className="provider-card-title">
756
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
757
- <circle cx="12" cy="12" r="10"></circle>
758
- <path d="M8 14s1.5 2 4 2 4-2 4-2"></path>
759
- <line x1="9" y1="9" x2="9.01" y2="9"></line>
760
- <line x1="15" y1="9" x2="15.01" y2="9"></line>
761
- </svg>
973
+ <SettingsProviderLogo provider="huggingface" />
762
974
  Hugging Face (Inference API)
763
975
  </div>
764
976
  <div className="provider-card-actions">
@@ -773,7 +985,7 @@ export default function GeneralTab({
773
985
  </div>
774
986
  <div className="provider-card-body">
775
987
  <div className="setting-row">
776
- <label>Hugging Face Model</label>
988
+ <label>Hugging Face model</label>
777
989
  <select
778
990
  value={(HF_MODELS as readonly string[]).includes(config.hfModel) ? config.hfModel : 'custom'}
779
991
  onChange={(e) => updateField('hfModel', e.target.value)}
@@ -786,7 +998,7 @@ export default function GeneralTab({
786
998
  </div>
787
999
  {(!(HF_MODELS as readonly string[]).includes(config.hfModel) || config.hfModel === 'custom') && (
788
1000
  <div className="setting-row">
789
- <label>Custom Hugging Face Model</label>
1001
+ <label>Custom Hugging Face model</label>
790
1002
  <input
791
1003
  type="text"
792
1004
  value={customHF}
@@ -796,11 +1008,11 @@ export default function GeneralTab({
796
1008
  </div>
797
1009
  )}
798
1010
  <div className="setting-row">
799
- <label>Hugging Face API Key</label>
1011
+ <label>Hugging Face API key</label>
800
1012
  <ApiKeyInput
801
1013
  value={config.hfApiKey}
802
1014
  onChange={(value) => updateField('hfApiKey', value)}
803
- placeholder="Enter Hugging Face API Key..."
1015
+ placeholder="Enter Hugging Face API key..."
804
1016
  />
805
1017
  </div>
806
1018
  </div>
@@ -810,11 +1022,7 @@ export default function GeneralTab({
810
1022
  <div className={`provider-card ${config.aiProvider === 'local_openai' ? 'active-provider' : ''}`}>
811
1023
  <div className="provider-card-header">
812
1024
  <div className="provider-card-title">
813
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
814
- <rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
815
- <line x1="8" y1="21" x2="16" y2="21"></line>
816
- <line x1="12" y1="17" x2="12" y2="21"></line>
817
- </svg>
1025
+ <SettingsProviderLogo provider="local_openai" />
818
1026
  LM Studio / Local OpenAI
819
1027
  </div>
820
1028
  <div className="provider-card-actions">
@@ -867,9 +1075,7 @@ export default function GeneralTab({
867
1075
  <div className={`provider-card ${config.aiProvider === 'ollama' ? 'active-provider' : ''}`}>
868
1076
  <div className="provider-card-header">
869
1077
  <div className="provider-card-title">
870
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
871
- <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
872
- </svg>
1078
+ <SettingsProviderLogo provider="ollama" />
873
1079
  Ollama (Local)
874
1080
  </div>
875
1081
  <div className="provider-card-actions">
@@ -884,7 +1090,7 @@ export default function GeneralTab({
884
1090
  </div>
885
1091
  <div className="provider-card-body">
886
1092
  <div className="setting-row">
887
- <label>Ollama Model</label>
1093
+ <label>Ollama model</label>
888
1094
  <select
889
1095
  value={dynamicOllamaModels.includes(config.ollamaModel) ? config.ollamaModel : 'custom'}
890
1096
  onChange={(e) => updateField('ollamaModel', e.target.value)}
@@ -900,7 +1106,7 @@ export default function GeneralTab({
900
1106
  </div>
901
1107
  {(!dynamicOllamaModels.includes(config.ollamaModel) || config.ollamaModel === 'custom') && (
902
1108
  <div className="setting-row">
903
- <label>Custom Ollama Model</label>
1109
+ <label>Custom Ollama model</label>
904
1110
  <input
905
1111
  type="text"
906
1112
  value={customOllama}
@@ -910,7 +1116,7 @@ export default function GeneralTab({
910
1116
  </div>
911
1117
  )}
912
1118
  <div className="setting-row">
913
- <label>Ollama Host</label>
1119
+ <label>Ollama host</label>
914
1120
  <input
915
1121
  type="text"
916
1122
  value={config.ollamaHost}
@@ -953,11 +1159,11 @@ export default function GeneralTab({
953
1159
  </div>
954
1160
  <div className="provider-card-body">
955
1161
  <div className="setting-row">
956
- <label>Brave Search API Key</label>
1162
+ <label>Brave Search API key</label>
957
1163
  <ApiKeyInput
958
1164
  value={config.braveSearchApiKey}
959
1165
  onChange={(value) => updateField('braveSearchApiKey', value)}
960
- placeholder="Enter Brave Search API Key..."
1166
+ placeholder="Enter Brave Search API key..."
961
1167
  />
962
1168
  </div>
963
1169
  </div>
@@ -985,15 +1191,15 @@ export default function GeneralTab({
985
1191
  </div>
986
1192
  <div className="provider-card-body">
987
1193
  <div className="setting-row">
988
- <label>Google Search API Key</label>
1194
+ <label>Google Search API key</label>
989
1195
  <ApiKeyInput
990
1196
  value={config.googleSearchApiKey}
991
1197
  onChange={(value) => updateField('googleSearchApiKey', value)}
992
- placeholder="Enter Google Search API Key..."
1198
+ placeholder="Enter Google Search API key..."
993
1199
  />
994
1200
  </div>
995
1201
  <div className="setting-row">
996
- <label>Google Search Engine ID (CX)</label>
1202
+ <label>Google Search engine ID (CX)</label>
997
1203
  <input
998
1204
  type="text"
999
1205
  value={config.googleSearchCx}
@@ -1051,7 +1257,7 @@ export default function GeneralTab({
1051
1257
  <>
1052
1258
  <div className="form-grid compact">
1053
1259
  <div className="setting-row stacked">
1054
- <label>Active Provider</label>
1260
+ <label>Active provider</label>
1055
1261
  <div className="pill-segmented" role="radiogroup" aria-label="Image Provider">
1056
1262
  {IMAGE_PROVIDERS.map(o => (
1057
1263
  <button
@@ -1163,7 +1369,7 @@ export default function GeneralTab({
1163
1369
  <div className="provider-card-body">
1164
1370
  <p className="hint">Uses your Gemini API key — no extra key needed.</p>
1165
1371
  <div className="setting-row">
1166
- <label>Default Veo Model</label>
1372
+ <label>Default Veo model</label>
1167
1373
  {(() => {
1168
1374
  const veoOpts = dynamicVideoModels?.veo || VEO_STUDIO_MODELS.veo || []
1169
1375
  const currentVeoModel = config.veoModel || 'veo-3.1-generate-preview'
@@ -1243,9 +1449,13 @@ export default function GeneralTab({
1243
1449
  <div key={cpIdx} className={`provider-card ${isActive ? 'active-provider' : ''}`}>
1244
1450
  <div className="provider-card-header">
1245
1451
  <div className="provider-card-title">
1246
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
1247
- <circle cx="12" cy="12" r="3" /><path d="M19.07 4.93a10 10 0 0 1 0 14.14M4.93 4.93a10 10 0 0 0 0 14.14" />
1248
- </svg>
1452
+ {cp.logoDataUrl ? (
1453
+ <img className="settings-provider-logo custom-provider-logo" src={cp.logoDataUrl} alt="" />
1454
+ ) : (
1455
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
1456
+ <circle cx="12" cy="12" r="3" /><path d="M19.07 4.93a10 10 0 0 1 0 14.14M4.93 4.93a10 10 0 0 0 0 14.14" />
1457
+ </svg>
1458
+ )}
1249
1459
  {cp.displayName || cp.id || 'Unnamed Provider'}
1250
1460
  </div>
1251
1461
  <div className="provider-card-actions">
@@ -1296,6 +1506,50 @@ export default function GeneralTab({
1296
1506
  />
1297
1507
  </div>
1298
1508
 
1509
+ <div className="setting-row">
1510
+ <label>Provider logo (optional)</label>
1511
+ <div className="custom-provider-logo-picker">
1512
+ <div className="custom-provider-logo-preview" aria-hidden="true">
1513
+ {cp.logoDataUrl ? (
1514
+ <img src={cp.logoDataUrl} alt="" />
1515
+ ) : (
1516
+ <span>Logo</span>
1517
+ )}
1518
+ </div>
1519
+ <label className="btn btn-secondary btn-xs custom-provider-logo-select">
1520
+ {cp.logoDataUrl ? 'Change image' : 'Choose image'}
1521
+ <input
1522
+ type="file"
1523
+ accept="image/png,image/jpeg,image/webp"
1524
+ onChange={(event) => {
1525
+ handleProviderLogoChange(cp.id, event.currentTarget.files?.[0])
1526
+ event.currentTarget.value = ''
1527
+ }}
1528
+ />
1529
+ </label>
1530
+ {cp.logoDataUrl && (
1531
+ <button
1532
+ type="button"
1533
+ className="btn btn-secondary btn-xs"
1534
+ onClick={() => {
1535
+ updateCp({ logoDataUrl: undefined })
1536
+ setProviderLogoErrors(prev => {
1537
+ const next = { ...prev }
1538
+ delete next[cp.id]
1539
+ return next
1540
+ })
1541
+ }}
1542
+ >
1543
+ Remove
1544
+ </button>
1545
+ )}
1546
+ <span className="custom-provider-logo-help">PNG, JPEG, or WebP · max 256 KB</span>
1547
+ {providerLogoErrors[cp.id] && (
1548
+ <span className="custom-provider-logo-error" role="alert">{providerLogoErrors[cp.id]}</span>
1549
+ )}
1550
+ </div>
1551
+ </div>
1552
+
1299
1553
  <div className="setting-row">
1300
1554
  <label>Base URL</label>
1301
1555
  <input
@@ -1417,11 +1671,11 @@ export default function GeneralTab({
1417
1671
  </div>
1418
1672
  <div className="form-grid single">
1419
1673
  <div className="setting-row">
1420
- <label>Updater Endpoint</label>
1674
+ <label>Updater endpoint</label>
1421
1675
  <input type="text" value={config.updaterEndpoint} onChange={(e) => updateField('updaterEndpoint', e.target.value)} placeholder="https://updates.example.com/latest.json" />
1422
1676
  </div>
1423
1677
  <div className="setting-row">
1424
- <label>Updater Public Key</label>
1678
+ <label>Updater public key</label>
1425
1679
  <textarea value={config.updaterPublicKey} onChange={(e) => updateField('updaterPublicKey', e.target.value)} placeholder="Minisign public key" />
1426
1680
  </div>
1427
1681
  </div>
@@ -1442,7 +1696,7 @@ export default function GeneralTab({
1442
1696
  'Configure the mini AI character desktop presence widget.',
1443
1697
  <div className="toggle-row">
1444
1698
  <div>
1445
- <label>Show Desktop AI Candidate</label>
1699
+ <label>Show Desktop AI candidate</label>
1446
1700
  <p className="hint">Show the mini AI character on your desktop.</p>
1447
1701
  </div>
1448
1702
  <label className="settings-toggle-switch">