@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,8 +1,16 @@
1
- import React, { useState, useEffect, useRef, useMemo } from 'react'
1
+ import React, { useState, useEffect, useRef, useMemo, useCallback } from 'react'
2
2
  import { useProviderModels } from '@/hooks/useProviderModels'
3
- import { fetchProviderModels } from '@/tauri'
4
- import { HF_MODELS } from '../constants/models'
3
+ import { catalogPlatform } from '../platform'
4
+ import { HF_MODELS, getModelMetadata, isFreeModel, OPENROUTER_POPULAR_MODELS } from '../constants/models'
5
5
  import type { CustomProviderConfig } from '../types'
6
+ import anthropicLogo from '@lobehub/icons-static-svg/icons/anthropic.svg?url'
7
+ import deepseekLogo from '@lobehub/icons-static-svg/icons/deepseek-color.svg?url'
8
+ import geminiLogo from '@lobehub/icons-static-svg/icons/gemini-color.svg?url'
9
+ import huggingFaceLogo from '@lobehub/icons-static-svg/icons/huggingface-color.svg?url'
10
+ import lmStudioLogo from '@lobehub/icons-static-svg/icons/lmstudio.svg?url'
11
+ import ollamaLogo from '@lobehub/icons-static-svg/icons/ollama.svg?url'
12
+ import openAiLogo from '@lobehub/icons-static-svg/icons/openai.svg?url'
13
+ import openRouterLogo from '@lobehub/icons-static-svg/icons/openrouter-color.svg?url'
6
14
 
