@pheem49/mint 1.14.0 → 1.16.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 (925) hide show
  1. package/Cargo.lock +1258 -35
  2. package/Cargo.toml +5 -2
  3. package/LICENSE +21 -654
  4. package/README.md +93 -756
  5. package/Release_Note.md +53 -446
  6. package/apps/mint-companion/src-tauri/Cargo.toml +20 -0
  7. package/apps/mint-companion/src-tauri/build.rs +3 -0
  8. package/apps/mint-companion/src-tauri/src/main.rs +468 -0
  9. package/apps/mint-companion/tsconfig.json +20 -0
  10. package/apps/mint-companion/vite.config.ts +3 -0
  11. package/components.json +19 -0
  12. package/crates/mint-cli/Cargo.toml +9 -1
  13. package/crates/mint-cli/src/agent/approval_prompts.rs +16 -3
  14. package/crates/mint-cli/src/agent/live_status.rs +545 -148
  15. package/crates/mint-cli/src/agent/markdown_render.rs +601 -61
  16. package/crates/mint-cli/src/agent.rs +723 -258
  17. package/crates/mint-cli/src/commands/agent.rs +83 -74
  18. package/crates/mint-cli/src/commands/eval.rs +9 -5
  19. package/crates/mint-cli/src/commands/git.rs +204 -0
  20. package/crates/mint-cli/src/commands/integrations.rs +35 -0
  21. package/crates/mint-cli/src/commands/knowledge.rs +13 -32
  22. package/crates/mint-cli/src/commands/mod.rs +81 -2
  23. package/crates/mint-cli/src/commands/tailnet_web.rs +235 -0
  24. package/crates/mint-cli/src/image.rs +32 -11
  25. package/crates/mint-cli/src/interactive/chat_tui.rs +7853 -0
  26. package/crates/mint-cli/src/interactive/command_ui.rs +477 -0
  27. package/crates/mint-cli/src/interactive/format.rs +8 -0
  28. package/crates/mint-cli/src/interactive/input_box.rs +94 -8
  29. package/crates/mint-cli/src/interactive/picker.rs +180 -37
  30. package/crates/mint-cli/src/interactive/resume_picker.rs +686 -0
  31. package/crates/mint-cli/src/interactive/slash_commands.rs +1071 -501
  32. package/crates/mint-cli/src/interactive/thought_viewer.rs +286 -0
  33. package/crates/mint-cli/src/interactive/tool_activity.rs +328 -0
  34. package/crates/mint-cli/src/interactive.rs +454 -166
  35. package/crates/mint-cli/src/main.rs +93 -26
  36. package/crates/mint-cli/src/markdown.rs +12 -5
  37. package/crates/mint-cli/src/mcp.rs +5 -0
  38. package/crates/mint-cli/src/mod_host.rs +6 -0
  39. package/crates/mint-cli/src/mods_cli.rs +62 -0
  40. package/crates/mint-cli/src/mods_ui.rs +187 -0
  41. package/crates/mint-cli/src/onboard.rs +37 -61
  42. package/crates/mint-cli/src/plugins_cli.rs +8 -5
  43. package/crates/mint-cli/src/setup.rs +10 -8
  44. package/crates/mint-cli/src/terminal_theme.rs +189 -0
  45. package/crates/mint-cli/src/updater.rs +112 -23
  46. package/crates/mint-cli/tests/library_intake.rs +77 -0
  47. package/crates/mint-cli/tests/mods_testing.rs +133 -0
  48. package/crates/mint-companion-protocol/Cargo.toml +10 -0
  49. package/crates/mint-companion-protocol/src/lib.rs +163 -0
  50. package/crates/mint-core/Cargo.toml +6 -3
  51. package/crates/mint-core/build.rs +26 -0
  52. package/crates/mint-core/src/agent/agent_loop.rs +1 -0
  53. package/crates/mint-core/src/agent/chat.rs +1003 -209
  54. package/crates/mint-core/src/agent/code_tools.rs +98 -2
  55. package/crates/mint-core/src/agent/memory/sources.rs +240 -0
  56. package/crates/mint-core/src/agent/memory.rs +805 -33
  57. package/crates/mint-core/src/agent/skill_inventory.rs +325 -0
  58. package/crates/mint-core/src/agent/skills.rs +437 -90
  59. package/crates/mint-core/src/agent.rs +1 -0
  60. package/crates/mint-core/src/api_server/routes/background_jobs.rs +310 -0
  61. package/crates/mint-core/src/api_server/routes/chat.rs +233 -190
  62. package/crates/mint-core/src/api_server/routes/html_preview.rs +77 -0
  63. package/crates/mint-core/src/api_server/routes/library.rs +97 -0
  64. package/crates/mint-core/src/api_server/routes/linked_folders.rs +118 -3
  65. package/crates/mint-core/src/api_server/routes/media_gen.rs +10 -57
  66. package/crates/mint-core/src/api_server/routes/misc.rs +114 -121
  67. package/crates/mint-core/src/api_server/routes/mod.rs +6 -0
  68. package/crates/mint-core/src/api_server/routes/mods.rs +31 -0
  69. package/crates/mint-core/src/api_server/routes/sessions.rs +85 -0
  70. package/crates/mint-core/src/api_server/routes/skills_subagents.rs +12 -42
  71. package/crates/mint-core/src/api_server/routes/slash.rs +50 -1
  72. package/crates/mint-core/src/api_server/routes/sources.rs +101 -0
  73. package/crates/mint-core/src/api_server.rs +140 -12
  74. package/crates/mint-core/src/avatar_bridge.rs +13 -2
  75. package/crates/mint-core/src/browser/cdp.rs +74 -83
  76. package/crates/mint-core/src/browser/evidence.rs +260 -0
  77. package/crates/mint-core/src/browser/input.rs +1 -1
  78. package/crates/mint-core/src/browser/interact.rs +98 -124
  79. package/crates/mint-core/src/browser/lifecycle.rs +75 -4
  80. package/crates/mint-core/src/browser/mod.rs +16 -2
  81. package/crates/mint-core/src/browser/navigate.rs +27 -19
  82. package/crates/mint-core/src/browser/observe.js +40 -0
  83. package/crates/mint-core/src/browser/session.rs +1610 -0
  84. package/crates/mint-core/src/companion.rs +716 -0
  85. package/crates/mint-core/src/cron/scheduler.rs +34 -2
  86. package/crates/mint-core/src/git/branches.rs +348 -0
  87. package/crates/mint-core/src/git/checkpoint.rs +40 -0
  88. package/crates/mint-core/src/git/diff.rs +206 -0
  89. package/crates/mint-core/src/git/mod.rs +10 -2
  90. package/crates/mint-core/src/integrations/channels.rs +88 -345
  91. package/crates/mint-core/src/integrations/mcp.rs +397 -50
  92. package/crates/mint-core/src/integrations/mcp_calls.rs +823 -0
  93. package/crates/mint-core/src/integrations/mcp_catalog.rs +267 -0
  94. package/crates/mint-core/src/integrations/mcp_device.rs +319 -0
  95. package/crates/mint-core/src/integrations/mcp_result.rs +356 -0
  96. package/crates/mint-core/src/integrations/webhooks.rs +539 -0
  97. package/crates/mint-core/src/integrations.rs +2 -0
  98. package/crates/mint-core/src/lib.rs +107 -40
  99. package/crates/mint-core/src/live_sync.rs +28 -9
  100. package/crates/mint-core/src/media/auto_shorts.rs +1 -0
  101. package/crates/mint-core/src/media/gemini_live.rs +145 -14
  102. package/crates/mint-core/src/media/image_models.rs +3 -27
  103. package/crates/mint-core/src/media/image_workflow.rs +216 -0
  104. package/crates/mint-core/src/media/library/intake.rs +144 -0
  105. package/crates/mint-core/src/media/library/migration.rs +56 -0
  106. package/crates/mint-core/src/media/library/removal.rs +55 -0
  107. package/crates/mint-core/src/media/library/tests.rs +730 -0
  108. package/crates/mint-core/src/media/library/thumbnails.rs +72 -0
  109. package/crates/mint-core/src/media/library.rs +545 -0
  110. package/crates/mint-core/src/media/mic_transcribe.rs +1 -0
  111. package/crates/mint-core/src/media/model_catalog.rs +375 -0
  112. package/crates/mint-core/src/media/pictures.rs +79 -222
  113. package/crates/mint-core/src/media/subtitle.rs +1 -0
  114. package/crates/mint-core/src/media/video_models.rs +3 -22
  115. package/crates/mint-core/src/media.rs +3 -0
  116. package/crates/mint-core/src/mods/manager.rs +1124 -0
  117. package/crates/mint-core/src/mods/mod.rs +569 -0
  118. package/crates/mint-core/src/mods/operations.rs +204 -0
  119. package/crates/mint-core/src/mods/session.rs +146 -0
  120. package/crates/mint-core/src/mods/slash.rs +59 -0
  121. package/crates/mint-core/src/mods/telemetry.rs +306 -0
  122. package/crates/mint-core/src/orchestration/approvals.rs +344 -0
  123. package/crates/mint-core/src/orchestration/context_render.rs +105 -0
  124. package/crates/mint-core/src/orchestration/mcp_review.rs +153 -0
  125. package/crates/mint-core/src/orchestration/memory_skill.rs +110 -33
  126. package/crates/mint-core/src/orchestration/mod.rs +3129 -481
  127. package/crates/mint-core/src/orchestration/mod_authoring_regressions.rs +209 -0
  128. package/crates/mint-core/src/orchestration/progress_clock.rs +80 -0
  129. package/crates/mint-core/src/orchestration/repeated_failures.rs +116 -0
  130. package/crates/mint-core/src/orchestration/review_regressions.rs +449 -0
  131. package/crates/mint-core/src/orchestration/run_control.rs +196 -0
  132. package/crates/mint-core/src/orchestration/tools/browser.rs +16 -139
  133. package/crates/mint-core/src/orchestration/tools/files.rs +161 -14
  134. package/crates/mint-core/src/orchestration/tools/media.rs +37 -41
  135. package/crates/mint-core/src/orchestration/tools/misc.rs +5 -3
  136. package/crates/mint-core/src/orchestration/tools/mod.rs +2 -0
  137. package/crates/mint-core/src/orchestration/tools/mods.rs +161 -0
  138. package/crates/mint-core/src/orchestration/tools/plugins_mcp.rs +303 -71
  139. package/crates/mint-core/src/orchestration/tools/shell.rs +95 -2
  140. package/crates/mint-core/src/orchestration/tools/web.rs +1 -1
  141. package/crates/mint-core/src/orchestration/workspace_helpers.rs +4 -1
  142. package/crates/mint-core/src/prompts/agent.rs +75 -31
  143. package/crates/mint-core/src/prompts/chat.rs +1 -1
  144. package/crates/mint-core/src/prompts/persona.rs +1 -1
  145. package/crates/mint-core/src/prompts/tool_catalog.rs +121 -27
  146. package/crates/mint-core/src/search/knowledge.rs +7 -1
  147. package/crates/mint-core/src/search/linked_folders/index.rs +896 -0
  148. package/crates/mint-core/src/search/linked_folders.rs +473 -131
  149. package/crates/mint-core/src/slash/catalog.rs +1 -1
  150. package/crates/mint-core/src/slash/mod.rs +644 -33
  151. package/crates/mint-core/src/slash/model_fetcher.rs +12 -3
  152. package/crates/mint-core/src/slash/models.rs +66 -10
  153. package/crates/mint-core/src/slash/mods.rs +155 -0
  154. package/crates/mint-core/src/system/bg_shell.rs +1129 -95
  155. package/crates/mint-core/src/system/config.rs +235 -10
  156. package/crates/mint-core/src/system/html_preview.rs +398 -0
  157. package/crates/mint-core/src/system/mint_web.rs +164 -0
  158. package/crates/mint-core/src/system/release_notes.rs +18 -0
  159. package/crates/mint-core/src/system/shell.rs +21 -6
  160. package/crates/mint-core/src/system/workspace.rs +292 -0
  161. package/crates/mint-core/src/system/workspace_history.rs +604 -0
  162. package/crates/mint-core/src/system.rs +5 -0
  163. package/crates/mint-core/tests/background_retention.rs +34 -0
  164. package/crates/mint-core/tests/background_shutdown.rs +24 -0
  165. package/crates/mint-core/tests/library_http.rs +209 -0
  166. package/crates/mint-core/tests/mcp_contract.rs +283 -0
  167. package/crates/mint-core/tests/mcp_stdio.rs +11 -10
  168. package/crates/mint-core/tests/media_model_catalog_http.rs +403 -0
  169. package/crates/mint-core/tests/memory_persistence.rs +39 -0
  170. package/crates/mint-core/tests/mods_http.rs +215 -0
  171. package/crates/mint-core/tests/terminal_shutdown.rs +109 -0
  172. package/crates/mint-mod-runtime/Cargo.toml +18 -0
  173. package/crates/mint-mod-runtime/src/lib.rs +507 -0
  174. package/crates/mint-mod-runtime/src/sdk.js +56 -0
  175. package/crates/mint-mod-runtime/src/test_sdk.js +32 -0
  176. package/crates/mint-mod-runtime/src/testing.rs +94 -0
  177. package/crates/mint-mod-runtime/tests/runtime.rs +156 -0
  178. package/docs/mods/AUTHORING.md +61 -0
  179. package/docs/mods/README.md +139 -0
  180. package/docs/mods/TESTING.md +56 -0
  181. package/docs/mods/mint-mods.d.ts +66 -0
  182. package/examples/device-mcp/README.md +22 -0
  183. package/examples/device-mcp/contract.md +49 -0
  184. package/examples/device-mcp/mock-device.mjs +66 -0
  185. package/examples/device-mcp/server.mjs +48 -0
  186. package/examples/device-mcp/server.test.mjs +78 -0
  187. package/examples/mods/task-checklist/README.md +1 -0
  188. package/examples/mods/task-checklist/main.ts +17 -0
  189. package/examples/mods/task-checklist/manifest.json +1 -0
  190. package/examples/mods/task-checklist/tests/checklist.test.ts +15 -0
  191. package/examples/mods/token-meter/README.md +1 -0
  192. package/examples/mods/token-meter/main.ts +8 -0
  193. package/examples/mods/token-meter/manifest.json +1 -0
  194. package/examples/mods/tool-guard/README.md +1 -0
  195. package/examples/mods/tool-guard/main.ts +9 -0
  196. package/examples/mods/tool-guard/manifest.json +1 -0
  197. package/out/web/assets/CliSessionsView-CtzUJpK_.css +1 -0
  198. package/out/web/assets/CliSessionsView-D7hw0Mgj.js +1 -0
  199. package/out/web/assets/CodeReviewPage-C7bEOJfd.js +4 -0
  200. package/out/web/assets/CodeReviewPage-Dte9uLiL.css +1 -0
  201. package/out/web/assets/CommandPalette-0RrF-AOT.js +1 -0
  202. package/out/web/assets/ImageStudioPanel-CdxkAf_r.js +1 -0
  203. package/out/web/assets/ImageStudioPanel-D0lnhQV5.css +1 -0
  204. package/out/web/assets/LibraryPage--Qfisp6D.js +2 -0
  205. package/out/web/assets/LibraryPage-DAxUTAg7.css +1 -0
  206. package/out/web/assets/LinkedFoldersView-2nfZbDgN.js +1 -0
  207. package/out/web/assets/McpRegistryPicker-h9uS8_wT.js +1 -0
  208. package/out/web/assets/McpServersView-slfQJzNB.js +1 -0
  209. package/out/web/assets/MintDashboard-BSR5XpXh.js +25 -0
  210. package/out/web/assets/MintDashboard-CWUcCGhd.css +1 -0
  211. package/out/web/assets/PluginsView-l7LSm503.js +1 -0
  212. package/out/web/assets/ScheduledTasksView-CttmLbq1.js +1 -0
  213. package/out/web/assets/SettingsWindow-BCMLYvEV.js +4 -0
  214. package/out/web/assets/SettingsWindow-DcMVmU9u.css +1 -0
  215. package/out/web/assets/SkillsView-rNs1qr_U.js +2 -0
  216. package/out/web/assets/ToolSurfacePage-B9DzEPWN.js +37 -0
  217. package/out/web/assets/ToolSurfacePage-CTfgggF2.css +1 -0
  218. package/out/web/assets/VeoStudioPanel-DOj7_WR3.css +1 -0
  219. package/out/web/assets/VeoStudioPanel-DiJs_Cg2.js +4 -0
  220. package/out/web/assets/WorkspacePanel-CbJ1PFoZ.js +1 -0
  221. package/out/web/assets/WorkspaceSelector-B2xIp04D.js +1 -0
  222. package/out/web/assets/WorkspaceSelector-Ca8uJOsS.css +1 -0
  223. package/out/web/assets/{abnfDiagram-VCTEODGH-DAOBA7ZG.js → abnfDiagram-VCTEODGH-CD0CjoGl.js} +1 -1
  224. package/out/web/assets/{architecture-7GRP2DOG-CgSwQOPQ.js → architecture-7GRP2DOG-RKV83OeZ.js} +1 -1
  225. package/out/web/assets/{architectureDiagram-5GKGNRK7-CYp3yupP.js → architectureDiagram-5GKGNRK7-nN_HAFct.js} +1 -1
  226. package/out/web/assets/{blockDiagram-NRAW4CY4-CyWybDWr.js → blockDiagram-NRAW4CY4-BrrqzHW5.js} +1 -1
  227. package/out/web/assets/{c4Diagram-UCG6FXSJ-BvY3U709.js → c4Diagram-UCG6FXSJ-DTdV8_zE.js} +1 -1
  228. package/out/web/assets/{chunk-75Z2AOVW-TLXCoZYv.js → chunk-75Z2AOVW-_M0z5olV.js} +1 -1
  229. package/out/web/assets/chunk-CKBBP62Z-BpQEgeHF.js +2 -0
  230. package/out/web/assets/{chunk-CLGD4ZFX-xjsKtNS7.js → chunk-CLGD4ZFX-D54yGvGS.js} +1 -1
  231. package/out/web/assets/chunk-DSNCTWBM-C-gvT2ru.js +2 -0
  232. package/out/web/assets/chunk-DU6HZSFF-CnFngIhW.js +128 -0
  233. package/out/web/assets/{chunk-F27PBJKO-BFpgF55A.js → chunk-F27PBJKO-BqtWrnEO.js} +1 -1
  234. package/out/web/assets/{chunk-G27WJ6UU-DfF7qW-C.js → chunk-G27WJ6UU-Ckoq5mi2.js} +1 -1
  235. package/out/web/assets/{chunk-GMAD6QVW-C-558kh_.js → chunk-GMAD6QVW-BuhEcgHq.js} +1 -1
  236. package/out/web/assets/{chunk-JQ64N6SF-wJmeGKAw.js → chunk-JQ64N6SF-CF8T7GiZ.js} +1 -1
  237. package/out/web/assets/{chunk-LCL6LL3I-C1wHD8Ie.js → chunk-LCL6LL3I-BhXV9zyH.js} +1 -1
  238. package/out/web/assets/{chunk-OBVCFTLP-BsRTPBqs.js → chunk-OBVCFTLP-CRIkunUB.js} +1 -1
  239. package/out/web/assets/{chunk-P2QGCYS3-HZIiM7Ni.js → chunk-P2QGCYS3-UFEU6BxZ.js} +1 -1
  240. package/out/web/assets/{chunk-POPQ4Y6H-Dk9wvVb0.js → chunk-POPQ4Y6H-CQcrNbjr.js} +1 -1
  241. package/out/web/assets/{chunk-PWAF6VOD-BmjYLNbq.js → chunk-PWAF6VOD-Cc2uVDsG.js} +1 -1
  242. package/out/web/assets/{chunk-R7TYR2AO-CaHIf-lK.js → chunk-R7TYR2AO-DiCxzdAY.js} +1 -1
  243. package/out/web/assets/{chunk-RHFEMEQ7-_T561hOU.js → chunk-RHFEMEQ7-b7hnPmrR.js} +1 -1
  244. package/out/web/assets/{chunk-SVP7TREG-CM-GGYoY.js → chunk-SVP7TREG-Bu_yYb-V.js} +1 -1
  245. package/out/web/assets/{chunk-TEH6E4GO-K2A8Vg2C.js → chunk-TEH6E4GO-G4Cdlyrt.js} +1 -1
  246. package/out/web/assets/classDiagram-DTDB5LWJ-RnC2mYO4.js +1 -0
  247. package/out/web/assets/classDiagram-v2-JRS7N3AN-RnC2mYO4.js +1 -0
  248. package/out/web/assets/config-CnvCChUM.js +2 -0
  249. package/out/web/assets/config-DM6oIVO3.css +1 -0
  250. package/out/web/assets/core-DsKkQ7ig.js +1 -0
  251. package/out/web/assets/{cynefin-OW5HDTMX-ClzaB6cc.js → cynefin-OW5HDTMX-CnzQfOGp.js} +1 -1
  252. package/out/web/assets/{cynefinDiagram-5FMLGOSQ-D_JzZBzf.js → cynefinDiagram-5FMLGOSQ-DVtQnfpm.js} +1 -1
  253. package/out/web/assets/{dagre-3AP2YEHR-BDuUeMHj.js → dagre-3AP2YEHR-DG76_k5_.js} +1 -1
  254. package/out/web/assets/{diagram-S7CK7UJ4-DgtcfE8P.js → diagram-S7CK7UJ4-CaouUoze.js} +1 -1
  255. package/out/web/assets/{diagram-UQ7AKVKN-DTLoEYti.js → diagram-UQ7AKVKN-B4bEc26B.js} +1 -1
  256. package/out/web/assets/{diagram-VSXAHHWV-ChGl9pXz.js → diagram-VSXAHHWV-BJ86Ov2Y.js} +1 -1
  257. package/out/web/assets/{diagram-VX7I27RA-Be8DWz0S.js → diagram-VX7I27RA-7hH5IPYf.js} +1 -1
  258. package/out/web/assets/{diagram-Z3DM3KII-BMXjRTOF.js → diagram-Z3DM3KII-CCM4clo8.js} +1 -1
  259. package/out/web/assets/dist-js-BkYNznHX.js +1 -0
  260. package/out/web/assets/{ebnfDiagram-PWID7BFC-8Q9pl1CJ.js → ebnfDiagram-PWID7BFC-Da7WAM3k.js} +1 -1
  261. package/out/web/assets/{erDiagram-SSCWMZ5O-DjH8Lnkn.js → erDiagram-SSCWMZ5O-CzzmnZWT.js} +1 -1
  262. package/out/web/assets/event-Cdt7Byyj.js +1 -0
  263. package/out/web/assets/{eventmodeling-NTZA5JFV-BKUH_DOp.js → eventmodeling-NTZA5JFV-xcfsA0XD.js} +1 -1
  264. package/out/web/assets/fira-code-latin-600-normal-BmSSHshu.woff +0 -0
  265. package/out/web/assets/fira-code-latin-600-normal-CvYZpPHg.woff2 +0 -0
  266. package/out/web/assets/fira-code-symbols2-600-normal-Dvq6IQE5.woff +0 -0
  267. package/out/web/assets/flowDiagram-A5DVABFB-JdtH1673.js +1 -0
  268. package/out/web/assets/{ganttDiagram-EL5Y4UJY-D7fZKJNM.js → ganttDiagram-EL5Y4UJY-B3ClFGmL.js} +1 -1
  269. package/out/web/assets/{gitGraph-4MIJSDKK-BypWaaBU.js → gitGraph-4MIJSDKK-BZ_y_cDU.js} +1 -1
  270. package/out/web/assets/{gitGraphDiagram-WWUBYQGX-DWiw_3bq.js → gitGraphDiagram-WWUBYQGX-drhRSYm3.js} +1 -1
  271. package/out/web/assets/index-BZ9xgmMP.css +1 -0
  272. package/out/web/assets/index-Ca8cCS4h.js +168 -0
  273. package/out/web/assets/{info-A6RAGUB7-KkAUxT4j.js → info-A6RAGUB7-B7I3K0F1.js} +1 -1
  274. package/out/web/assets/{infoDiagram-RXCK75RN-BNb6E48y.js → infoDiagram-RXCK75RN-deX_1MPh.js} +1 -1
  275. package/out/web/assets/{ishikawaDiagram-5VMMS53U-Caa-JoAK.js → ishikawaDiagram-5VMMS53U-s38yo28y.js} +1 -1
  276. package/out/web/assets/{journeyDiagram-EYS64GPL-DOrmFGz6.js → journeyDiagram-EYS64GPL-CZn2kB8b.js} +1 -1
  277. package/out/web/assets/jsx-runtime-DN4NhQUK.js +1 -0
  278. package/out/web/assets/{kanban-definition-3QL26DDD-BOWCYcK0.js → kanban-definition-3QL26DDD-DodjgySL.js} +1 -1
  279. package/out/web/assets/markdown-CMhYIcWB.js +39 -0
  280. package/out/web/assets/{mermaid-parser.core-BQqjCkS_.js → mermaid-parser.core-Whu2rlJC.js} +3 -3
  281. package/out/web/assets/mermaid.core-CKyPo8VH.js +11 -0
  282. package/out/web/assets/{mindmap-definition-FBJOCRG2-jTceWpr0.js → mindmap-definition-FBJOCRG2-260WBDxZ.js} +1 -1
  283. package/out/web/assets/modelManager-CUaGWMWu.js +2 -0
  284. package/out/web/assets/oauthManager-DlNhXJr6.js +1 -0
  285. package/out/web/assets/{packet-AYTQ26CC-CJ5RXgol.js → packet-AYTQ26CC-CEeIRKRG.js} +1 -1
  286. package/out/web/assets/{pegDiagram-XKGWAZYB-y8wMtd0y.js → pegDiagram-XKGWAZYB-BYadI-KO.js} +1 -1
  287. package/out/web/assets/{pie-WAS4IAKB-72fTBbl4.js → pie-WAS4IAKB-D8uf4dh5.js} +1 -1
  288. package/out/web/assets/{pieDiagram-E7YTZNPT-e0O02qWq.js → pieDiagram-E7YTZNPT-CjSDy4hO.js} +1 -1
  289. package/out/web/assets/{quadrantDiagram-AXDQQJYC-C9phYLom.js → quadrantDiagram-AXDQQJYC-B8D3gU5d.js} +1 -1
  290. package/out/web/assets/{radar-RG4KPBEZ-BAU2hzUT.js → radar-RG4KPBEZ-DZJxnokY.js} +1 -1
  291. package/out/web/assets/{railroad-74A4TZTK-B0bCAVHC.js → railroad-74A4TZTK-DBysUiUi.js} +1 -1
  292. package/out/web/assets/{railroad-abnf-HS5TGJTU-WhxO7ndE.js → railroad-abnf-HS5TGJTU-CHWxoJYg.js} +1 -1
  293. package/out/web/assets/{railroad-ebnf-LZEXJU2U-BkA0m7-F.js → railroad-ebnf-LZEXJU2U-DDv7X6bY.js} +1 -1
  294. package/out/web/assets/{railroad-peg-WCYAUIDC-BsVpHIaj.js → railroad-peg-WCYAUIDC-DpfcYYNJ.js} +1 -1
  295. package/out/web/assets/{railroadDiagram-O6MQD6OU-CyOLN65Q.js → railroadDiagram-O6MQD6OU-CYtyv0t3.js} +1 -1
  296. package/out/web/assets/{requirementDiagram-EFPCY7ZU-DQXJ7Dud.js → requirementDiagram-EFPCY7ZU-D2X-Ewik.js} +1 -1
  297. package/out/web/assets/{sankeyDiagram-P5KCCOFB-B2XLyIIc.js → sankeyDiagram-P5KCCOFB-Bn2x6C4Y.js} +1 -1
  298. package/out/web/assets/{sequenceDiagram-WJ2MYXX4-DGQY4wwm.js → sequenceDiagram-WJ2MYXX4-BvFLKtPd.js} +1 -1
  299. package/out/web/assets/{stateDiagram-HBIQ2CUA-DHZpDwNy.js → stateDiagram-HBIQ2CUA-Bx0GWeaY.js} +1 -1
  300. package/out/web/assets/stateDiagram-v2-4QOOHH4V--hol1yg_.js +1 -0
  301. package/out/web/assets/studio-B1mk40wD.js +1 -0
  302. package/out/web/assets/{swimlanes-XN3QIQJK-Bn_jcZz-.js → swimlanes-XN3QIQJK-CCma0T7L.js} +1 -1
  303. package/out/web/assets/swimlanesDiagram-VK2B7HYN-BkohoVsU.js +8 -0
  304. package/out/web/assets/{timeline-definition-24CTP7MA-CdTERuJZ.js → timeline-definition-24CTP7MA-iCRhhJ7C.js} +1 -1
  305. package/out/web/assets/{treeView-Q6P3EWNA-TKBKQG6R.js → treeView-Q6P3EWNA-DZ-y08qp.js} +1 -1
  306. package/out/web/assets/{treemap-WGGIJYW6-BP7gQoiC.js → treemap-WGGIJYW6-De0CxzMx.js} +1 -1
  307. package/out/web/assets/{vennDiagram-4TSXK5OY-BHUmxDuK.js → vennDiagram-4TSXK5OY-w_7aZ6xe.js} +1 -1
  308. package/out/web/assets/{wardley-WFR3VGLG-9bct5AAN.js → wardley-WFR3VGLG-DT0y0xJ4.js} +1 -1
  309. package/out/web/assets/{wardleyDiagram-VM6X3IG4-BfJwDDso.js → wardleyDiagram-VM6X3IG4-DAdXELbQ.js} +1 -1
  310. package/out/web/assets/window-BJCVtyET.js +1 -0
  311. package/out/web/assets/{xychartDiagram-S5SC5T6Z-Dqd9Mvpo.js → xychartDiagram-S5SC5T6Z-IZIXf3Vo.js} +1 -1
  312. package/out/web/index-web.html +4 -4
  313. package/out/web/index.html +4 -4
  314. package/package.json +80 -20
  315. package/shared-modules/.github/workflows/ci.yml +120 -0
  316. package/shared-modules/.github/workflows/update.yaml +28 -0
  317. package/slash-commands.json +16 -2
  318. package/src/bin/auto-build.js +66 -0
  319. package/src/bin/desktop.js +113 -0
  320. package/src/bin/desktop.test.js +113 -0
  321. package/src/bin/index.js +18 -25
  322. package/src/bin/index.test.js +89 -0
  323. package/src/bin/measure-effects.mjs +53 -0
  324. package/src/bin/package.test.js +28 -0
  325. package/src/bin/release-notes.test.js +84 -0
  326. package/src/bin/styles.test.js +20 -0
  327. package/src/bin/web.js +5 -0
  328. package/src/bin/web.test.js +39 -0
  329. package/src/renderer/index-web.html +1 -0
  330. package/src/renderer/index.html +1 -2
  331. package/src/renderer/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  332. package/src/renderer/shared/agentProgress.ts +201 -3
  333. package/src/renderer/shared/components/AgentActivityDrawer.tsx +9 -8
  334. package/src/renderer/shared/components/AgentActivityTable.tsx +193 -133
  335. package/src/renderer/shared/components/ApprovalCard.test.tsx +24 -0
  336. package/src/renderer/shared/components/ApprovalCard.tsx +10 -3
  337. package/src/renderer/shared/components/ArtifactPreviewPanel.tsx +91 -40
  338. package/src/renderer/shared/components/AuthGate.tsx +79 -48
  339. package/src/renderer/shared/components/BackgroundTerminals.tsx +181 -0
  340. package/src/renderer/shared/components/CalculationCard.tsx +41 -15
  341. package/src/renderer/shared/components/ChatCodeBlock.tsx +8 -4
  342. package/src/renderer/shared/components/ChatMessageItem.test.tsx +68 -0
  343. package/src/renderer/shared/components/ChatMessageItem.tsx +52 -33
  344. package/src/renderer/shared/components/ChatPanel.test.tsx +21 -0
  345. package/src/renderer/shared/components/ChatPanel.tsx +676 -415
  346. package/src/renderer/shared/components/ChunkErrorBoundary.tsx +115 -64
  347. package/src/renderer/shared/components/CliSessionsView.test.tsx +125 -0
  348. package/src/renderer/shared/components/CliSessionsView.tsx +543 -0
  349. package/src/renderer/shared/components/CodeReviewPage.tsx +668 -0
  350. package/src/renderer/shared/components/CollapsiblePasteInput.tsx +90 -0
  351. package/src/renderer/shared/components/CommandPalette.tsx +8 -8
  352. package/src/renderer/shared/components/ContextCompactionStatus.tsx +17 -0
  353. package/src/renderer/shared/components/DashboardSidebar.tsx +853 -229
  354. package/src/renderer/shared/components/DesktopTitlebar.tsx +371 -0
  355. package/src/renderer/shared/components/DiffReviewModal.tsx +3 -3
  356. package/src/renderer/shared/components/ErrorNotice.tsx +29 -0
  357. package/src/renderer/shared/components/FormattedMessage.tsx +11 -0
  358. package/src/renderer/shared/components/GeminiLiveOverlay.css +86 -0
  359. package/src/renderer/shared/components/GeminiLiveOverlay.test.tsx +24 -0
  360. package/src/renderer/shared/components/GeminiLiveOverlay.tsx +85 -101
  361. package/src/renderer/shared/components/GitBranchSelector.tsx +442 -0
  362. package/src/renderer/shared/components/GlideSelect.css +138 -0
  363. package/src/renderer/shared/components/GlideSelect.d.ts +31 -0
  364. package/src/renderer/shared/components/GlideSelect.jsx +266 -0
  365. package/src/renderer/shared/components/ImageGenCard.tsx +31 -12
  366. package/src/renderer/shared/components/ImageSearchCard.tsx +76 -65
  367. package/src/renderer/shared/components/ImageStudioPanel.tsx +49 -49
  368. package/src/renderer/shared/components/InlineThoughtNote.tsx +27 -0
  369. package/src/renderer/shared/components/LibraryItemCard.tsx +72 -0
  370. package/src/renderer/shared/components/LibraryPage.tsx +165 -0
  371. package/src/renderer/shared/components/LibraryPreview.tsx +59 -0
  372. package/src/renderer/shared/components/LinkedFoldersView.tsx +365 -46
  373. package/src/renderer/shared/components/McpRegistryPicker.tsx +1 -1
  374. package/src/renderer/shared/components/McpServersView.tsx +51 -30
  375. package/src/renderer/shared/components/McpToolAllowlist.tsx +2 -4
  376. package/src/renderer/shared/components/McpToolResults.tsx +99 -0
  377. package/src/renderer/shared/components/MermaidCard.tsx +14 -8
  378. package/src/renderer/shared/components/MintDashboard.tsx +1002 -831
  379. package/src/renderer/shared/components/ModSessionControls.tsx +8 -0
  380. package/src/renderer/shared/components/ModUi.test.tsx +65 -0
  381. package/src/renderer/shared/components/ModUi.tsx +26 -0
  382. package/src/renderer/shared/components/ModelSelectorPopover.tsx +547 -219
  383. package/src/renderer/shared/components/ModsPanel.tsx +156 -0
  384. package/src/renderer/shared/components/PlanChecklistWidget.tsx +1 -1
  385. package/src/renderer/shared/components/PluginsView.tsx +1 -1
  386. package/src/renderer/shared/components/ProgressActivity.tsx +17 -0
  387. package/src/renderer/shared/components/ReviewHistory.tsx +42 -0
  388. package/src/renderer/shared/components/RewindModal.tsx +11 -18
  389. package/src/renderer/shared/components/RunSummaryDashboard.tsx +8 -14
  390. package/src/renderer/shared/components/ScheduledTasksView.tsx +11 -10
  391. package/src/renderer/shared/components/ScreenCaptureDialog.css +221 -0
  392. package/src/renderer/shared/components/ScreenCaptureDialog.tsx +199 -0
  393. package/src/renderer/shared/components/SelectField.test.tsx +27 -0
  394. package/src/renderer/shared/components/SelectField.tsx +38 -0
  395. package/src/renderer/shared/components/SessionSources.tsx +48 -0
  396. package/src/renderer/shared/components/SessionSourcesPopover.tsx +61 -0
  397. package/src/renderer/shared/components/Settings/AgentsTab.tsx +41 -45
  398. package/src/renderer/shared/components/Settings/AudioTab.tsx +16 -15
  399. package/src/renderer/shared/components/Settings/AutomationTab.tsx +10 -60
  400. package/src/renderer/shared/components/Settings/AvatarCropModal.tsx +368 -0
  401. package/src/renderer/shared/components/Settings/GeneralTab.tsx +368 -113
  402. package/src/renderer/shared/components/Settings/MemoryTab.test.tsx +37 -0
  403. package/src/renderer/shared/components/Settings/MemoryTab.tsx +71 -31
  404. package/src/renderer/shared/components/Settings/NotificationsTab.test.tsx +15 -0
  405. package/src/renderer/shared/components/Settings/NotificationsTab.tsx +84 -0
  406. package/src/renderer/shared/components/Settings/PluginsTab.tsx +20 -12
  407. package/src/renderer/shared/components/Settings/ProfileTab.tsx +29 -5
  408. package/src/renderer/shared/components/Settings/SearchableModelCombobox.tsx +411 -0
  409. package/src/renderer/shared/components/Settings/ThemeTab.tsx +416 -165
  410. package/src/renderer/shared/components/SkillsView.tsx +41 -16
  411. package/src/renderer/shared/components/SlashChoicePanel.tsx +88 -0
  412. package/src/renderer/shared/components/SlashSuggestions.test.tsx +33 -0
  413. package/src/renderer/shared/components/SlashSuggestions.tsx +41 -12
  414. package/src/renderer/shared/components/SourcesBlock.tsx +55 -51
  415. package/src/renderer/shared/components/StockCard.tsx +58 -24
  416. package/src/renderer/shared/components/SubagentDagView.tsx +4 -4
  417. package/src/renderer/shared/components/TerminalDock.tsx +241 -0
  418. package/src/renderer/shared/components/ThinkingBlock.tsx +14 -8
  419. package/src/renderer/shared/components/ToolSurfacePage.test.tsx +32 -0
  420. package/src/renderer/shared/components/ToolSurfacePage.tsx +568 -0
  421. package/src/renderer/shared/components/ToolsPanelToggle.tsx +13 -0
  422. package/src/renderer/shared/components/UiFeatureCard.tsx +267 -0
  423. package/src/renderer/shared/components/UiGridCard.tsx +188 -0
  424. package/src/renderer/shared/components/UiMockupWidget.tsx +149 -0
  425. package/src/renderer/shared/components/VeoStudioPanel.tsx +22 -37
  426. package/src/renderer/shared/components/ViewedImages.tsx +36 -0
  427. package/src/renderer/shared/components/VirtualChatHistory.tsx +82 -0
  428. package/src/renderer/shared/components/VoicePill.css +85 -0
  429. package/src/renderer/shared/components/VoicePill.d.ts +12 -0
  430. package/src/renderer/shared/components/VoicePill.jsx +190 -0
  431. package/src/renderer/shared/components/VoicePill.test.tsx +22 -0
  432. package/src/renderer/shared/components/WeatherCard.tsx +3 -3
  433. package/src/renderer/shared/components/WorkspaceContextPopover.tsx +138 -0
  434. package/src/renderer/shared/components/WorkspacePaneResizer.tsx +92 -0
  435. package/src/renderer/shared/components/WorkspacePreviewActions.test.tsx +44 -0
  436. package/src/renderer/shared/components/WorkspacePreviewActions.tsx +19 -0
  437. package/src/renderer/shared/components/WorkspaceSelector.tsx +154 -0
  438. package/src/renderer/shared/components/background-terminals.css +292 -0
  439. package/src/renderer/shared/components/ui/README.md +52 -0
  440. package/src/renderer/shared/components/ui/button.tsx +37 -0
  441. package/src/renderer/shared/components/ui/demo.tsx +26 -0
  442. package/src/renderer/shared/components/ui/error-recovery.css +35 -0
  443. package/src/renderer/shared/components/ui/error-recovery.tsx +35 -0
  444. package/src/renderer/shared/components/ui/voice-powered-orb.css +6 -0
  445. package/src/renderer/shared/components/ui/voice-powered-orb.tsx +374 -0
  446. package/src/renderer/shared/components/workspace-selector.css +248 -0
  447. package/src/renderer/shared/constants/config.ts +57 -3
  448. package/src/renderer/shared/constants/models.ts +189 -2
  449. package/src/renderer/shared/constants/slashCommands.ts +1 -1
  450. package/src/renderer/shared/conversation/coordinator.test.ts +27 -0
  451. package/src/renderer/shared/conversation/coordinator.ts +82 -0
  452. package/src/renderer/shared/conversation/lifecycle.test.ts +362 -0
  453. package/src/renderer/shared/conversation/lifecycle.ts +418 -0
  454. package/src/renderer/shared/conversation/projectNavigation.test.ts +105 -0
  455. package/src/renderer/shared/conversation/projectNavigation.ts +39 -0
  456. package/src/renderer/shared/conversation/sourcesTransport.ts +27 -0
  457. package/src/renderer/shared/conversation/syncView.test.ts +13 -0
  458. package/src/renderer/shared/conversation/syncView.ts +6 -0
  459. package/src/renderer/shared/conversation/transport.test.ts +163 -0
  460. package/src/renderer/shared/conversation/transport.ts +159 -0
  461. package/src/renderer/shared/conversation/useConversationCoordinator.ts +64 -0
  462. package/src/renderer/shared/css/agent-observability.css +46 -15
  463. package/src/renderer/shared/css/auth-gate.css +114 -15
  464. package/src/renderer/shared/css/chat-ui-cards.css +495 -0
  465. package/src/renderer/shared/css/code-review.css +856 -0
  466. package/src/renderer/shared/css/code-sessions.css +479 -0
  467. package/src/renderer/shared/css/collapsed-paste.css +35 -0
  468. package/src/renderer/shared/css/effects.css +15 -0
  469. package/src/renderer/shared/css/error-notice.css +60 -0
  470. package/src/renderer/shared/css/file-changes.css +132 -0
  471. package/src/renderer/shared/css/image-studio.css +16 -16
  472. package/src/renderer/shared/css/library.css +476 -0
  473. package/src/renderer/shared/css/management-views.css +415 -27
  474. package/src/renderer/shared/css/mcp-results.css +11 -0
  475. package/src/renderer/shared/css/model-selector.css +543 -85
  476. package/src/renderer/shared/css/mods.css +77 -0
  477. package/src/renderer/shared/css/notification-notice.css +28 -0
  478. package/src/renderer/shared/css/session-sources-popover.css +9 -0
  479. package/src/renderer/shared/css/session-sources.css +23 -0
  480. package/src/renderer/shared/css/settings/agents.css +1 -1
  481. package/src/renderer/shared/css/settings/automation.css +13 -13
  482. package/src/renderer/shared/css/settings/general.css +526 -5
  483. package/src/renderer/shared/css/settings/memory.css +154 -0
  484. package/src/renderer/shared/css/settings/notifications.css +11 -0
  485. package/src/renderer/shared/css/settings/plugins.css +5 -5
  486. package/src/renderer/shared/css/settings/profile.css +331 -1
  487. package/src/renderer/shared/css/settings/theme.css +656 -3
  488. package/src/renderer/shared/css/slash-choice.css +95 -0
  489. package/src/renderer/shared/css/slash-suggestions.css +68 -0
  490. package/src/renderer/shared/css/sources-block.css +91 -0
  491. package/src/renderer/shared/css/thinking-status.css +46 -0
  492. package/src/renderer/shared/css/tools-panel.css +7 -0
  493. package/src/renderer/shared/css/ui-tailwind.css +19 -0
  494. package/src/renderer/shared/css/veo-studio.css +16 -15
  495. package/src/renderer/shared/css/viewed-images.css +15 -0
  496. package/src/renderer/shared/fonts.css +46 -0
  497. package/src/renderer/shared/fonts.ts +10 -37
  498. package/src/renderer/shared/lib/utils.ts +6 -0
  499. package/src/renderer/shared/library/controller.test.ts +61 -0
  500. package/src/renderer/shared/library/controller.ts +57 -0
  501. package/src/renderer/shared/library/transport.test.ts +26 -0
  502. package/src/renderer/shared/library/transport.ts +60 -0
  503. package/src/renderer/shared/library/useLibraryFile.ts +38 -0
  504. package/src/renderer/shared/mods.ts +58 -0
  505. package/src/renderer/shared/platform.test.ts +90 -0
  506. package/src/renderer/shared/platform.ts +219 -7
  507. package/src/renderer/shared/theme/themeManager.test.ts +43 -0
  508. package/src/renderer/shared/theme/themeManager.ts +157 -0
  509. package/src/renderer/shared/theme/themes.ts +116 -0
  510. package/src/renderer/shared/theme/tokens.css +318 -0
  511. package/src/renderer/shared/types.ts +137 -2
  512. package/src/renderer/shared/utils/agentActivity.test.ts +75 -0
  513. package/src/renderer/shared/utils/agentActivity.ts +168 -8
  514. package/src/renderer/shared/utils/approval.tsx +7 -0
  515. package/src/renderer/shared/utils/artifactBrowser.test.ts +80 -0
  516. package/src/renderer/shared/utils/artifactBrowser.ts +41 -0
  517. package/src/renderer/shared/utils/cardJson.test.ts +35 -0
  518. package/src/renderer/shared/utils/cardJson.ts +30 -0
  519. package/src/renderer/shared/utils/contextCompaction.test.tsx +48 -0
  520. package/src/renderer/shared/utils/contextCompaction.ts +21 -0
  521. package/src/renderer/shared/utils/effectVisibility.ts +9 -0
  522. package/src/renderer/shared/utils/fileIcons.ts +1 -1
  523. package/src/renderer/shared/utils/markdown.tsx +330 -81
  524. package/src/renderer/shared/utils/markdown.webImages.test.tsx +40 -0
  525. package/src/renderer/shared/utils/mcpResults.test.tsx +91 -0
  526. package/src/renderer/shared/utils/modViewport.ts +7 -0
  527. package/src/renderer/shared/utils/nativeRecordingSession.test.ts +61 -0
  528. package/src/renderer/shared/utils/nativeRecordingSession.ts +46 -0
  529. package/src/renderer/shared/utils/notificationSettings.test.ts +14 -0
  530. package/src/renderer/shared/utils/notificationSettings.ts +23 -0
  531. package/src/renderer/shared/utils/notifications.test.ts +51 -0
  532. package/src/renderer/shared/utils/notifications.ts +54 -0
  533. package/src/renderer/shared/utils/pastedText.test.ts +20 -0
  534. package/src/renderer/shared/utils/pastedText.ts +13 -0
  535. package/src/renderer/shared/utils/progressCache.test.ts +32 -0
  536. package/src/renderer/shared/utils/providers.ts +8 -3
  537. package/src/renderer/shared/utils/screenCapture.ts +43 -0
  538. package/src/renderer/shared/utils/sessionSources.test.ts +31 -0
  539. package/src/renderer/shared/utils/sessionSources.ts +34 -0
  540. package/src/renderer/shared/utils/slashCommandProcessor.ts +5 -2
  541. package/src/renderer/shared/utils/sourceAttachments.ts +28 -0
  542. package/src/renderer/shared/utils/speech.ts +51 -9
  543. package/src/renderer/shared/utils/syntaxHighlight.test.tsx +22 -0
  544. package/src/renderer/shared/utils/syntaxHighlight.tsx +26 -0
  545. package/src/renderer/shared/utils/ui.ts +4 -64
  546. package/src/renderer/shared/utils/useGeminiLiveVoice.ts +49 -5
  547. package/src/renderer/shared/utils/useLatestCallback.ts +9 -0
  548. package/src/renderer/shared/utils/useNativeVoiceInput.ts +80 -72
  549. package/src/renderer/shared/utils/useSessionSources.ts +33 -0
  550. package/src/renderer/shared/utils/viewedImages.ts +26 -0
  551. package/src/renderer/shared/utils/workspacePane.test.ts +33 -0
  552. package/src/renderer/shared/utils/workspacePane.ts +20 -0
  553. package/src/renderer/shared/utils/workspacePreview.test.ts +24 -0
  554. package/src/renderer/shared/utils/workspacePreview.ts +16 -0
  555. package/src/renderer/shared/utils/workspaceSnapshot.test.ts +49 -0
  556. package/src/renderer/shared/utils/workspaceSnapshot.ts +26 -0
  557. package/src/renderer/shared/utils/workspaces.ts +10 -0
  558. package/src/renderer/shared/workspaceUndo.ts +88 -0
  559. package/src/renderer/src/App.tsx +16 -1
  560. package/src/renderer/src/components/BrowserShell.tsx +108 -0
  561. package/src/renderer/src/components/BrowserSuggestionsPopup.tsx +91 -0
  562. package/src/renderer/src/components/LiveTranslateControls.tsx +65 -0
  563. package/src/renderer/src/components/MintDashboard.tsx +4 -2
  564. package/src/renderer/src/components/PicturesLibrary.tsx +2 -287
  565. package/src/renderer/src/components/ScreenPicker.css +227 -0
  566. package/src/renderer/src/components/ScreenPicker.tsx +312 -526
  567. package/src/renderer/src/components/SettingsWindow.tsx +48 -5
  568. package/src/renderer/src/components/SpotlightWindow.tsx +1 -0
  569. package/src/renderer/src/components/WidgetWindow.tsx +27 -3
  570. package/src/renderer/src/components/WorkspacePanel.tsx +269 -61
  571. package/src/renderer/src/components/browser-shell.css +185 -0
  572. package/src/renderer/src/components/browser-suggestions-popup.css +55 -0
  573. package/src/renderer/src/components/liveTranslateFrames.test.ts +44 -0
  574. package/src/renderer/src/components/liveTranslateFrames.ts +45 -0
  575. package/src/renderer/src/components/liveTranslateLanguage.ts +6 -0
  576. package/src/renderer/src/css/app-shell.css +400 -204
  577. package/src/renderer/src/css/chat.css +1666 -594
  578. package/src/renderer/src/css/dashboard.css +11 -0
  579. package/src/renderer/src/css/desktop-tools.css +928 -0
  580. package/src/renderer/src/css/misc.css +5 -60
  581. package/src/renderer/src/css/pictures.css +2 -407
  582. package/src/renderer/src/css/settings/base.css +394 -157
  583. package/src/renderer/src/css/sidebar-workspace.css +1072 -376
  584. package/src/renderer/src/css/spotlight.css +15 -26
  585. package/src/renderer/src/css/tool-surfaces.css +784 -0
  586. package/src/renderer/src/css/widget.css +36 -8
  587. package/src/renderer/src/env.d.ts +4 -9
  588. package/src/renderer/src/hooks/useProviderModels.ts +2 -9
  589. package/src/renderer/src/index.css +53 -46
  590. package/src/renderer/src/main.tsx +12 -0
  591. package/src/renderer/src/proactiveSuggestions.ts +29 -0
  592. package/src/renderer/src/tauri.ts +302 -339
  593. package/src/renderer/src/voiceInput.ts +2 -1
  594. package/src/renderer/src-web/App.tsx +40 -0
  595. package/src/renderer/src-web/components/MintDashboard.tsx +4 -2
  596. package/src/renderer/src-web/components/PicturesLibrary.tsx +2 -284
  597. package/src/renderer/src-web/components/PullToRefresh.tsx +107 -0
  598. package/src/renderer/src-web/components/SettingsWindow.tsx +36 -5
  599. package/src/renderer/src-web/css/app-shell.css +188 -207
  600. package/src/renderer/src-web/css/chat.css +1236 -507
  601. package/src/renderer/src-web/css/dashboard.css +11 -0
  602. package/src/renderer/src-web/css/misc.css +3 -55
  603. package/src/renderer/src-web/css/mobile.css +679 -0
  604. package/src/renderer/src-web/css/pictures.css +2 -415
  605. package/src/renderer/src-web/css/pull-to-refresh.css +54 -0
  606. package/src/renderer/src-web/css/settings/base.css +353 -134
  607. package/src/renderer/src-web/css/settings/mobile.css +320 -0
  608. package/src/renderer/src-web/css/sidebar-workspace.css +546 -187
  609. package/src/renderer/src-web/css/spotlight.css +9 -26
  610. package/src/renderer/src-web/css/widget.css +1 -6
  611. package/src/renderer/src-web/env.d.ts +4 -12
  612. package/src/renderer/src-web/hooks/useProviderModels.ts +2 -9
  613. package/src/renderer/src-web/index.css +53 -96
  614. package/src/renderer/src-web/main.tsx +12 -0
  615. package/src/renderer/src-web/proactiveSuggestions.ts +3 -0
  616. package/src/renderer/src-web/tauri.ts +309 -364
  617. package/src/renderer/tests/backgroundTerminals.browser.html +81 -0
  618. package/src/renderer/tests/chatPanelFixture.ts +23 -0
  619. package/src/renderer/tests/chatPerformance.browser.html +71 -0
  620. package/src/renderer/tests/cliSessions.browser.html +82 -0
  621. package/src/renderer/tests/collapsedPaste.browser.html +70 -0
  622. package/src/renderer/tests/composerMenus.browser.html +116 -0
  623. package/src/renderer/tests/contextCompaction.browser.html +17 -0
  624. package/src/renderer/tests/conversationLifecycle.browser.html +70 -0
  625. package/src/renderer/tests/effectsPerformance.browser.html +13 -0
  626. package/src/renderer/tests/errorRecovery.browser.html +21 -0
  627. package/src/renderer/tests/glideSelect.browser.html +71 -0
  628. package/src/renderer/tests/glideSelect.preview.html +27 -0
  629. package/src/renderer/tests/library.browser.html +1 -0
  630. package/src/renderer/tests/library.browser.tsx +78 -0
  631. package/src/renderer/tests/liveOrb.browser.html +49 -0
  632. package/src/renderer/tests/liveVoice.browser.html +29 -0
  633. package/src/renderer/tests/modInput.browser.html +22 -0
  634. package/src/renderer/tests/sessionSources.browser.html +1 -0
  635. package/src/renderer/tests/sessionSources.browser.tsx +107 -0
  636. package/src/renderer/tests/skills.browser.html +24 -0
  637. package/src/renderer/tests/toolsPanel.browser.html +1 -0
  638. package/src/renderer/tests/toolsPanel.browser.tsx +113 -0
  639. package/src/renderer/tests/viewedImages.browser.html +1 -0
  640. package/src/renderer/tests/viewedImages.browser.tsx +93 -0
  641. package/src/renderer/tests/voicePill.browser.html +80 -0
  642. package/src/renderer/tests/voicePill.preview.html +34 -0
  643. package/src/renderer/tests/webSources.browser.html +1 -0
  644. package/src/renderer/tests/webSources.browser.tsx +98 -0
  645. package/src/renderer/tests/workspaceUndo.browser.html +92 -0
  646. package/src-tauri/Cargo.toml +40 -0
  647. package/src-tauri/build.rs +3 -0
  648. package/src-tauri/src/app/lifecycle.rs +277 -0
  649. package/src-tauri/src/app/mod.rs +4 -0
  650. package/src-tauri/src/app/shortcuts.rs +40 -0
  651. package/src-tauri/src/app/tray.rs +52 -0
  652. package/src-tauri/src/background/events.rs +70 -0
  653. package/src-tauri/src/background/headless.rs +230 -0
  654. package/src-tauri/src/background/mod.rs +4 -0
  655. package/src-tauri/src/background/proactive.rs +262 -0
  656. package/src-tauri/src/commands/approvals.rs +20 -0
  657. package/src-tauri/src/commands/auth.rs +127 -0
  658. package/src-tauri/src/commands/conversation.rs +642 -0
  659. package/src-tauri/src/commands/integrations.rs +157 -0
  660. package/src-tauri/src/commands/media.rs +179 -0
  661. package/src-tauri/src/commands/mod.rs +11 -0
  662. package/src-tauri/src/commands/mods.rs +6 -0
  663. package/src-tauri/src/commands/settings.rs +141 -0
  664. package/src-tauri/src/commands/voice.rs +153 -0
  665. package/src-tauri/src/commands/workspace.rs +501 -0
  666. package/src-tauri/src/lib.rs +10 -0
  667. package/src-tauri/src/main.rs +3 -0
  668. package/src-tauri/src/native/actions.rs +206 -0
  669. package/src-tauri/src/native/browser.rs +252 -0
  670. package/src-tauri/src/native/capture.rs +695 -0
  671. package/src-tauri/src/native/discord_rpc.rs +99 -0
  672. package/src-tauri/src/native/integrations.rs +126 -0
  673. package/src-tauri/src/native/mod.rs +12 -0
  674. package/src-tauri/src/native/notifications.rs +51 -0
  675. package/src-tauri/src/native/plugins.rs +14 -0
  676. package/src-tauri/src/native/system.rs +250 -0
  677. package/src-tauri/src/native/terminal.rs +201 -0
  678. package/src-tauri/src/native/updater.rs +148 -0
  679. package/src-tauri/src/native/windows.rs +143 -0
  680. package/tsconfig.json +2 -0
  681. package/vite.config.ts +4 -1
  682. package/vite.config.web.ts +5 -0
  683. package/.cargo/config.toml +0 -13
  684. package/.claude/settings.local.json +0 -182
  685. package/.codex +0 -0
  686. package/CLAUDE.md +0 -102
  687. package/out/web/Live2DCubismCore.js +0 -9
  688. package/out/web/assets/MintDashboard-DWSqucgb.js +0 -57
  689. package/out/web/assets/SettingsWindow-DFM2aj5B.js +0 -2
  690. package/out/web/assets/chunk-CKBBP62Z-nr1uKPj9.js +0 -2
  691. package/out/web/assets/chunk-DSNCTWBM-Dtj8Rqsd.js +0 -2
  692. package/out/web/assets/chunk-DU6HZSFF-2tv5K1wT.js +0 -128
  693. package/out/web/assets/classDiagram-DTDB5LWJ-BdSFArgw.js +0 -1
  694. package/out/web/assets/classDiagram-v2-JRS7N3AN-BdSFArgw.js +0 -1
  695. package/out/web/assets/core-DImejIUG.js +0 -1
  696. package/out/web/assets/dist-js-BxuKEVWM.js +0 -1
  697. package/out/web/assets/event-BNl8Zahw.js +0 -1
  698. package/out/web/assets/fira-code-cyrillic-400-normal-UC0NFL4U.woff2 +0 -0
  699. package/out/web/assets/fira-code-cyrillic-400-normal-dc1q3VD7.woff +0 -0
  700. package/out/web/assets/fira-code-cyrillic-500-normal-Bu7VCL72.woff +0 -0
  701. package/out/web/assets/fira-code-cyrillic-500-normal-CX35h3Mg.woff2 +0 -0
  702. package/out/web/assets/fira-code-cyrillic-ext-400-normal-Buh61xzB.woff +0 -0
  703. package/out/web/assets/fira-code-cyrillic-ext-400-normal-txZ9Fk_1.woff2 +0 -0
  704. package/out/web/assets/fira-code-cyrillic-ext-500-normal-CYRspHgm.woff2 +0 -0
  705. package/out/web/assets/fira-code-cyrillic-ext-500-normal-CwtLmSFD.woff +0 -0
  706. package/out/web/assets/fira-code-greek-400-normal-B2Gh_Y8s.woff2 +0 -0
  707. package/out/web/assets/fira-code-greek-400-normal-DobhaxvF.woff +0 -0
  708. package/out/web/assets/fira-code-greek-500-normal-CVO0IRNt.woff2 +0 -0
  709. package/out/web/assets/fira-code-greek-500-normal-DEXIWiey.woff +0 -0
  710. package/out/web/assets/fira-code-greek-ext-400-normal-DR7mBgIM.woff2 +0 -0
  711. package/out/web/assets/fira-code-greek-ext-400-normal-DSPUheWg.woff +0 -0
  712. package/out/web/assets/fira-code-greek-ext-500-normal-BO3iq16n.woff2 +0 -0
  713. package/out/web/assets/fira-code-greek-ext-500-normal-CMiNLXER.woff +0 -0
  714. package/out/web/assets/fira-code-latin-ext-400-normal-DG73JjOf.woff +0 -0
  715. package/out/web/assets/fira-code-latin-ext-400-normal-KSMg0QLl.woff2 +0 -0
  716. package/out/web/assets/fira-code-latin-ext-500-normal-CaANqXjI.woff +0 -0
  717. package/out/web/assets/fira-code-latin-ext-500-normal-Crd9e_oI.woff2 +0 -0
  718. package/out/web/assets/flowDiagram-A5DVABFB-BpnHUSU7.js +0 -1
  719. package/out/web/assets/index-CVRg270z.css +0 -1
  720. package/out/web/assets/index-DxZQr9yD.js +0 -10
  721. package/out/web/assets/inter-cyrillic-400-normal-HOLc17fK.woff +0 -0
  722. package/out/web/assets/inter-cyrillic-400-normal-obahsSVq.woff2 +0 -0
  723. package/out/web/assets/inter-cyrillic-500-normal-BasfLYem.woff2 +0 -0
  724. package/out/web/assets/inter-cyrillic-500-normal-CxZf_p3X.woff +0 -0
  725. package/out/web/assets/inter-cyrillic-600-normal-4D_pXhcN.woff +0 -0
  726. package/out/web/assets/inter-cyrillic-600-normal-CWCymEST.woff2 +0 -0
  727. package/out/web/assets/inter-cyrillic-ext-400-normal-BQZuk6qB.woff2 +0 -0
  728. package/out/web/assets/inter-cyrillic-ext-400-normal-DQukG94-.woff +0 -0
  729. package/out/web/assets/inter-cyrillic-ext-500-normal-B0yAr1jD.woff2 +0 -0
  730. package/out/web/assets/inter-cyrillic-ext-500-normal-BmqWE9Dz.woff +0 -0
  731. package/out/web/assets/inter-cyrillic-ext-600-normal-Bcila6Z-.woff +0 -0
  732. package/out/web/assets/inter-cyrillic-ext-600-normal-Dfes3d0z.woff2 +0 -0
  733. package/out/web/assets/inter-greek-400-normal-B4URO6DV.woff2 +0 -0
  734. package/out/web/assets/inter-greek-400-normal-q2sYcFCs.woff +0 -0
  735. package/out/web/assets/inter-greek-500-normal-BIZE56-Y.woff2 +0 -0
  736. package/out/web/assets/inter-greek-500-normal-Xzm54t5V.woff +0 -0
  737. package/out/web/assets/inter-greek-600-normal-BZpKdvQh.woff +0 -0
  738. package/out/web/assets/inter-greek-600-normal-plRanbMR.woff2 +0 -0
  739. package/out/web/assets/inter-greek-ext-400-normal-DGGRlc-M.woff2 +0 -0
  740. package/out/web/assets/inter-greek-ext-400-normal-KugGGMne.woff +0 -0
  741. package/out/web/assets/inter-greek-ext-500-normal-2j5mBUwD.woff +0 -0
  742. package/out/web/assets/inter-greek-ext-500-normal-C4iEst2y.woff2 +0 -0
  743. package/out/web/assets/inter-greek-ext-600-normal-B8X0CLgF.woff +0 -0
  744. package/out/web/assets/inter-greek-ext-600-normal-DRtmH8MT.woff2 +0 -0
  745. package/out/web/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  746. package/out/web/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
  747. package/out/web/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
  748. package/out/web/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  749. package/out/web/assets/inter-latin-600-normal-CiBQ2DWP.woff +0 -0
  750. package/out/web/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
  751. package/out/web/assets/inter-latin-ext-400-normal-77YHD8bZ.woff +0 -0
  752. package/out/web/assets/inter-latin-ext-400-normal-C1nco2VV.woff2 +0 -0
  753. package/out/web/assets/inter-latin-ext-500-normal-BxGbmqWO.woff +0 -0
  754. package/out/web/assets/inter-latin-ext-500-normal-CV4jyFjo.woff2 +0 -0
  755. package/out/web/assets/inter-latin-ext-600-normal-CIVaiw4L.woff +0 -0
  756. package/out/web/assets/inter-latin-ext-600-normal-D2bJ5OIk.woff2 +0 -0
  757. package/out/web/assets/inter-vietnamese-400-normal-Bbgyi5SW.woff +0 -0
  758. package/out/web/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
  759. package/out/web/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
  760. package/out/web/assets/inter-vietnamese-500-normal-mJboJaSs.woff +0 -0
  761. package/out/web/assets/inter-vietnamese-600-normal-BuLX-rYi.woff +0 -0
  762. package/out/web/assets/inter-vietnamese-600-normal-Cc8MFFhd.woff2 +0 -0
  763. package/out/web/assets/kanit-latin-400-normal-BUlsQXH3.woff2 +0 -0
  764. package/out/web/assets/kanit-latin-400-normal-HVZWrfev.woff +0 -0
  765. package/out/web/assets/kanit-latin-500-normal-CX_4XcKi.woff2 +0 -0
  766. package/out/web/assets/kanit-latin-500-normal-qBha86O4.woff +0 -0
  767. package/out/web/assets/kanit-latin-600-normal-0lS78yAd.woff2 +0 -0
  768. package/out/web/assets/kanit-latin-600-normal-DlacpeTg.woff +0 -0
  769. package/out/web/assets/kanit-latin-ext-400-normal-B2xPf58u.woff2 +0 -0
  770. package/out/web/assets/kanit-latin-ext-400-normal-CHvNKHHD.woff +0 -0
  771. package/out/web/assets/kanit-latin-ext-500-normal-BFdWrG22.woff +0 -0
  772. package/out/web/assets/kanit-latin-ext-500-normal-EHs3suD6.woff2 +0 -0
  773. package/out/web/assets/kanit-latin-ext-600-normal-BBDzoLaj.woff +0 -0
  774. package/out/web/assets/kanit-latin-ext-600-normal-DAX3wtuq.woff2 +0 -0
  775. package/out/web/assets/kanit-thai-400-normal-D2nliXKa.woff +0 -0
  776. package/out/web/assets/kanit-thai-400-normal-D80Pglro.woff2 +0 -0
  777. package/out/web/assets/kanit-thai-500-normal-BB8gri04.woff2 +0 -0
  778. package/out/web/assets/kanit-thai-500-normal-Iy_w0a80.woff +0 -0
  779. package/out/web/assets/kanit-thai-600-normal-Bj6oiaDc.woff2 +0 -0
  780. package/out/web/assets/kanit-thai-600-normal-wbTlPO7I.woff +0 -0
  781. package/out/web/assets/kanit-vietnamese-400-normal-DRI8YWyb.woff2 +0 -0
  782. package/out/web/assets/kanit-vietnamese-400-normal-dow6Bnto.woff +0 -0
  783. package/out/web/assets/kanit-vietnamese-500-normal-BzTrpCM3.woff2 +0 -0
  784. package/out/web/assets/kanit-vietnamese-500-normal-T1ndT7MF.woff +0 -0
  785. package/out/web/assets/kanit-vietnamese-600-normal-Bi7fw3I4.woff2 +0 -0
  786. package/out/web/assets/kanit-vietnamese-600-normal-DXCRAa_8.woff +0 -0
  787. package/out/web/assets/mali-latin-400-normal-ByPcZ8Gx.woff +0 -0
  788. package/out/web/assets/mali-latin-400-normal-Cuc6Ykl8.woff2 +0 -0
  789. package/out/web/assets/mali-latin-500-normal-B01M-LP6.woff2 +0 -0
  790. package/out/web/assets/mali-latin-500-normal-Thgqw_9f.woff +0 -0
  791. package/out/web/assets/mali-latin-600-normal-B9TiUNpT.woff2 +0 -0
  792. package/out/web/assets/mali-latin-600-normal-CycpQCwU.woff +0 -0
  793. package/out/web/assets/mali-latin-ext-400-normal-DUVdJQO4.woff +0 -0
  794. package/out/web/assets/mali-latin-ext-400-normal-iCG1ALuJ.woff2 +0 -0
  795. package/out/web/assets/mali-latin-ext-500-normal-BfJE4UMZ.woff2 +0 -0
  796. package/out/web/assets/mali-latin-ext-500-normal-FoLEyOKS.woff +0 -0
  797. package/out/web/assets/mali-latin-ext-600-normal-BTvIfiCp.woff2 +0 -0
  798. package/out/web/assets/mali-latin-ext-600-normal-DAQcLVmD.woff +0 -0
  799. package/out/web/assets/mali-thai-400-normal-BO7A3bLZ.woff2 +0 -0
  800. package/out/web/assets/mali-thai-400-normal-CX9VrjTn.woff +0 -0
  801. package/out/web/assets/mali-thai-500-normal-Cph2qha9.woff +0 -0
  802. package/out/web/assets/mali-thai-500-normal-D89rMT77.woff2 +0 -0
  803. package/out/web/assets/mali-thai-600-normal-DPgXT6rZ.woff +0 -0
  804. package/out/web/assets/mali-thai-600-normal-DlTx3OsB.woff2 +0 -0
  805. package/out/web/assets/mali-vietnamese-400-normal-DUKxzXaz.woff2 +0 -0
  806. package/out/web/assets/mali-vietnamese-400-normal-gFDLvsOK.woff +0 -0
  807. package/out/web/assets/mali-vietnamese-500-normal--OY07q2c.woff +0 -0
  808. package/out/web/assets/mali-vietnamese-500-normal-KDrNRwfW.woff2 +0 -0
  809. package/out/web/assets/mali-vietnamese-600-normal-CtTMUU7T.woff +0 -0
  810. package/out/web/assets/mali-vietnamese-600-normal-DFlJr66u.woff2 +0 -0
  811. package/out/web/assets/mermaid.core-DYGGlqOf.js +0 -11
  812. package/out/web/assets/mitr-latin-400-normal-Cb18vPmZ.woff +0 -0
  813. package/out/web/assets/mitr-latin-400-normal-CwbkLQ4a.woff2 +0 -0
  814. package/out/web/assets/mitr-latin-500-normal-B4JOhzAi.woff +0 -0
  815. package/out/web/assets/mitr-latin-500-normal-BmClOow2.woff2 +0 -0
  816. package/out/web/assets/mitr-latin-ext-400-normal-B3CPG7Yo.woff2 +0 -0
  817. package/out/web/assets/mitr-latin-ext-400-normal-DTx65hiC.woff +0 -0
  818. package/out/web/assets/mitr-latin-ext-500-normal-B_Diajz1.woff2 +0 -0
  819. package/out/web/assets/mitr-latin-ext-500-normal-DYOsVaVT.woff +0 -0
  820. package/out/web/assets/mitr-thai-400-normal-CS4Do6aM.woff +0 -0
  821. package/out/web/assets/mitr-thai-400-normal-CXWaAdVj.woff2 +0 -0
  822. package/out/web/assets/mitr-thai-500-normal-CVdBrEVH.woff2 +0 -0
  823. package/out/web/assets/mitr-thai-500-normal-CW_B5D-i.woff +0 -0
  824. package/out/web/assets/mitr-vietnamese-400-normal-CPMGWyoC.woff2 +0 -0
  825. package/out/web/assets/mitr-vietnamese-400-normal-Z6XhIpdY.woff +0 -0
  826. package/out/web/assets/mitr-vietnamese-500-normal-CDrv0585.woff2 +0 -0
  827. package/out/web/assets/mitr-vietnamese-500-normal-CMQWyq-Z.woff +0 -0
  828. package/out/web/assets/noto-sans-thai-latin-400-normal-BaWBrqFP.woff2 +0 -0
  829. package/out/web/assets/noto-sans-thai-latin-400-normal-Dh_FJjOB.woff +0 -0
  830. package/out/web/assets/noto-sans-thai-latin-500-normal-BC04jsmm.woff +0 -0
  831. package/out/web/assets/noto-sans-thai-latin-500-normal-fyBKClF1.woff2 +0 -0
  832. package/out/web/assets/noto-sans-thai-latin-600-normal-CemcjnVR.woff2 +0 -0
  833. package/out/web/assets/noto-sans-thai-latin-600-normal-Dbc-dNO6.woff +0 -0
  834. package/out/web/assets/noto-sans-thai-latin-ext-400-normal-B-1H0YkH.woff +0 -0
  835. package/out/web/assets/noto-sans-thai-latin-ext-400-normal-nBP59pVw.woff2 +0 -0
  836. package/out/web/assets/noto-sans-thai-latin-ext-500-normal-B-ZWb8SZ.woff2 +0 -0
  837. package/out/web/assets/noto-sans-thai-latin-ext-500-normal-CrEHO7C8.woff +0 -0
  838. package/out/web/assets/noto-sans-thai-latin-ext-600-normal-PkMZo0xa.woff +0 -0
  839. package/out/web/assets/noto-sans-thai-latin-ext-600-normal-maHHBsez.woff2 +0 -0
  840. package/out/web/assets/noto-sans-thai-thai-400-normal-BEOmKAI1.woff2 +0 -0
  841. package/out/web/assets/noto-sans-thai-thai-400-normal-Dxb_unuU.woff +0 -0
  842. package/out/web/assets/noto-sans-thai-thai-500-normal-BOGXO2tw.woff +0 -0
  843. package/out/web/assets/noto-sans-thai-thai-500-normal-CU_X86GQ.woff2 +0 -0
  844. package/out/web/assets/noto-sans-thai-thai-600-normal-CmgB8_JK.woff +0 -0
  845. package/out/web/assets/noto-sans-thai-thai-600-normal-Cs73sVjl.woff2 +0 -0
  846. package/out/web/assets/oauthManager-DNiwM8Rn.js +0 -2
  847. package/out/web/assets/oauthManager-DuamS1Av.css +0 -1
  848. package/out/web/assets/outfit-latin-300-normal-AWLfuCom.woff +0 -0
  849. package/out/web/assets/outfit-latin-300-normal-CRYTwY6m.woff2 +0 -0
  850. package/out/web/assets/outfit-latin-400-normal-BGsTXAXT.woff2 +0 -0
  851. package/out/web/assets/outfit-latin-400-normal-DMwTpYkH.woff +0 -0
  852. package/out/web/assets/outfit-latin-500-normal-ClnHRwRh.woff +0 -0
  853. package/out/web/assets/outfit-latin-500-normal-DKnIMDSk.woff2 +0 -0
  854. package/out/web/assets/outfit-latin-600-normal-B7SfZ07L.woff2 +0 -0
  855. package/out/web/assets/outfit-latin-600-normal-BEfTtDA7.woff +0 -0
  856. package/out/web/assets/outfit-latin-ext-300-normal-BYS6Dpvq.woff2 +0 -0
  857. package/out/web/assets/outfit-latin-ext-300-normal-CMIMshEd.woff +0 -0
  858. package/out/web/assets/outfit-latin-ext-400-normal-5tcqmc2S.woff2 +0 -0
  859. package/out/web/assets/outfit-latin-ext-400-normal-DHm7mdGe.woff +0 -0
  860. package/out/web/assets/outfit-latin-ext-500-normal-DrCvqoFD.woff +0 -0
  861. package/out/web/assets/outfit-latin-ext-500-normal-zeox_O30.woff2 +0 -0
  862. package/out/web/assets/outfit-latin-ext-600-normal-B85nYjL1.woff2 +0 -0
  863. package/out/web/assets/outfit-latin-ext-600-normal-CWJcPgd7.woff +0 -0
  864. package/out/web/assets/preload-helper-D0uHx7FM.js +0 -1
  865. package/out/web/assets/prompt-latin-400-normal-BQ9zjSN8.woff2 +0 -0
  866. package/out/web/assets/prompt-latin-400-normal-CxU4ec_r.woff +0 -0
  867. package/out/web/assets/prompt-latin-500-normal-B1edBDQ9.woff +0 -0
  868. package/out/web/assets/prompt-latin-500-normal-CxzxEHZc.woff2 +0 -0
  869. package/out/web/assets/prompt-latin-600-normal-CSDDLorv.woff +0 -0
  870. package/out/web/assets/prompt-latin-600-normal-hKZWXsc1.woff2 +0 -0
  871. package/out/web/assets/prompt-latin-ext-400-normal-1pHbN9uy.woff +0 -0
  872. package/out/web/assets/prompt-latin-ext-400-normal-DdSafGZ9.woff2 +0 -0
  873. package/out/web/assets/prompt-latin-ext-500-normal--EZ1um7s.woff2 +0 -0
  874. package/out/web/assets/prompt-latin-ext-500-normal-D-lI1EVT.woff +0 -0
  875. package/out/web/assets/prompt-latin-ext-600-normal-C8b50x67.woff +0 -0
  876. package/out/web/assets/prompt-latin-ext-600-normal-Cg9L7iJU.woff2 +0 -0
  877. package/out/web/assets/prompt-thai-400-normal-BrkKv8cO.woff2 +0 -0
  878. package/out/web/assets/prompt-thai-400-normal-DJypnfr3.woff +0 -0
  879. package/out/web/assets/prompt-thai-500-normal-C18pDUoL.woff2 +0 -0
  880. package/out/web/assets/prompt-thai-500-normal-D7YNqUJD.woff +0 -0
  881. package/out/web/assets/prompt-thai-600-normal-CYPViXds.woff +0 -0
  882. package/out/web/assets/prompt-thai-600-normal-MrdfU7zR.woff2 +0 -0
  883. package/out/web/assets/prompt-vietnamese-400-normal-BCPzsgPT.woff2 +0 -0
  884. package/out/web/assets/prompt-vietnamese-400-normal-D4pLyeNK.woff +0 -0
  885. package/out/web/assets/prompt-vietnamese-500-normal-DmzxmPwa.woff2 +0 -0
  886. package/out/web/assets/prompt-vietnamese-500-normal-w_sS_j2F.woff +0 -0
  887. package/out/web/assets/prompt-vietnamese-600-normal-1dyohtNh.woff +0 -0
  888. package/out/web/assets/prompt-vietnamese-600-normal-7QWjJBsF.woff2 +0 -0
  889. package/out/web/assets/sarabun-latin-400-normal-DmguIS-7.woff +0 -0
  890. package/out/web/assets/sarabun-latin-400-normal-URPBxl-K.woff2 +0 -0
  891. package/out/web/assets/sarabun-latin-500-normal-BjUTcdxu.woff2 +0 -0
  892. package/out/web/assets/sarabun-latin-500-normal-CJexTAnl.woff +0 -0
  893. package/out/web/assets/sarabun-latin-600-normal-9FonlkKx.woff +0 -0
  894. package/out/web/assets/sarabun-latin-600-normal-DMD3TROr.woff2 +0 -0
  895. package/out/web/assets/sarabun-latin-ext-400-normal-BbP7GpLL.woff2 +0 -0
  896. package/out/web/assets/sarabun-latin-ext-400-normal-BsmTn0SS.woff +0 -0
  897. package/out/web/assets/sarabun-latin-ext-500-normal-Cot16Bd2.woff +0 -0
  898. package/out/web/assets/sarabun-latin-ext-500-normal-DE1LysqI.woff2 +0 -0
  899. package/out/web/assets/sarabun-latin-ext-600-normal-0tXu9x_i.woff +0 -0
  900. package/out/web/assets/sarabun-latin-ext-600-normal-BRxjKUQ6.woff2 +0 -0
  901. package/out/web/assets/sarabun-thai-400-normal-C2DaJlKK.woff2 +0 -0
  902. package/out/web/assets/sarabun-thai-400-normal-CH-UbWgg.woff +0 -0
  903. package/out/web/assets/sarabun-thai-500-normal-BVssjame.woff2 +0 -0
  904. package/out/web/assets/sarabun-thai-500-normal-C3iDLEzi.woff +0 -0
  905. package/out/web/assets/sarabun-thai-600-normal-3dIAQ-_s.woff2 +0 -0
  906. package/out/web/assets/sarabun-thai-600-normal-DWKeTe6a.woff +0 -0
  907. package/out/web/assets/sarabun-vietnamese-400-normal-DPfkSCMy.woff +0 -0
  908. package/out/web/assets/sarabun-vietnamese-400-normal-igdrzAGY.woff2 +0 -0
  909. package/out/web/assets/sarabun-vietnamese-500-normal-CpRVvGRU.woff +0 -0
  910. package/out/web/assets/sarabun-vietnamese-500-normal-Dpe7Br9m.woff2 +0 -0
  911. package/out/web/assets/sarabun-vietnamese-600-normal-BMbOgAW-.woff +0 -0
  912. package/out/web/assets/sarabun-vietnamese-600-normal-DkxrOlLB.woff2 +0 -0
  913. package/out/web/assets/stateDiagram-v2-4QOOHH4V-s6P9g2_b.js +0 -1
  914. package/out/web/assets/swimlanesDiagram-VK2B7HYN-CV9fOLrV.js +0 -8
  915. package/out/web/assets/tauri-CNrHQ2Gb.js +0 -3
  916. package/out/web/assets/window-DkIhgI7B.js +0 -1
  917. package/skills-lock.json +0 -41
  918. package/src/renderer/public/Live2DCubismCore.js +0 -9
  919. package/src/renderer/src/companionWidget.ts +0 -95
  920. package/src/renderer/src/components/Live2DStage.tsx +0 -389
  921. package/src/renderer/src/components/ModelPanel.tsx +0 -154
  922. package/src/renderer/src/css/model.css +0 -627
  923. package/src/renderer/src-web/companionWidget.ts +0 -37
  924. package/src/renderer/src-web/components/ModelPanel.tsx +0 -12
  925. package/src/renderer/src-web/css/model.css +0 -628