7
15
  interface ModelSelectorPopoverProps {
8
16
  activeProvider: string
@@ -12,10 +20,12 @@ interface ModelSelectorPopoverProps {
12
20
  dynamicOllamaModels?: string[]
13
21
  onSelect: (provider: string, model: string) => void
14
22
  disabled?: boolean
23
+ onUpdateSettings?: (config: any) => void
15
24
  }
16
25
 
17
26
  interface ProviderGroup {
18
27
  id: string
28
+ providerId: string
19
29
  name: string
20
30
  icon: React.ReactNode
21
31
  models: string[]
@@ -27,92 +37,70 @@ interface FlattenedItem {
27
37
  model: string
28
38
  }
29
39
 
30
- // ─── SVG Icons for Providers (NO EMOJIS) ───────────────────────────────────────
40
+ const Effort_LEVELS = [
41
+ { id: 'low', label: 'Low' },
42
+ { id: 'medium', label: 'Medium' },
43
+ { id: 'high', label: 'High' },
44
+ { id: 'extra_high', label: 'Extra High' },
45
+ ] as const
46
+
47
+ function formatEffortDisplay(effort?: string): string {
48
+ if (!effort) return 'Medium'
49
+ const lower = effort.toLowerCase().replace(/[- ]/g, '_')
50
+ if (lower === 'low') return 'Low'
51
+ if (lower === 'high') return 'High'
52
+ if (lower === 'extra_high' || lower === 'extra') return 'Extra High'
53
+ return 'Medium'
54
+ }
55
+
56
+ // Brand marks are bundled locally so the selector never depends on a remote image host.
57
+ const providerLogos: Record<string, { src: string; color?: string }> = {
58
+ anthropic: { src: anthropicLogo, color: '#d97757' },
59
+ deepseek: { src: deepseekLogo },
60
+ gemini: { src: geminiLogo },
61
+ huggingface: { src: huggingFaceLogo },
62
+ local_openai: { src: lmStudioLogo, color: '#8b5cf6' },
63
+ ollama: { src: ollamaLogo, color: '#f3f4f6' },
64
+ openai: { src: openAiLogo, color: '#10a37f' },
65
+ openrouter: { src: openRouterLogo },
66
+ }
31
67
 
32
68
  function ProviderIcon({ provider }: { provider: string }) {
33
69
  const p = provider.toLowerCase()
34
- if (p === 'gemini') {
35
- return (
36
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
37
- <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" />
38
- </svg>
39
- )
40
- }
41
- if (p === 'anthropic') {
42
- return (
43
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
44
- <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" />
45
- <path d="M12 2L2 22h20L12 2z" />
46
- </svg>
47
- )
48
- }
49
- if (p === 'openai') {
50
- return (
51
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
52
- <circle cx="12" cy="12" r="10" />
53
- <line x1="12" y1="2" x2="12" y2="22" />
54
- <path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6" />
55
- </svg>
56
- )
57
- }
58
- if (p === 'deepseek') {
59
- return (
60
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
61
- <circle cx="11" cy="11" r="8" />
62
- <line x1="21" y1="21" x2="16.65" y2="16.65" />
63
- </svg>
64
- )
65
- }
66
- if (p === 'openrouter') {
67
- return (
68
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
69
- <polyline points="16 3 21 3 21 8" />
70
- <line x1="4" y1="20" x2="21" y2="3" />
71
- <polyline points="21 16 21 21 16 21" />
72
- <line x1="15" y1="15" x2="21" y2="21" />
73
- <line x1="4" y1="4" x2="9" y2="9" />
74
- </svg>
75
- )
76
- }
77
- if (p === 'huggingface') {
78
- return (
79
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
80
- <circle cx="12" cy="12" r="10" />
81
- <path d="M8 14s1.5 2 4 2 4-2 4-2" />
82
- <line x1="9" y1="9" x2="9.01" y2="9" />
83
- <line x1="15" y1="9" x2="15.01" y2="9" />
84
- </svg>
85
- )
86
- }
87
- if (p === 'local_openai') {
88
- return (
89
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
90
- <rect x="2" y="3" width="20" height="14" rx="2" ry="2" />
91
- <line x1="8" y1="21" x2="16" y2="21" />
92
- <line x1="12" y1="17" x2="12" y2="21" />
93
- </svg>
94
- )
95
- }
96
- if (p === 'ollama') {
97
- return (
98
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
99
- <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" />
100
- </svg>
101
- )
70
+ const logo = providerLogos[p]
71
+ if (logo) {
72
+ if (logo.color) {
73
+ return (
74
+ <span
75
+ className="provider-brand-logo is-monochrome"
76
+ aria-hidden="true"
77
+ style={{
78
+ '--provider-brand-color': logo.color,
79
+ maskImage: `url("${logo.src}")`,
80
+ WebkitMaskImage: `url("${logo.src}")`,
81
+ } as React.CSSProperties}
82
+ />
83
+ )
84
+ }
85
+ return <img className="provider-brand-logo" src={logo.src} alt="" aria-hidden="true" />
102
86
  }
103
87
  return (
104
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
88
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
105
89
  <circle cx="12" cy="12" r="3" />
106
90
  <path d="M19.07 4.93a10 10 0 0 1 0 14.14M4.93 4.93a10 10 0 0 0 0 14.14" />
107
91
  </svg>
108
92
  )
109
93
  }
110
94
 
111
- // ─── SVG Capability Badges (NO EMOJIS) ─────────────────────────────────────────
112
-
113
- function ModelBadge({ type, label }: { type: 'fast' | 'reasoning' | 'top' | 'vision'; label: string }) {
95
+ function ModelBadge({ type, label }: { type: 'fast' | 'reasoning' | 'top' | 'vision' | 'free'; label: string }) {
114
96
  return (
115
97
  <span className={`model-tag-badge badge-${type}`}>
98
+ {type === 'free' && (
99
+ <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
100
+ <path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z" />
101
+ <line x1="7" y1="7" x2="7.01" y2="7" />
102
+ </svg>
103
+ )}
116
104
  {type === 'fast' && (
117
105
  <svg width="10" height="10" viewBox="0 0 24 24" fill="currentColor">
118
106
  <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
@@ -148,10 +136,15 @@ function ModelBadge({ type, label }: { type: 'fast' | 'reasoning' | 'top' | 'vis
148
136
  )
149
137
  }
150
138
 
151
- function getModelBadges(modelId: string): Array<{ label: string; type: 'fast' | 'reasoning' | 'top' | 'vision' }> {
139
+ function getModelBadges(modelId: string): Array<{ label: string; type: 'fast' | 'reasoning' | 'top' | 'vision' | 'free' }> {
140
+ const badges: Array<{ label: string; type: 'fast' | 'reasoning' | 'top' | 'vision' | 'free' }> = []
141
+
142
+ if (isFreeModel(modelId)) {
143
+ badges.push({ label: 'FREE', type: 'free' })
144
+ }
145
+
152
146
  const lower = modelId.toLowerCase()
153
147
 
154
- // 1. Dedicated Reasoning models
155
148
  if (
156
149
  lower.includes('reason') ||
157
150
  lower.includes('thinking') ||
@@ -160,15 +153,11 @@ function getModelBadges(modelId: string): Array<{ label: string; type: 'fast' |
160
153
  lower.includes('o3') ||
161
154
  lower.includes('qwq')
162
155
  ) {
163
- return [{ label: 'Reasoning', type: 'reasoning' }]
156
+ badges.push({ label: 'Reasoning', type: 'reasoning' })
164
157
  }
165
-
166
- // 2. Vision / Multimodal models
167
158
  if (lower.includes('vision') || lower.includes('multimodal') || lower.includes('-vl')) {
168
- return [{ label: 'Vision', type: 'vision' }]
159
+ badges.push({ label: 'Vision', type: 'vision' })
169
160
  }
170
-
171
- // 3. Fast / Lightweight models
172
161
  if (
173
162
  lower.includes('flash') ||
174
163
  lower.includes('haiku') ||
@@ -176,10 +165,8 @@ function getModelBadges(modelId: string): Array<{ label: string; type: 'fast' |
176
165
  lower.includes('turbo') ||
177
166
  lower.includes('lite')
178
167
  ) {
179
- return [{ label: 'Fast', type: 'fast' }]
168
+ badges.push({ label: 'Fast', type: 'fast' })
180
169
  }
181
-
182
- // 4. Flagship / Top-tier models
183
170
  if (
184
171
  lower === 'claude-sonnet-5' ||
185
172
  lower === 'claude-opus-5' ||
@@ -189,10 +176,9 @@ function getModelBadges(modelId: string): Array<{ label: string; type: 'fast' |
189
176
  lower === 'deepseek-chat' ||
190
177
  lower === 'deepseek-v4-pro'
191
178
  ) {
192
- return [{ label: 'Top', type: 'top' }]
179
+ badges.push({ label: 'Top', type: 'top' })
193
180
  }
194
-
195
- return []
181
+ return badges
196
182
  }
197
183
 
198
184
  export default function ModelSelectorPopover({
@@ -203,16 +189,32 @@ export default function ModelSelectorPopover({
203
189
  dynamicOllamaModels,
204
190
  onSelect,
205
191
  disabled = false,
192
+ onUpdateSettings,
206
193
  }: ModelSelectorPopoverProps) {
207
194
  const [isOpen, setIsOpen] = useState(false)
195
+ const [mobilePane, setMobilePane] = useState<'models' | 'options'>('models')
208
196
  const [search, setSearch] = useState('')
209
197
  const [highlightedIndex, setHighlightedIndex] = useState(0)
198
+ const [expandOtherModels, setExpandOtherModels] = useState(false)
199
+
200
+ // Local state tracking model thinking overrides for responsive updates
201
+ const [modelThinkingOverrides, setModelThinkingOverrides] = useState<
202
+ Record<string, { enabled?: boolean; effort?: string }>
203
+ >({})
204
+
205
+ // Keep overrides in sync when settingsConfig arrives
206
+ useEffect(() => {
207
+ if (settingsConfig?.modelThinkingConfigs) {
208
+ setModelThinkingOverrides(settingsConfig.modelThinkingConfigs)
209
+ }
210
+ }, [settingsConfig?.modelThinkingConfigs])
211
+
210
212
  const popoverRef = useRef<HTMLDivElement>(null)
211
213
  const triggerRef = useRef<HTMLButtonElement>(null)
212
214
  const searchInputRef = useRef<HTMLInputElement>(null)
213
215
  const listRef = useRef<HTMLDivElement>(null)
214
216
 
215
- // ─── Live Dynamic Models from Hook ──────────────────────────────────────────
217
+ // Dynamic models from hook
216
218
  const { models: dynamicGemini } = useProviderModels('gemini', settingsConfig?.apiKey || '')
217
219
  const { models: dynamicClaude } = useProviderModels('anthropic', settingsConfig?.anthropicApiKey || '')
218
220
  const { models: dynamicOpenAI } = useProviderModels('openai', settingsConfig?.openaiApiKey || '')
@@ -220,7 +222,7 @@ export default function ModelSelectorPopover({
220
222
  const { models: dynamicDeepSeek } = useProviderModels('deepseek', settingsConfig?.deepseekApiKey || '')
221
223
  const { models: dynamicLocal } = useProviderModels('local_openai', '', settingsConfig?.localApiBaseUrl || '')
222
224
 
223
- // ─── Live Dynamic Ollama Models (Self-Fetch Fallback) ───────────────────────
225
+ // Ollama self-fetch fallback
224
226
  const [internalOllamaModels, setInternalOllamaModels] = useState<string[]>([])
225
227
 
226
228
  useEffect(() => {
@@ -247,7 +249,7 @@ export default function ModelSelectorPopover({
247
249
  } catch {}
248
250
 
249
251
  try {
250
- const live = await fetchProviderModels('ollama', '')
252
+ const live = await catalogPlatform.fetchProviderModels('ollama', '')
251
253
  if (!cancelled && live && live.length > 0) {
252
254
  setInternalOllamaModels(live)
253
255
  return
@@ -264,40 +266,59 @@ export default function ModelSelectorPopover({
264
266
  }
265
267
  }, [dynamicOllamaModels, settingsConfig?.ollamaHost, settingsConfig?.ollamaModel])
266
268
 
267
- // ─── Assemble Provider Groups ───────────────────────────────────────────────
269
+ // Assemble Provider Groups
268
270
  const providerGroups = useMemo<ProviderGroup[]>(() => {
269
271
  const list: ProviderGroup[] = []
270
272
 
271
- const addGroup = (id: string, name: string, models: string[]) => {
273
+ const addGroup = (id: string, providerId: string, name: string, models: string[], logoDataUrl?: string) => {
272
274
  if (models.length === 0) return
273
275
  list.push({
274
276
  id,
277
+ providerId,
275
278
  name,
276
- icon: <ProviderIcon provider={id} />,
279
+ icon: logoDataUrl
280
+ ? <img className="provider-brand-logo" src={logoDataUrl} alt="" aria-hidden="true" />
281
+ : <ProviderIcon provider={providerId} />,
277
282
  models,
278
283
  })
279
284
  }
280
285
 
281
286
  if (availableProviders.includes('gemini')) {
282
- addGroup('gemini', 'Google Gemini', dynamicGemini)
287
+ addGroup('gemini', 'gemini', 'Google Gemini', dynamicGemini)
283
288
  }
284
289
  if (availableProviders.includes('anthropic')) {
285
- addGroup('anthropic', 'Anthropic Claude', dynamicClaude)
290
+ addGroup('anthropic', 'anthropic', 'Anthropic Claude', dynamicClaude)
286
291
  }
287
292
  if (availableProviders.includes('openai')) {
288
- addGroup('openai', 'OpenAI', dynamicOpenAI)
293
+ addGroup('openai', 'openai', 'OpenAI', dynamicOpenAI)
289
294
  }
290
295
  if (availableProviders.includes('deepseek')) {
291
- addGroup('deepseek', 'DeepSeek', dynamicDeepSeek)
296
+ addGroup('deepseek', 'deepseek', 'DeepSeek', dynamicDeepSeek)
292
297
  }
293
298
  if (availableProviders.includes('openrouter')) {
294
- addGroup('openrouter', 'OpenRouter', dynamicOpenRouter)
299
+ const popularSet = new Set<string>(OPENROUTER_POPULAR_MODELS)
300
+ const popularModels: string[] = []
301
+ for (const pop of OPENROUTER_POPULAR_MODELS) {
302
+ if (dynamicOpenRouter.includes(pop)) {
303
+ popularModels.push(pop)
304
+ }
305
+ }
306
+ const otherModels = dynamicOpenRouter.filter((m) => !popularSet.has(m))
307
+
308
+ if (popularModels.length > 0) {
309
+ addGroup('openrouter-popular', 'openrouter', 'OpenRouter • Popular & Recommended', popularModels)
310
+ if (otherModels.length > 0) {
311
+ addGroup('openrouter-other', 'openrouter', `OpenRouter • Other models (${otherModels.length})`, otherModels)
312
+ }
313
+ } else {
314
+ addGroup('openrouter', 'openrouter', 'OpenRouter', dynamicOpenRouter)
315
+ }
295
316
  }
296
317
  if (availableProviders.includes('huggingface')) {
297
- addGroup('huggingface', 'Hugging Face', [...HF_MODELS])
318
+ addGroup('huggingface', 'huggingface', 'Hugging Face', [...HF_MODELS])
298
319
  }
299
320
  if (availableProviders.includes('local_openai')) {
300
- addGroup('local_openai', 'LM Studio / Local', dynamicLocal)
321
+ addGroup('local_openai', 'local_openai', 'LM Studio / Local', dynamicLocal)
301
322
  }
302
323
  if (availableProviders.includes('ollama')) {
303
324
  const ollamaList = (dynamicOllamaModels && dynamicOllamaModels.length > 0)
@@ -305,16 +326,15 @@ export default function ModelSelectorPopover({
305
326
  : (internalOllamaModels.length > 0
306
327
  ? internalOllamaModels
307
328
  : (settingsConfig?.ollamaModel ? [settingsConfig.ollamaModel] : []))
308
- addGroup('ollama', 'Ollama', ollamaList)
329
+ addGroup('ollama', 'ollama', 'Ollama', ollamaList)
309
330
  }
310
331
 
311
- // Custom providers
312
332
  const customProviders: CustomProviderConfig[] = settingsConfig?.customProviders || []
313
333
  for (const cp of customProviders) {
314
334
  const pid = `custom:${cp.id}`
315
335
  if (availableProviders.includes(pid)) {
316
336
  const cModels = (cp.models || []).map((m: any) => m.modelId).filter(Boolean)
317
- addGroup(pid, cp.displayName || cp.id, cModels)
337
+ addGroup(pid, pid, cp.displayName || cp.id, cModels, cp.logoDataUrl)
318
338
  }
319
339
  }
320
340
 
@@ -333,20 +353,20 @@ export default function ModelSelectorPopover({
333
353
  settingsConfig?.ollamaModel,
334
354
  ])
335
355
 
336
- // ─── Filter Groups by Search Query ─────────────────────────────────────────
356
+ // Filter Groups by Search Query
337
357
  const filteredGroups = useMemo(() => {
338
358
  const q = search.trim().toLowerCase()
339
359
  if (!q) return providerGroups
340
360
 
341
361
  const results: ProviderGroup[] = []
342
-
343
362
  for (const group of providerGroups) {
344
- const providerMatches = group.name.toLowerCase().includes(q) || group.id.toLowerCase().includes(q)
363
+ const providerMatches =
364
+ group.name.toLowerCase().includes(q) ||
365
+ group.id.toLowerCase().includes(q) ||
366
+ group.providerId.toLowerCase().includes(q)
345
367
  if (providerMatches) {
346
- // Show all models in this provider
347
368
  results.push(group)
348
369
  } else {
349
- // Filter models
350
370
  const matchedModels = group.models.filter((m) => m.toLowerCase().includes(q))
351
371
  if (matchedModels.length > 0) {
352
372
  results.push({
@@ -356,30 +376,104 @@ export default function ModelSelectorPopover({
356
376
  }
357
377
  }
358
378
  }
359
-
360
379
  return results
361
380
  }, [providerGroups, search])
362
381
 
363
- // ─── Flattened Items for Keyboard Navigation ────────────────────────────────
382
+ // Automatically expand other models when searching, or manual toggle
383
+ const isOtherExpanded = Boolean(search.trim()) || expandOtherModels
384
+
385
+ // Flattened Items for Keyboard Navigation
364
386
  const flattenedItems = useMemo<FlattenedItem[]>(() => {
365
387
  const items: FlattenedItem[] = []
366
388
  for (const g of filteredGroups) {
389
+ if (g.id === 'openrouter-other' && !isOtherExpanded) {
390
+ continue
391
+ }
367
392
  for (const m of g.models) {
368
393
  items.push({
369
- providerId: g.id,
394
+ providerId: g.providerId,
370
395
  providerName: g.name,
371
396
  model: m,
372
397
  })
373
398
  }
374
399
  }
375
400
  return items
376
- }, [filteredGroups])
401
+ }, [filteredGroups, isOtherExpanded])
402
+
403
+ // Model currently inspected in the right detail pane
404
+ const [inspectedItem, setInspectedItem] = useState<{ providerId: string; model: string } | null>(null)
377
405
 
378
- // Keep highlighted index in range
406
+ // Initialize or reset inspected item and collapsed state on open
407
+ useEffect(() => {
408
+ if (isOpen) {
409
+ if (activeModel) {
410
+ setInspectedItem({ providerId: activeProvider, model: activeModel })
411
+ } else if (flattenedItems.length > 0) {
412
+ setInspectedItem({ providerId: flattenedItems[0].providerId, model: flattenedItems[0].model })
413
+ }
414
+ } else {
415
+ setExpandOtherModels(false)
416
+ }
417
+ }, [isOpen, activeProvider, activeModel])
418
+
419
+ // Reset highlight on search
379
420
  useEffect(() => {
380
421
  setHighlightedIndex(0)
422
+ if (flattenedItems.length > 0) {
423
+ setInspectedItem({ providerId: flattenedItems[0].providerId, model: flattenedItems[0].model })
424
+ }
381
425
  }, [search])
382
426
 
427
+ // Helper to resolve a model's thinking status
428
+ const getThinkingConfig = useCallback((model: string, provider: string) => {
429
+ const meta = getModelMetadata(model, provider)
430
+ const override = modelThinkingOverrides[model]
431
+ if (override) {
432
+ return {
433
+ supported: meta.supportsThinking,
434
+ enabled: override.enabled ?? true,
435
+ effort: (override.effort || 'medium').toLowerCase(),
436
+ }
437
+ }
438
+ return {
439
+ supported: meta.supportsThinking,
440
+ enabled: meta.supportsThinking ? (settingsConfig?.thinkingEnabled ?? true) : false,
441
+ effort: (settingsConfig?.thinkingEffort || 'medium').toLowerCase(),
442
+ }
443
+ }, [modelThinkingOverrides, settingsConfig?.thinkingEnabled, settingsConfig?.thinkingEffort])
444
+
445
+ // Persist thinking change
446
+ const persistThinking = async (model: string, enabled: boolean, effort: string) => {
447
+ const updatedOverrides = {
448
+ ...modelThinkingOverrides,
449
+ [model]: { enabled, effort },
450
+ }
451
+ setModelThinkingOverrides(updatedOverrides)
452
+
453
+ const updatedConfig = {
454
+ ...(settingsConfig || {}),
455
+ modelThinkingConfigs: updatedOverrides,
456
+ }
457
+
458
+ if (model === activeModel) {
459
+ updatedConfig.thinkingEnabled = enabled
460
+ updatedConfig.thinkingEffort = effort
461
+ }
462
+
463
+ if (onUpdateSettings) {
464
+ onUpdateSettings(updatedConfig)
465
+ }
466
+
467
+ const api = (window as any).settingsApi
468
+ if (api?.saveSettings) {
469
+ try {
470
+ await api.saveSettings(updatedConfig)
471
+ } catch (err) {
472
+ console.error('Failed to save thinking config:', err)
473
+ }
474
+ }
475
+ }
476
+
383
477
  // Click Outside to Close
384
478
  useEffect(() => {
385
479
  if (!isOpen) return
@@ -404,8 +498,9 @@ export default function ModelSelectorPopover({
404
498
  useEffect(() => {
405
499
  if (isOpen) {
406
500
  setSearch('')
501
+ setMobilePane('models')
407
502
  setTimeout(() => {
408
- searchInputRef.current?.focus()
503
+ if (!window.matchMedia('(max-width: 760px)').matches) searchInputRef.current?.focus()
409
504
  }, 50)
410
505
  }
411
506
  }, [isOpen])
@@ -421,41 +516,75 @@ export default function ModelSelectorPopover({
421
516
 
422
517
  // Keyboard navigation
423
518
  const handleKeyDown = (e: React.KeyboardEvent) => {
424
- if (!isOpen) return
519
+ if (!isOpen || e.nativeEvent.isComposing) return
520
+ if (e.key === 'Escape') {
521
+ e.preventDefault()
522
+ setIsOpen(false)
523
+ triggerRef.current?.focus()
524
+ return
525
+ }
526
+ // Let tabs and thinking controls keep their own keyboard behavior.
527
+ if (mobilePane !== 'models' || e.target instanceof HTMLButtonElement) return
425
528
 
426
529
  if (e.key === 'ArrowDown') {
427
530
  e.preventDefault()
428
531
  if (flattenedItems.length === 0) return
429
- setHighlightedIndex((prev) => (prev + 1) % flattenedItems.length)
532
+ const nextIdx = (highlightedIndex + 1) % flattenedItems.length
533
+ setHighlightedIndex(nextIdx)
534
+ setInspectedItem({ providerId: flattenedItems[nextIdx].providerId, model: flattenedItems[nextIdx].model })
430
535
  } else if (e.key === 'ArrowUp') {
431
536
  e.preventDefault()
432
537
  if (flattenedItems.length === 0) return
433
- setHighlightedIndex((prev) => (prev - 1 + flattenedItems.length) % flattenedItems.length)
538
+ const nextIdx = (highlightedIndex - 1 + flattenedItems.length) % flattenedItems.length
539
+ setHighlightedIndex(nextIdx)
540
+ setInspectedItem({ providerId: flattenedItems[nextIdx].providerId, model: flattenedItems[nextIdx].model })
434
541
  } else if (e.key === 'Enter') {
435
542
  e.preventDefault()
436
543
  const item = flattenedItems[highlightedIndex]
437
544
  if (item) {
438
545
  onSelect(item.providerId, item.model)
439
546
  setIsOpen(false)
547
+ triggerRef.current?.focus()
440
548
  }
441
- } else if (e.key === 'Escape') {
442
- e.preventDefault()
443
- setIsOpen(false)
444
- triggerRef.current?.focus()
445
549
  }
446
550
  }
447
551
 
448
- // Active item label for trigger pill
552
+ // Active item label & effort for trigger pill
449
553
  const activeModelDisplay = useMemo(() => {
450
554
  if (!activeModel) return 'Select Model'
451
555
  return activeModel.split('/').pop() || activeModel
452
556
  }, [activeModel])
453
557
 
558
+ const activeThinking = useMemo(() => {
559
+ return getThinkingConfig(activeModel, activeProvider)
560
+ }, [activeModel, activeProvider, getThinkingConfig])
561
+
562
+ // Inspected model details
563
+ const currentInspected = inspectedItem || (activeModel ? { providerId: activeProvider, model: activeModel } : null)
564
+ const inspectedMeta = useMemo(() => {
565
+ if (!currentInspected) return null
566
+ return getModelMetadata(currentInspected.model, currentInspected.providerId)
567
+ }, [currentInspected])
568
+
569
+ const inspectedThinking = useMemo(() => {
570
+ if (!currentInspected) return { supported: false, enabled: false, effort: 'medium' }
571
+ return getThinkingConfig(currentInspected.model, currentInspected.providerId)
572
+ }, [currentInspected, getThinkingConfig])
573
+
574
+ const inspectedBadges = useMemo(() => {
575
+ if (!currentInspected) return []
576
+ return getModelBadges(currentInspected.model)
577
+ }, [currentInspected])
578
+
579
+ const customLogoForProvider = (providerId: string) =>
580
+ (settingsConfig?.customProviders as CustomProviderConfig[] | undefined)
581
+ ?.find((provider) => `custom:${provider.id}` === providerId)?.logoDataUrl
582
+
454
583
  let itemCounter = 0
455
584
 
456
585
  return (
457
586
  <div className="model-selector-container">
458
- {/* ─── Trigger Button ─── */}
587
+ {/* ─── Trigger Button in Chat Bar ─── */}
459
588
  <button
460
589
  ref={triggerRef}
461
590
  type="button"
@@ -467,9 +596,16 @@ export default function ModelSelectorPopover({
467
596
  aria-expanded={isOpen}
468
597
  >
469
598
  <span className="model-selector-trigger-icon">
470
- <ProviderIcon provider={activeProvider} />
599
+ {customLogoForProvider(activeProvider)
600
+ ? <img className="provider-brand-logo" src={customLogoForProvider(activeProvider)} alt="" aria-hidden="true" />
601
+ : <ProviderIcon provider={activeProvider} />}
471
602
  </span>
472
603
  <span className="model-selector-trigger-name">{activeModelDisplay}</span>
604
+ {activeThinking.enabled && (
605
+ <span className="model-selector-trigger-effort">
606
+ {formatEffortDisplay(activeThinking.effort)}
607
+ </span>
608
+ )}
473
609
  <svg
474
610
  className={`model-selector-trigger-chevron ${isOpen ? 'open' : ''}`}
475
611
  width="11"
@@ -485,101 +621,289 @@ export default function ModelSelectorPopover({
485
621
  </svg>
486
622
  </button>
487
623
 
488
- {/* ─── Spotlight Floating Popover ─── */}
624
+ {/* ─── Spotlight 2-Column Master-Detail Floating Popover ─── */}
489
625
  {isOpen && (
490
- <div ref={popoverRef} className="model-spotlight-popover" onKeyDown={handleKeyDown}>
491
- {/* Search Header */}
492
- <div className="model-spotlight-search-bar">
493
- <svg
494
- className="search-icon"
495
- width="13"
496
- height="13"
497
- viewBox="0 0 24 24"
498
- fill="none"
499
- stroke="currentColor"
500
- strokeWidth="2.2"
501
- strokeLinecap="round"
502
- strokeLinejoin="round"
503
- >
504
- <circle cx="11" cy="11" r="8" />
505
- <line x1="21" y1="21" x2="16.65" y2="16.65" />
506
- </svg>
507
- <input
508
- ref={searchInputRef}
509
- type="text"
510
- className="model-spotlight-input"
511
- placeholder="Search model or provider..."
512
- value={search}
513
- onChange={(e) => setSearch(e.target.value)}
514
- />
515
- {search && (
516
- <button
517
- type="button"
518
- className="search-clear-btn"
519
- onClick={() => setSearch('')}
520
- title="Clear search"
626
+ <div ref={popoverRef} className={`model-spotlight-popover mobile-pane-${mobilePane}`} onKeyDown={handleKeyDown}>
627
+ <div className="model-spotlight-mobile-tabs" role="tablist" aria-label="Model selector view">
628
+ <button type="button" role="tab" aria-selected={mobilePane === 'models'} onClick={() => setMobilePane('models')}>Models</button>
629
+ <button type="button" role="tab" aria-selected={mobilePane === 'options'} onClick={() => setMobilePane('options')}>Options</button>
630
+ </div>
631
+ {/* ─── Left Column: Model List ─── */}
632
+ <div className="model-spotlight-left-pane">
633
+ {/* Search Header */}
634
+ <div className="model-spotlight-search-bar">
635
+ <svg
636
+ className="search-icon"
637
+ width="13"
638
+ height="13"
639
+ viewBox="0 0 24 24"
640
+ fill="none"
641
+ stroke="currentColor"
642
+ strokeWidth="2.2"
643
+ strokeLinecap="round"
644
+ strokeLinejoin="round"
521
645
  >
522
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
523
- <line x1="18" y1="6" x2="6" y2="18" />
524
- <line x1="6" y1="6" x2="18" y2="18" />
525
- </svg>
526
- </button>
527
- )}
646
+ <circle cx="11" cy="11" r="8" />
647
+ <line x1="21" y1="21" x2="16.65" y2="16.65" />
648
+ </svg>
649
+ <input
650
+ ref={searchInputRef}
651
+ type="text"
652
+ className="model-spotlight-input"
653
+ aria-label="Search models"
654
+ placeholder="Search models..."
655
+ value={search}
656
+ onChange={(e) => setSearch(e.target.value)}
657
+ />
658
+ {search && (
659
+ <button
660
+ type="button"
661
+ className="search-clear-btn"
662
+ onClick={() => setSearch('')}
663
+ title="Clear search"
664
+ >
665
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
666
+ <line x1="18" y1="6" x2="6" y2="18" />
667
+ <line x1="6" y1="6" x2="18" y2="18" />
668
+ </svg>
669
+ </button>
670
+ )}
671
+ </div>
672
+
673
+ {/* Grouped Model List */}
674
+ <div ref={listRef} className="model-spotlight-list" role="listbox">
675
+ {filteredGroups.length === 0 ? (
676
+ <div className="model-spotlight-empty">
677
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
678
+ <circle cx="11" cy="11" r="8" />
679
+ <line x1="21" y1="21" x2="16.65" y2="16.65" />
680
+ </svg>
681
+ <span>No models found matching &quot;{search}&quot;</span>
682
+ </div>
683
+ ) : (
684
+ filteredGroups.map((group) => {
685
+ const isOtherGroup = group.id === 'openrouter-other'
686
+ const isCollapsed = isOtherGroup && !isOtherExpanded
687
+
688
+ return (
689
+ <div key={group.id} className="model-spotlight-group">
690
+ <div className="model-spotlight-group-header">
691
+ <span className="group-header-icon">{group.icon}</span>
692
+ <span className="group-header-title">{group.name}</span>
693
+ </div>
694
+
695
+ {isCollapsed ? (
696
+ <div className="model-spotlight-see-more-wrap">
697
+ <button
698
+ type="button"
699
+ className="model-spotlight-see-more-btn"
700
+ onClick={() => setExpandOtherModels(true)}
701
+ >
702
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
703
+ <polyline points="6 9 12 15 18 9" />
704
+ </svg>
705
+ <span>Show all {group.models.length} other models</span>
706
+ </button>
707
+ </div>
708
+ ) : (
709
+ <>
710
+ <div className="model-spotlight-group-items">
711
+ {group.models.map((m) => {
712
+ const currentIndex = itemCounter++
713
+ const isSelected = activeProvider === group.providerId && activeModel === m
714
+ const isInspected = currentInspected?.model === m && currentInspected?.providerId === group.providerId
715
+ const itemThinking = getThinkingConfig(m, group.providerId)
716
+
717
+ return (
718
+ <div
719
+ key={m}
720
+ data-item-index={currentIndex}
721
+ className={`model-spotlight-item ${isSelected ? 'is-active' : ''} ${isInspected ? 'is-inspected' : ''}`}
722
+ onClick={() => {
723
+ setInspectedItem({ providerId: group.providerId, model: m })
724
+ onSelect(group.providerId, m)
725
+ setIsOpen(false)
726
+ triggerRef.current?.focus()
727
+ }}
728
+ onMouseEnter={() => {
729
+ setHighlightedIndex(currentIndex)
730
+ setInspectedItem({ providerId: group.providerId, model: m })
731
+ }}
732
+ role="option"
733
+ aria-selected={isSelected}
734
+ >
735
+ <div className="model-item-left">
736
+ <div style={{ display: 'inline-flex', alignItems: 'center', gap: '6px' }}>
737
+ <span className="model-item-provider-icon" aria-hidden="true">
738
+ {group.icon}
739
+ </span>
740
+ <span className="model-item-name">{m.split('/').pop() || m}</span>
741
+ {isFreeModel(m) && (
742
+ <span className="model-tag-badge badge-free">Free</span>
743
+ )}
744
+ </div>
745
+ {m.includes('/') && <span className="model-item-repo">{m}</span>}
746
+ </div>
747
+
748
+ <div className="model-item-right">
749
+ {itemThinking.enabled && (
750
+ <span className="model-item-effort-pill">
751
+ {formatEffortDisplay(itemThinking.effort)}
752
+ </span>
753
+ )}
754
+
755
+ {isSelected && (
756
+ <svg
757
+ className="model-item-check"
758
+ width="14"
759
+ height="14"
760
+ viewBox="0 0 24 24"
761
+ fill="none"
762
+ stroke="var(--accent, #10b981)"
763
+ strokeWidth="2.5"
764
+ strokeLinecap="round"
765
+ strokeLinejoin="round"
766
+ >
767
+ <polyline points="20 6 9 17 4 12" />
768
+ </svg>
769
+ )}
770
+ </div>
771
+ </div>
772
+ )
773
+ })}
774
+ </div>
775
+
776
+ {isOtherGroup && !search.trim() && (
777
+ <div className="model-spotlight-see-more-wrap" style={{ marginTop: '4px' }}>
778
+ <button
779
+ type="button"
780
+ className="model-spotlight-see-more-btn collapse-btn"
781
+ onClick={() => setExpandOtherModels(false)}
782
+ >
783
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
784
+ <polyline points="18 15 12 9 6 15" />
785
+ </svg>
786
+ <span>Collapse other models</span>
787
+ </button>
788
+ </div>
789
+ )}
790
+ </>
791
+ )}
792
+ </div>
793
+ )
794
+ })
795
+ )}
796
+ </div>
528
797
  </div>
529
798
 
530
- {/* Grouped Model List */}
531
- <div ref={listRef} className="model-spotlight-list" role="listbox">
532
- {filteredGroups.length === 0 ? (
533
- <div className="model-spotlight-empty">
534
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
535
- <circle cx="11" cy="11" r="8" />
536
- <line x1="21" y1="21" x2="16.65" y2="16.65" />
537
- </svg>
538
- <span>No models found matching &quot;{search}&quot;</span>
539
- </div>
540
- ) : (
541
- filteredGroups.map((group) => (
542
- <div key={group.id} className="model-spotlight-group">
543
- <div className="model-spotlight-group-header">
544
- <span className="group-header-icon">{group.icon}</span>
545
- <span className="group-header-title">{group.name}</span>
799
+ {/* ─── Right Column: Model Detail & Thinking Controls ─── */}
800
+ <div className="model-spotlight-right-pane">
801
+ {currentInspected && inspectedMeta ? (
802
+ <div className="model-detail-container">
803
+ {/* Header: Icon + Name */}
804
+ <div className="model-detail-header">
805
+ <div className="model-detail-icon">
806
+ {customLogoForProvider(currentInspected.providerId)
807
+ ? <img className="provider-brand-logo" src={customLogoForProvider(currentInspected.providerId)} alt="" aria-hidden="true" />
808
+ : <ProviderIcon provider={currentInspected.providerId} />}
809
+ </div>
810
+ <div className="model-detail-title-wrap">
811
+ <span className="model-detail-title">{currentInspected.model.split('/').pop() || currentInspected.model}</span>
812
+ {currentInspected.model.includes('/') && (
813
+ <span className="model-detail-subtitle">{currentInspected.model}</span>
814
+ )}
546
815
  </div>
816
+ </div>
547
817
 
548
- <div className="model-spotlight-group-items">
549
- {group.models.map((m) => {
550
- const currentIndex = itemCounter++
551
- const isSelected = activeProvider === group.id && activeModel === m
552
- const isHighlighted = highlightedIndex === currentIndex
553
- const badges = getModelBadges(m)
554
-
555
- return (
556
- <div
557
- key={m}
558
- data-item-index={currentIndex}
559
- className={`model-spotlight-item ${isSelected ? 'is-active' : ''} ${isHighlighted ? 'is-highlighted' : ''}`}
560
- onClick={() => {
561
- onSelect(group.id, m)
562
- setIsOpen(false)
563
- }}
564
- onMouseEnter={() => setHighlightedIndex(currentIndex)}
565
- role="option"
566
- aria-selected={isSelected}
567
- >
568
- <div className="model-item-left">
569
- <span className="model-item-name">{m.split('/').pop() || m}</span>
570
- {m.includes('/') && <span className="model-item-repo">{m}</span>}
571
- </div>
818
+ {/* Description */}
819
+ <p className="model-detail-description">
820
+ {inspectedMeta.description}
821
+ </p>
822
+
823
+ {/* Badges / Capabilities */}
824
+ <div className="model-detail-tags">
825
+ <span className="model-detail-context-badge">
826
+ {inspectedMeta.contextWindow}
827
+ </span>
828
+ {inspectedBadges.map((b) => (
829
+ <ModelBadge key={b.type} type={b.type} label={b.label} />
830
+ ))}
831
+ </div>
572
832
 
573
- <div className="model-item-right">
574
- <div className="model-item-badges">
575
- {badges.map((b) => (
576
- <ModelBadge key={b.type} type={b.type} label={b.label} />
577
- ))}
578
- </div>
833
+ {/* Divider */}
834
+ <div className="model-detail-divider" />
835
+
836
+ {/* Options Section */}
837
+ <div className="model-detail-section-title">Options</div>
838
+ <div className="model-detail-option-row">
839
+ <div className="option-row-left">
840
+ <svg
841
+ width="15"
842
+ height="15"
843
+ viewBox="0 0 24 24"
844
+ fill="none"
845
+ stroke="currentColor"
846
+ strokeWidth="2"
847
+ strokeLinecap="round"
848
+ strokeLinejoin="round"
849
+ className="option-icon"
850
+ >
851
+ <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" />
852
+ <path d="M9 21h6" />
853
+ </svg>
854
+ <span className="option-label">Thinking</span>
855
+ </div>
856
+
857
+ <button
858
+ type="button"
859
+ role="switch"
860
+ aria-checked={inspectedThinking.enabled}
861
+ className={`model-detail-switch ${inspectedThinking.enabled ? 'checked' : ''}`}
862
+ onClick={() => {
863
+ persistThinking(
864
+ currentInspected.model,
865
+ !inspectedThinking.enabled,
866
+ inspectedThinking.effort
867
+ )
868
+ }}
869
+ title={
870
+ inspectedThinking.enabled
871
+ ? 'Disable thinking'
872
+ : 'Enable thinking'
873
+ }
874
+ >
875
+ <span className="model-detail-switch-thumb" />
876
+ </button>
877
+ </div>
579
878
 
580
- {isSelected && (
879
+ {!inspectedThinking.supported && (
880
+ <div className="model-unsupported-note" style={{ color: inspectedThinking.enabled ? 'var(--interactive-fg)' : undefined }}>
881
+ {inspectedThinking.enabled
882
+ ? 'Thinking enabled (force toggle)'
883
+ : 'Not flagged as reasoning model by default (toggle to force enable)'}
884
+ </div>
885
+ )}
886
+
887
+ {/* Effort Section (visible when Thinking is ON) */}
888
+ {inspectedThinking.enabled && (
889
+ <div className="model-effort-section">
890
+ <div className="model-detail-section-title">Effort</div>
891
+ <div className="model-effort-list">
892
+ {Effort_LEVELS.map((level) => {
893
+ const isCurrent = inspectedThinking.effort === level.id
894
+ return (
895
+ <button
896
+ key={level.id}
897
+ type="button"
898
+ className={`model-effort-item ${isCurrent ? 'is-selected' : ''}`}
899
+ onClick={() => {
900
+ persistThinking(currentInspected.model, true, level.id)
901
+ }}
902
+ >
903
+ <span className="effort-item-label">{level.label}</span>
904
+ {isCurrent && (
581
905
  <svg
582
- className="model-item-check"
906
+ className="effort-item-check"
583
907
  width="14"
584
908
  height="14"
585
909
  viewBox="0 0 24 24"
@@ -592,13 +916,17 @@ export default function ModelSelectorPopover({
592
916
  <polyline points="20 6 9 17 4 12" />
593
917
  </svg>
594
918
  )}
595
- </div>
596
- </div>
597
- )
598
- })}
919
+ </button>
920
+ )
921
+ })}
922
+ </div>
599
923
  </div>
600
- </div>
601
- ))
924
+ )}
925
+ </div>
926
+ ) : (
927
+ <div className="model-detail-empty">
928
+ <span>Select a model to view options</span>
929
+ </div>
602
930
  )}
603
931
  </div>
604
932
  </div>