@@ -1,3 +1,4 @@
1
+ import SelectField from '../SelectField'
1
2
  import React from 'react'
2
3
  import { DEFAULT_CONFIG } from '../../constants/config'
3
4
  import {
@@ -11,6 +12,7 @@ import {
11
12
  IMAGE_STUDIO_MODELS,
12
13
  IMAGE_GEN_PROVIDER_MODELS,
13
14
  VEO_STUDIO_MODELS,
15
+ getModelMetadata,
14
16
  } from '../../constants/models'
15
17
  import type {
16
18
  CustomProviderConfig,
@@ -20,6 +22,47 @@ import type {
20
22
  import { setActiveModel } from '../../utils/modelManager'
21
23
  import { providerLabel as aiProviderLabel } from '../../utils/providers'
22
24
  import ApiKeyInput from './ApiKeyInput'
25
+ import SearchableModelCombobox from './SearchableModelCombobox'
26
+ import anthropicLogo from '@lobehub/icons-static-svg/icons/anthropic.svg?url'
27
+ import deepseekLogo from '@lobehub/icons-static-svg/icons/deepseek-color.svg?url'
28
+ import geminiLogo from '@lobehub/icons-static-svg/icons/gemini-color.svg?url'
29
+ import huggingFaceLogo from '@lobehub/icons-static-svg/icons/huggingface-color.svg?url'
30
+ import lmStudioLogo from '@lobehub/icons-static-svg/icons/lmstudio.svg?url'
31
+ import ollamaLogo from '@lobehub/icons-static-svg/icons/ollama.svg?url'
32
+ import openAiLogo from '@lobehub/icons-static-svg/icons/openai.svg?url'
33
+ import openRouterLogo from '@lobehub/icons-static-svg/icons/openrouter-color.svg?url'
34
+
35
+ const settingsProviderLogos: Record<string, { src: string; color?: string }> = {
36
+ anthropic: { src: anthropicLogo, color: '#d97757' },
37
+ deepseek: { src: deepseekLogo },
38
+ gemini: { src: geminiLogo },
39
+ huggingface: { src: huggingFaceLogo },
40
+ local_openai: { src: lmStudioLogo, color: '#8b5cf6' },
41
+ ollama: { src: ollamaLogo, color: '#f3f4f6' },
42
+ openai: { src: openAiLogo, color: '#10a37f' },
43
+ openrouter: { src: openRouterLogo },
44
+ }
45
+
46
+ function SettingsProviderLogo({ provider }: { provider: string }) {
47
+ const logo = settingsProviderLogos[provider]
48
+ if (!logo) return null
49
+
50
+ if (logo.color) {
51
+ return (
52
+ <span
53
+ className="settings-provider-logo is-monochrome"
54
+ aria-hidden="true"
55
+ style={{
56
+ '--provider-brand-color': logo.color,
57
+ maskImage: `url("${logo.src}")`,
58
+ WebkitMaskImage: `url("${logo.src}")`,
59
+ } as React.CSSProperties}
60
+ />
61
+ )
62
+ }
63
+
64
+ return <img className="settings-provider-logo" src={logo.src} alt="" aria-hidden="true" />
65
+ }
23
66
 
24
67
  // One card per image-gen provider (mirrors the chat "Provider & Model"
25
68
  // cards): a model dropdown plus either its own API-key field, or a note
@@ -144,6 +187,7 @@ export default function GeneralTab({
144
187
  onSaveWithoutClosing
145
188
  }: GeneralTabProps) {
146
189
  const [savedProviderId, setSavedProviderId] = React.useState<string | null>(null)
190
+ const [providerLogoErrors, setProviderLogoErrors] = React.useState<Record<string, string>>({})
147
191
  const [openSections, setOpenSections] = React.useState<Record<string, boolean>>({
148
192
  ai_routing: true,
149
193
  search: false,
@@ -180,6 +224,42 @@ export default function GeneralTab({
180
224
  }
181
225
  }
182
226
 
227
+ const handleProviderLogoChange = (providerId: string, file?: File) => {
228
+ if (!file) return
229
+ const supportedTypes = ['image/png', 'image/jpeg', 'image/webp']
230
+ if (!supportedTypes.includes(file.type)) {
231
+ setProviderLogoErrors(prev => ({ ...prev, [providerId]: 'Choose a PNG, JPEG, or WebP image.' }))
232
+ return
233
+ }
234
+ if (file.size > 256 * 1024) {
235
+ setProviderLogoErrors(prev => ({ ...prev, [providerId]: 'The logo must be 256 KB or smaller.' }))
236
+ return
237
+ }
238
+
239
+ const reader = new FileReader()
240
+ reader.onload = () => {
241
+ if (typeof reader.result !== 'string') {
242
+ setProviderLogoErrors(prev => ({ ...prev, [providerId]: 'Could not read this image.' }))
243
+ return
244
+ }
245
+ const provider = (config.customProviders ?? []).find(item => item.id === providerId)
246
+ if (!provider) return
247
+ const updated = (config.customProviders ?? []).map(item =>
248
+ item.id === providerId ? { ...item, logoDataUrl: reader.result as string } : item
249
+ )
250
+ updateField('customProviders', updated)
251
+ setProviderLogoErrors(prev => {
252
+ const next = { ...prev }
253
+ delete next[providerId]
254
+ return next
255
+ })
256
+ }
257
+ reader.onerror = () => {
258
+ setProviderLogoErrors(prev => ({ ...prev, [providerId]: 'Could not read this image.' }))
259
+ }
260
+ reader.readAsDataURL(file)
261
+ }
262
+
183
263
  const renderCollapsibleSection = (
184
264
  key: string,
185
265
  kicker: string,
@@ -238,8 +318,8 @@ export default function GeneralTab({
238
318
  <div className="tab-pane active">
239
319
  {/* Accordion Quick Control Bar */}
240
320
  <div className="accordion-controls">
241
- <button type="button" onClick={() => setAllSections(true)}>Expand All</button>
242
- <button type="button" onClick={() => setAllSections(false)}>Collapse All</button>
321
+ <button type="button" onClick={() => setAllSections(true)}>Expand all</button>
322
+ <button type="button" onClick={() => setAllSections(false)}>Collapse all</button>
243
323
  </div>
244
324
 
245
325
  {/* ── Section 1: AI Routing ── */}
@@ -251,8 +331,8 @@ export default function GeneralTab({
251
331
  <>
252
332
  <div className="form-grid compact">
253
333
  <div className="setting-row stacked">
254
- <label>Active Provider</label>
255
- <div className="pill-segmented" role="radiogroup" aria-label="Active Provider">
334
+ <label>Active provider</label>
335
+ <div className="pill-segmented" role="radiogroup" aria-label="Active provider">
256
336
  {[
257
337
  { id: 'gemini', label: aiProviderLabel('gemini'), title: 'Google Gemini (Cloud)' },
258
338
  { id: 'anthropic', label: aiProviderLabel('anthropic'), title: 'Anthropic Claude' },
@@ -289,12 +369,12 @@ export default function GeneralTab({
289
369
  const currentModel = (config.customModelSelections ?? {})[activeId] ?? cp.models[0]?.modelId ?? ''
290
370
  return (
291
371
  <div className="setting-row wide">
292
- <label>Active Model</label>
293
- <select
372
+ <label>Active model</label>
373
+ <SelectField aria-label="Active model"
294
374
  value={currentModel}
295
- onChange={(e) => updateField('customModelSelections', {
375
+ onValueChange={(nextValue) => updateField('customModelSelections', {
296
376
  ...(config.customModelSelections ?? {}),
297
- [activeId]: e.target.value
377
+ [activeId]: nextValue
298
378
  })}
299
379
  >
300
380
  {cp.models.map(m => (
@@ -302,7 +382,7 @@ export default function GeneralTab({
302
382
  {m.displayName || m.modelId}
303
383
  </option>
304
384
  ))}
305
- </select>
385
+ </SelectField>
306
386
  </div>
307
387
  )
308
388
  })()}
@@ -413,10 +493,10 @@ export default function GeneralTab({
413
493
  }
414
494
 
415
495
  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)' }}>
496
+ <div className="setting-row stacked setting-feature-card">
417
497
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.35rem' }}>
418
498
  <label style={{ margin: 0, fontWeight: 600, display: 'flex', alignItems: 'baseline', gap: '0.45rem' }}>
419
- <span>Model Temperature</span>
499
+ <span>Model temperature</span>
420
500
  {modelDisplayName && (
421
501
  <span style={{ fontSize: '0.8rem', fontWeight: 500, color: 'var(--text-muted)' }}>
422
502
  · {modelDisplayName}
@@ -448,13 +528,13 @@ export default function GeneralTab({
448
528
  step="0.05"
449
529
  value={currentTemp}
450
530
  onChange={(e) => handleChange(parseFloat(e.target.value))}
451
- style={{ flex: 1, accentColor: 'var(--accent-color, #10b981)', cursor: 'pointer' }}
531
+ style={{ flex: 1, accentColor: 'var(--accent, #10b981)', cursor: 'pointer' }}
452
532
  />
453
533
  <span style={{ fontSize: '0.85rem', minWidth: '2.5rem', textAlign: 'right', fontFamily: 'monospace', fontWeight: 600 }}>
454
534
  {currentTemp.toFixed(2)}
455
535
  </span>
456
536
  </div>
457
- <span style={{ fontSize: '0.75rem', opacity: 0.75, marginTop: '0.35rem', lineHeight: 1.4 }}>
537
+ <span style={{ fontSize: '0.75rem', color: 'var(--text-muted)', marginTop: '0.35rem', lineHeight: 1.4 }}>
458
538
  Controls sampling entropy for <strong>{modelDisplayName || activeModelRaw}</strong>. {
459
539
  isReasoningOmit
460
540
  ? 'Reasoning models (o1/o3) automatically omit this parameter.'
@@ -468,6 +548,160 @@ export default function GeneralTab({
468
548
  </div>
469
549
  )
470
550
  })()}
551
+
552
+ {/* Thinking / Reasoning Configuration */}
553
+ {(() => {
554
+ const activeModelRaw = (() => {
555
+ if (config.aiProvider === 'gemini') return config.geminiModel || 'gemini-2.5-flash'
556
+ if (config.aiProvider === 'anthropic') return config.anthropicModel || 'claude-sonnet-5'
557
+ if (config.aiProvider === 'openai') return config.openaiModel || 'gpt-5.6-luna'
558
+ if (config.aiProvider === 'openrouter') return config.openrouterModel || 'openai/gpt-5.6-terra'
559
+ if (config.aiProvider === 'deepseek') return config.deepseekModel || 'deepseek-chat'
560
+ if (config.aiProvider === 'local_openai') return config.localModelName || 'local-model'
561
+ if (config.aiProvider === 'ollama') return config.ollamaModel || 'llama3'
562
+ if (config.aiProvider === 'huggingface') return config.hfModel || 'Qwen/Qwen3.6-27B'
563
+ return ''
564
+ })()
565
+
566
+ const meta = getModelMetadata(activeModelRaw, config.aiProvider)
567
+ const modelConfigs = (config.modelThinkingConfigs ?? {}) as Record<string, { enabled?: boolean; effort?: string }>
568
+ const customModelThinking = activeModelRaw ? modelConfigs[activeModelRaw] : undefined
569
+ const hasCustomModel = customModelThinking !== undefined
570
+
571
+ const isThinkingSupported = meta.supportsThinking
572
+ const currentEnabled = customModelThinking?.enabled !== undefined
573
+ ? customModelThinking.enabled
574
+ : (config.thinkingEnabled ?? true)
575
+
576
+ const currentEffort = (customModelThinking?.effort || config.thinkingEffort || 'medium').toLowerCase()
577
+
578
+ const handleResetThinking = () => {
579
+ if (activeModelRaw && modelConfigs[activeModelRaw] !== undefined) {
580
+ const updated = { ...modelConfigs }
581
+ delete updated[activeModelRaw]
582
+ updateField('modelThinkingConfigs', updated)
583
+ }
584
+ }
585
+
586
+ const handleToggleThinking = (enabled: boolean) => {
587
+ if (activeModelRaw) {
588
+ const updated = {
589
+ ...modelConfigs,
590
+ [activeModelRaw]: { enabled, effort: currentEffort },
591
+ }
592
+ updateField('modelThinkingConfigs', updated)
593
+ }
594
+ updateField('thinkingEnabled', enabled)
595
+ }
596
+
597
+ const handleEffortChange = (effort: string) => {
598
+ if (activeModelRaw) {
599
+ const updated = {
600
+ ...modelConfigs,
601
+ [activeModelRaw]: { enabled: currentEnabled, effort },
602
+ }
603
+ updateField('modelThinkingConfigs', updated)
604
+ }
605
+ updateField('thinkingEffort', effort)
606
+ }
607
+
608
+ const effortLabelMap: Record<string, string> = {
609
+ low: 'Low',
610
+ medium: 'Medium',
611
+ high: 'High',
612
+ extra_high: 'Extra High',
613
+ }
614
+
615
+ return (
616
+ <div className="setting-row stacked setting-feature-card">
617
+ <div className="thinking-card-header" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.5rem' }}>
618
+ <label className="thinking-card-title" style={{ margin: 0, fontWeight: 600, display: 'flex', alignItems: 'center', gap: '0.45rem' }}>
619
+ <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)' }}>
620
+ <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" />
621
+ <path d="M9 21h6" />
622
+ </svg>
623
+ <span>Thinking / Reasoning</span>
624
+ {activeModelRaw && (
625
+ <span style={{ fontSize: '0.8rem', fontWeight: 500, color: 'var(--text-muted)' }}>
626
+ · {activeModelRaw.split('/').pop()}
627
+ </span>
628
+ )}
629
+ </label>
630
+ <div className="thinking-card-status" style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
631
+ <span className="section-current-badge" style={{ fontSize: '0.75rem' }}>
632
+ {currentEnabled
633
+ ? `Thinking ON (${effortLabelMap[currentEffort] || 'Medium'})${!isThinkingSupported ? ' · Force' : ''}`
634
+ : 'Thinking OFF'}
635
+ </span>
636
+ {hasCustomModel && (
637
+ <button
638
+ type="button"
639
+ className="btn-secondary btn-small"
640
+ style={{ padding: '0.15rem 0.45rem', fontSize: '0.75rem' }}
641
+ onClick={handleResetThinking}
642
+ title={`Reset ${activeModelRaw} thinking configuration`}
643
+ >
644
+ Reset
645
+ </button>
646
+ )}
647
+ </div>
648
+ </div>
649
+
650
+ {/* Toggle Row */}
651
+ <div className="thinking-card-toggle-row" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '0.4rem 0' }}>
652
+ <div>
653
+ <span style={{ fontSize: '0.82rem', fontWeight: 500 }}>Enable thinking</span>
654
+ <p style={{ margin: '2px 0 0 0', fontSize: '0.73rem', color: 'var(--text-muted)' }}>
655
+ {isThinkingSupported
656
+ ? 'Allow model to output chain-of-thought tokens.'
657
+ : currentEnabled
658
+ ? 'Chain-of-thought token generation enabled (force toggle).'
659
+ : 'Model not flagged as reasoning by default — toggle on to force enable.'}
660
+ </p>
661
+ </div>
662
+ <label className="settings-toggle-switch">
663
+ <input
664
+ type="checkbox"
665
+ checked={currentEnabled}
666
+ onChange={(e) => handleToggleThinking(e.target.checked)}
667
+ />
668
+ <span className="settings-toggle-slider"></span>
669
+ </label>
670
+ </div>
671
+
672
+ {/* Effort Level Row */}
673
+ {currentEnabled && (
674
+ <div style={{ marginTop: '0.5rem', paddingTop: '0.5rem', borderTop: '1px solid var(--border)' }}>
675
+ <div className="thinking-card-effort-row" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
676
+ <span style={{ fontSize: '0.78rem', fontWeight: 600, color: 'var(--text-muted)', textTransform: 'none', letterSpacing: '0.04em' }}>
677
+ Reasoning Effort
678
+ </span>
679
+ <div className="thinking-card-effort-options" style={{ display: 'flex', gap: '4px' }}>
680
+ {(['low', 'medium', 'high', 'extra_high'] as const).map((eff) => (
681
+ <button
682
+ key={eff}
683
+ type="button"
684
+ className={`btn-secondary btn-small ${currentEffort === eff ? 'active' : ''}`}
685
+ style={{
686
+ padding: '0.2rem 0.6rem',
687
+ fontSize: '0.75rem',
688
+ fontWeight: currentEffort === eff ? 600 : 400,
689
+ background: currentEffort === eff ? 'rgba(16, 185, 129, 0.15)' : undefined,
690
+ borderColor: currentEffort === eff ? 'var(--accent, #10b981)' : undefined,
691
+ color: currentEffort === eff ? 'var(--accent, #10b981)' : undefined,
692
+ }}
693
+ onClick={() => handleEffortChange(eff)}
694
+ >
695
+ {effortLabelMap[eff]}
696
+ </button>
697
+ ))}
698
+ </div>
699
+ </div>
700
+ </div>
701
+ )}
702
+ </div>
703
+ )
704
+ })()}
471
705
  </div>
472
706
 
473
707
  <div className="provider-cards-container">
@@ -475,9 +709,7 @@ export default function GeneralTab({
475
709
  <div className={`provider-card ${config.aiProvider === 'gemini' ? 'active-provider' : ''}`}>
476
710
  <div className="provider-card-header">
477
711
  <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>
712
+ <SettingsProviderLogo provider="gemini" />
481
713
  Google Gemini (Cloud)
482
714
  </div>
483
715
  <div className="provider-card-actions">
@@ -492,20 +724,20 @@ export default function GeneralTab({
492
724
  </div>
493
725
  <div className="provider-card-body">
494
726
  <div className="setting-row">
495
- <label>Gemini Model</label>
496
- <select
727
+ <label>Gemini model</label>
728
+ <SelectField aria-label="Gemini model"
497
729
  value={dynamicGeminiModels.includes(config.geminiModel) ? config.geminiModel : 'custom'}
498
- onChange={(e) => updateField('geminiModel', e.target.value)}
730
+ onValueChange={(nextValue) => updateField('geminiModel', nextValue)}
499
731
  >
500
732
  {dynamicGeminiModels.map(model => (
501
733
  <option key={model} value={model}>{model}</option>
502
734
  ))}
503
735
  <option value="custom">Custom...</option>
504
- </select>
736
+ </SelectField>
505
737
  </div>
506
738
  {(!dynamicGeminiModels.includes(config.geminiModel) || config.geminiModel === 'custom') && (
507
739
  <div className="setting-row">
508
- <label>Custom Gemini Model</label>
740
+ <label>Custom Gemini model</label>
509
741
  <input
510
742
  type="text"
511
743
  value={customGemini}
@@ -529,10 +761,7 @@ export default function GeneralTab({
529
761
  <div className={`provider-card ${config.aiProvider === 'anthropic' ? 'active-provider' : ''}`}>
530
762
  <div className="provider-card-header">
531
763
  <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>
764
+ <SettingsProviderLogo provider="anthropic" />
536
765
  Anthropic Claude
537
766
  </div>
538
767
  <div className="provider-card-actions">
@@ -547,20 +776,20 @@ export default function GeneralTab({
547
776
  </div>
548
777
  <div className="provider-card-body">
549
778
  <div className="setting-row">
550
- <label>Anthropic Model</label>
551
- <select
779
+ <label>Anthropic model</label>
780
+ <SelectField aria-label="Anthropic model"
552
781
  value={dynamicAnthropicModels.includes(config.anthropicModel) ? config.anthropicModel : 'custom'}
553
- onChange={(e) => updateField('anthropicModel', e.target.value)}
782
+ onValueChange={(nextValue) => updateField('anthropicModel', nextValue)}
554
783
  >
555
784
  {dynamicAnthropicModels.map(model => (
556
785
  <option key={model} value={model}>{model}</option>
557
786
  ))}
558
787
  <option value="custom">Custom...</option>
559
- </select>
788
+ </SelectField>
560
789
  </div>
561
790
  {(!dynamicAnthropicModels.includes(config.anthropicModel) || config.anthropicModel === 'custom') && (
562
791
  <div className="setting-row">
563
- <label>Custom Anthropic Model</label>
792
+ <label>Custom Anthropic model</label>
564
793
  <input
565
794
  type="text"
566
795
  value={customAnthropic}
@@ -584,11 +813,7 @@ export default function GeneralTab({
584
813
  <div className={`provider-card ${config.aiProvider === 'openai' ? 'active-provider' : ''}`}>
585
814
  <div className="provider-card-header">
586
815
  <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>
816
+ <SettingsProviderLogo provider="openai" />
592
817
  OpenAI
593
818
  </div>
594
819
  <div className="provider-card-actions">
@@ -604,19 +829,19 @@ export default function GeneralTab({
604
829
  <div className="provider-card-body">
605
830
  <div className="setting-row">
606
831
  <label>OpenAI Model</label>
607
- <select
832
+ <SelectField aria-label="OpenAI Model"
608
833
  value={dynamicOpenAIModels.includes(config.openaiModel) ? config.openaiModel : 'custom'}
609
- onChange={(e) => updateField('openaiModel', e.target.value)}
834
+ onValueChange={(nextValue) => updateField('openaiModel', nextValue)}
610
835
  >
611
836
  {dynamicOpenAIModels.map(model => (
612
837
  <option key={model} value={model}>{model}</option>
613
838
  ))}
614
839
  <option value="custom">Custom...</option>
615
- </select>
840
+ </SelectField>
616
841
  </div>
617
842
  {(!dynamicOpenAIModels.includes(config.openaiModel) || config.openaiModel === 'custom') && (
618
843
  <div className="setting-row">
619
- <label>Custom OpenAI Model</label>
844
+ <label>Custom OpenAI model</label>
620
845
  <input
621
846
  type="text"
622
847
  value={customOpenAI}
@@ -640,13 +865,7 @@ export default function GeneralTab({
640
865
  <div className={`provider-card ${config.aiProvider === 'openrouter' ? 'active-provider' : ''}`}>
641
866
  <div className="provider-card-header">
642
867
  <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>
868
+ <SettingsProviderLogo provider="openrouter" />
650
869
  OpenRouter
651
870
  </div>
652
871
  <div className="provider-card-actions">
@@ -662,19 +881,21 @@ export default function GeneralTab({
662
881
  <div className="provider-card-body">
663
882
  <div className="setting-row">
664
883
  <label>OpenRouter Model</label>
665
- <select
884
+ <SearchableModelCombobox
666
885
  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>
886
+ models={dynamicOpenRouterModels}
887
+ onChange={(val) => updateField('openrouterModel', val)}
888
+ onCustomChange={(val) => {
889
+ setCustomOpenRouter(val)
890
+ updateField('openrouterModel', 'custom')
891
+ }}
892
+ customValue={customOpenRouter}
893
+ placeholder="Select or search OpenRouter model..."
894
+ />
674
895
  </div>
675
896
  {(!dynamicOpenRouterModels.includes(config.openrouterModel) || config.openrouterModel === 'custom') && (
676
897
  <div className="setting-row">
677
- <label>Custom OpenRouter Model</label>
898
+ <label>Custom OpenRouter model</label>
678
899
  <input
679
900
  type="text"
680
901
  value={customOpenRouter}
@@ -698,10 +919,7 @@ export default function GeneralTab({
698
919
  <div className={`provider-card ${config.aiProvider === 'deepseek' ? 'active-provider' : ''}`}>
699
920
  <div className="provider-card-header">
700
921
  <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>
922
+ <SettingsProviderLogo provider="deepseek" />
705
923
  DeepSeek
706
924
  </div>
707
925
  <div className="provider-card-actions">
@@ -717,19 +935,19 @@ export default function GeneralTab({
717
935
  <div className="provider-card-body">
718
936
  <div className="setting-row">
719
937
  <label>DeepSeek Model</label>
720
- <select
938
+ <SelectField aria-label="DeepSeek Model"
721
939
  value={dynamicDeepSeekModels.includes(config.deepseekModel) ? config.deepseekModel : 'custom'}
722
- onChange={(e) => updateField('deepseekModel', e.target.value)}
940
+ onValueChange={(nextValue) => updateField('deepseekModel', nextValue)}
723
941
  >
724
942
  {dynamicDeepSeekModels.map(model => (
725
943
  <option key={model} value={model}>{model}</option>
726
944
  ))}
727
945
  <option value="custom">Custom...</option>
728
- </select>
946
+ </SelectField>
729
947
  </div>
730
948
  {(!dynamicDeepSeekModels.includes(config.deepseekModel) || config.deepseekModel === 'custom') && (
731
949
  <div className="setting-row">
732
- <label>Custom DeepSeek Model</label>
950
+ <label>Custom DeepSeek model</label>
733
951
  <input
734
952
  type="text"
735
953
  value={customDeepSeek}
@@ -753,12 +971,7 @@ export default function GeneralTab({
753
971
  <div className={`provider-card ${config.aiProvider === 'huggingface' ? 'active-provider' : ''}`}>
754
972
  <div className="provider-card-header">
755
973
  <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>
974
+ <SettingsProviderLogo provider="huggingface" />
762
975
  Hugging Face (Inference API)
763
976
  </div>
764
977
  <div className="provider-card-actions">
@@ -773,20 +986,20 @@ export default function GeneralTab({
773
986
  </div>
774
987
  <div className="provider-card-body">
775
988
  <div className="setting-row">
776
- <label>Hugging Face Model</label>
777
- <select
989
+ <label>Hugging Face model</label>
990
+ <SelectField aria-label="Hugging Face model"
778
991
  value={(HF_MODELS as readonly string[]).includes(config.hfModel) ? config.hfModel : 'custom'}
779
- onChange={(e) => updateField('hfModel', e.target.value)}
992
+ onValueChange={(nextValue) => updateField('hfModel', nextValue)}
780
993
  >
781
994
  {HF_MODELS.map(model => (
782
995
  <option key={model} value={model}>{model}</option>
783
996
  ))}
784
997
  <option value="custom">Custom...</option>
785
- </select>
998
+ </SelectField>
786
999
  </div>
787
1000
  {(!(HF_MODELS as readonly string[]).includes(config.hfModel) || config.hfModel === 'custom') && (
788
1001
  <div className="setting-row">
789
- <label>Custom Hugging Face Model</label>
1002
+ <label>Custom Hugging Face model</label>
790
1003
  <input
791
1004
  type="text"
792
1005
  value={customHF}
@@ -796,11 +1009,11 @@ export default function GeneralTab({
796
1009
  </div>
797
1010
  )}
798
1011
  <div className="setting-row">
799
- <label>Hugging Face API Key</label>
1012
+ <label>Hugging Face API key</label>
800
1013
  <ApiKeyInput
801
1014
  value={config.hfApiKey}
802
1015
  onChange={(value) => updateField('hfApiKey', value)}
803
- placeholder="Enter Hugging Face API Key..."
1016
+ placeholder="Enter Hugging Face API key..."
804
1017
  />
805
1018
  </div>
806
1019
  </div>
@@ -810,11 +1023,7 @@ export default function GeneralTab({
810
1023
  <div className={`provider-card ${config.aiProvider === 'local_openai' ? 'active-provider' : ''}`}>
811
1024
  <div className="provider-card-header">
812
1025
  <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>
1026
+ <SettingsProviderLogo provider="local_openai" />
818
1027
  LM Studio / Local OpenAI
819
1028
  </div>
820
1029
  <div className="provider-card-actions">
@@ -830,15 +1039,15 @@ export default function GeneralTab({
830
1039
  <div className="provider-card-body">
831
1040
  <div className="setting-row">
832
1041
  <label>LM Studio Model</label>
833
- <select
1042
+ <SelectField aria-label="LM Studio Model"
834
1043
  value={dynamicLocalModels.includes(config.localModelName) ? config.localModelName : 'custom'}
835
- onChange={(e) => updateField('localModelName', e.target.value)}
1044
+ onValueChange={(nextValue) => updateField('localModelName', nextValue)}
836
1045
  >
837
1046
  {dynamicLocalModels.map(model => (
838
1047
  <option key={model} value={model}>{model}</option>
839
1048
  ))}
840
1049
  <option value="custom">Custom...</option>
841
- </select>
1050
+ </SelectField>
842
1051
  </div>
843
1052
  {(!dynamicLocalModels.includes(config.localModelName) || config.localModelName === 'custom') && (
844
1053
  <div className="setting-row">
@@ -867,9 +1076,7 @@ export default function GeneralTab({
867
1076
  <div className={`provider-card ${config.aiProvider === 'ollama' ? 'active-provider' : ''}`}>
868
1077
  <div className="provider-card-header">
869
1078
  <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>
1079
+ <SettingsProviderLogo provider="ollama" />
873
1080
  Ollama (Local)
874
1081
  </div>
875
1082
  <div className="provider-card-actions">
@@ -884,10 +1091,10 @@ export default function GeneralTab({
884
1091
  </div>
885
1092
  <div className="provider-card-body">
886
1093
  <div className="setting-row">
887
- <label>Ollama Model</label>
888
- <select
1094
+ <label>Ollama model</label>
1095
+ <SelectField aria-label="Ollama model"
889
1096
  value={dynamicOllamaModels.includes(config.ollamaModel) ? config.ollamaModel : 'custom'}
890
- onChange={(e) => updateField('ollamaModel', e.target.value)}
1097
+ onValueChange={(nextValue) => updateField('ollamaModel', nextValue)}
891
1098
  >
892
1099
  {dynamicOllamaModels.map(model => (
893
1100
  <option key={model} value={model}>{model}</option>
@@ -896,11 +1103,11 @@ export default function GeneralTab({
896
1103
  <option value={config.ollamaModel}>{config.ollamaModel}</option>
897
1104
  )}
898
1105
  <option value="custom">Custom...</option>
899
- </select>
1106
+ </SelectField>
900
1107
  </div>
901
1108
  {(!dynamicOllamaModels.includes(config.ollamaModel) || config.ollamaModel === 'custom') && (
902
1109
  <div className="setting-row">
903
- <label>Custom Ollama Model</label>
1110
+ <label>Custom Ollama model</label>
904
1111
  <input
905
1112
  type="text"
906
1113
  value={customOllama}
@@ -910,7 +1117,7 @@ export default function GeneralTab({
910
1117
  </div>
911
1118
  )}
912
1119
  <div className="setting-row">
913
- <label>Ollama Host</label>
1120
+ <label>Ollama host</label>
914
1121
  <input
915
1122
  type="text"
916
1123
  value={config.ollamaHost}
@@ -953,11 +1160,11 @@ export default function GeneralTab({
953
1160
  </div>
954
1161
  <div className="provider-card-body">
955
1162
  <div className="setting-row">
956
- <label>Brave Search API Key</label>
1163
+ <label>Brave Search API key</label>
957
1164
  <ApiKeyInput
958
1165
  value={config.braveSearchApiKey}
959
1166
  onChange={(value) => updateField('braveSearchApiKey', value)}
960
- placeholder="Enter Brave Search API Key..."
1167
+ placeholder="Enter Brave Search API key..."
961
1168
  />
962
1169
  </div>
963
1170
  </div>
@@ -985,15 +1192,15 @@ export default function GeneralTab({
985
1192
  </div>
986
1193
  <div className="provider-card-body">
987
1194
  <div className="setting-row">
988
- <label>Google Search API Key</label>
1195
+ <label>Google Search API key</label>
989
1196
  <ApiKeyInput
990
1197
  value={config.googleSearchApiKey}
991
1198
  onChange={(value) => updateField('googleSearchApiKey', value)}
992
- placeholder="Enter Google Search API Key..."
1199
+ placeholder="Enter Google Search API key..."
993
1200
  />
994
1201
  </div>
995
1202
  <div className="setting-row">
996
- <label>Google Search Engine ID (CX)</label>
1203
+ <label>Google Search engine ID (CX)</label>
997
1204
  <input
998
1205
  type="text"
999
1206
  value={config.googleSearchCx}
@@ -1051,7 +1258,7 @@ export default function GeneralTab({
1051
1258
  <>
1052
1259
  <div className="form-grid compact">
1053
1260
  <div className="setting-row stacked">
1054
- <label>Active Provider</label>
1261
+ <label>Active provider</label>
1055
1262
  <div className="pill-segmented" role="radiogroup" aria-label="Image Provider">
1056
1263
  {IMAGE_PROVIDERS.map(o => (
1057
1264
  <button
@@ -1102,14 +1309,14 @@ export default function GeneralTab({
1102
1309
  {modelField && opts.length > 0 && (
1103
1310
  <div className="setting-row">
1104
1311
  <label>{prov.label} Model</label>
1105
- <select value={currentModel} onChange={(e) => updateField(modelField, e.target.value)}>
1312
+ <SelectField aria-label="Model" value={currentModel} onValueChange={(nextValue) => updateField(modelField, nextValue)}>
1106
1313
  {opts.map(m => (
1107
1314
  <option key={m.value} value={m.value}>{m.label}</option>
1108
1315
  ))}
1109
1316
  {currentModel && !opts.some(m => m.value === currentModel) && (
1110
1317
  <option key={currentModel} value={currentModel}>{currentModel}</option>
1111
1318
  )}
1112
- </select>
1319
+ </SelectField>
1113
1320
  </div>
1114
1321
  )}
1115
1322
  {prov.keyField ? (
@@ -1163,16 +1370,16 @@ export default function GeneralTab({
1163
1370
  <div className="provider-card-body">
1164
1371
  <p className="hint">Uses your Gemini API key — no extra key needed.</p>
1165
1372
  <div className="setting-row">
1166
- <label>Default Veo Model</label>
1373
+ <label>Default Veo model</label>
1167
1374
  {(() => {
1168
1375
  const veoOpts = dynamicVideoModels?.veo || VEO_STUDIO_MODELS.veo || []
1169
1376
  const currentVeoModel = config.veoModel || 'veo-3.1-generate-preview'
1170
1377
  return (
1171
- <select
1378
+ <SelectField aria-label="Default Veo model"
1172
1379
  value={currentVeoModel}
1173
- onChange={(e) => {
1174
- updateField('veoModel', e.target.value)
1175
- setActiveModel('veoModel', e.target.value, 'video')
1380
+ onValueChange={(nextValue) => {
1381
+ updateField('veoModel', nextValue)
1382
+ setActiveModel('veoModel', nextValue, 'video')
1176
1383
  }}
1177
1384
  >
1178
1385
  {veoOpts.map((m) => (
@@ -1181,7 +1388,7 @@ export default function GeneralTab({
1181
1388
  {currentVeoModel && !veoOpts.some((m) => m.value === currentVeoModel) && (
1182
1389
  <option key={currentVeoModel} value={currentVeoModel}>{currentVeoModel}</option>
1183
1390
  )}
1184
- </select>
1391
+ </SelectField>
1185
1392
  )
1186
1393
  })()}
1187
1394
  </div>
@@ -1243,9 +1450,13 @@ export default function GeneralTab({
1243
1450
  <div key={cpIdx} className={`provider-card ${isActive ? 'active-provider' : ''}`}>
1244
1451
  <div className="provider-card-header">
1245
1452
  <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>
1453
+ {cp.logoDataUrl ? (
1454
+ <img className="settings-provider-logo custom-provider-logo" src={cp.logoDataUrl} alt="" />
1455
+ ) : (
1456
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
1457
+ <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" />
1458
+ </svg>
1459
+ )}
1249
1460
  {cp.displayName || cp.id || 'Unnamed Provider'}
1250
1461
  </div>
1251
1462
  <div className="provider-card-actions">
@@ -1296,6 +1507,50 @@ export default function GeneralTab({
1296
1507
  />
1297
1508
  </div>
1298
1509
 
1510
+ <div className="setting-row">
1511
+ <label>Provider logo (optional)</label>
1512
+ <div className="custom-provider-logo-picker">
1513
+ <div className="custom-provider-logo-preview" aria-hidden="true">
1514
+ {cp.logoDataUrl ? (
1515
+ <img src={cp.logoDataUrl} alt="" />
1516
+ ) : (
1517
+ <span>Logo</span>
1518
+ )}
1519
+ </div>
1520
+ <label className="btn btn-secondary btn-xs custom-provider-logo-select">
1521
+ {cp.logoDataUrl ? 'Change image' : 'Choose image'}
1522
+ <input
1523
+ type="file"
1524
+ accept="image/png,image/jpeg,image/webp"
1525
+ onChange={(event) => {
1526
+ handleProviderLogoChange(cp.id, event.currentTarget.files?.[0])
1527
+ event.currentTarget.value = ''
1528
+ }}
1529
+ />
1530
+ </label>
1531
+ {cp.logoDataUrl && (
1532
+ <button
1533
+ type="button"
1534
+ className="btn btn-secondary btn-xs"
1535
+ onClick={() => {
1536
+ updateCp({ logoDataUrl: undefined })
1537
+ setProviderLogoErrors(prev => {
1538
+ const next = { ...prev }
1539
+ delete next[cp.id]
1540
+ return next
1541
+ })
1542
+ }}
1543
+ >
1544
+ Remove
1545
+ </button>
1546
+ )}
1547
+ <span className="custom-provider-logo-help">PNG, JPEG, or WebP · max 256 KB</span>
1548
+ {providerLogoErrors[cp.id] && (
1549
+ <span className="custom-provider-logo-error" role="alert">{providerLogoErrors[cp.id]}</span>
1550
+ )}
1551
+ </div>
1552
+ </div>
1553
+
1299
1554
  <div className="setting-row">
1300
1555
  <label>Base URL</label>
1301
1556
  <input
@@ -1417,11 +1672,11 @@ export default function GeneralTab({
1417
1672
  </div>
1418
1673
  <div className="form-grid single">
1419
1674
  <div className="setting-row">
1420
- <label>Updater Endpoint</label>
1675
+ <label>Updater endpoint</label>
1421
1676
  <input type="text" value={config.updaterEndpoint} onChange={(e) => updateField('updaterEndpoint', e.target.value)} placeholder="https://updates.example.com/latest.json" />
1422
1677
  </div>
1423
1678
  <div className="setting-row">
1424
- <label>Updater Public Key</label>
1679
+ <label>Updater public key</label>
1425
1680
  <textarea value={config.updaterPublicKey} onChange={(e) => updateField('updaterPublicKey', e.target.value)} placeholder="Minisign public key" />
1426
1681
  </div>
1427
1682
  </div>
@@ -1442,7 +1697,7 @@ export default function GeneralTab({
1442
1697
  'Configure the mini AI character desktop presence widget.',
1443
1698
  <div className="toggle-row">
1444
1699
  <div>
1445
- <label>Show Desktop AI Candidate</label>
1700
+ <label>Show Desktop AI candidate</label>
1446
1701
  <p className="hint">Show the mini AI character on your desktop.</p>
1447
1702
  </div>
1448
1703
  <label className="settings-toggle-switch">