@hienlh/ppm 0.17.14 → 0.17.16

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 (427) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/assets/skills/ppm/SKILL.md +1 -1
  3. package/assets/skills/ppm/references/cli-reference.md +4 -4
  4. package/assets/skills/ppm/references/http-api.md +1 -1
  5. package/dist/web/assets/{ai-resource-editor-DfCN7LjR.js → ai-resource-editor-CsossqDO.js} +1 -1
  6. package/dist/web/assets/{angular-html-DkR4iCth.js → angular-html-CkxY2iBQ.js} +1 -1
  7. package/dist/web/assets/{angular-ts-DcyL4Chx.js → angular-ts-BePeGkkC.js} +1 -1
  8. package/dist/web/assets/{apl-BVlrVtjt.js → apl-DBS7PWvB.js} +1 -1
  9. package/dist/web/assets/architecture-PBZL5I3N-NAS99xy0.js +1 -0
  10. package/dist/web/assets/{astro-MjJlozLj.js → astro-Clbk1k4h.js} +1 -1
  11. package/dist/web/assets/{audio-preview-DbFUkIzm.js → audio-preview-DIkokvPM.js} +1 -1
  12. package/dist/web/assets/{blade-DnJWi1fz.js → blade-BeBsBuGS.js} +1 -1
  13. package/dist/web/assets/{bsl-DCmJxSIz.js → bsl-DYigT3JZ.js} +1 -1
  14. package/dist/web/assets/{cairo-C8dDenub.js → cairo-BjpO78wI.js} +1 -1
  15. package/dist/web/assets/chat-tab-Bh6l253v.js +18 -0
  16. package/dist/web/assets/click-outside-container-DXZVmhaX.js +1 -0
  17. package/dist/web/assets/{cobol-DPx_nifl.js → cobol-CpuUx69s.js} +1 -1
  18. package/dist/web/assets/code-editor-B7F-d4DK.js +10 -0
  19. package/dist/web/assets/{coffee-DvFzqhgN.js → coffee-FoFd2Cxo.js} +1 -1
  20. package/dist/web/assets/{conflict-editor-BAAffNdj.js → conflict-editor-Dqm1bkyL.js} +3 -3
  21. package/dist/web/assets/{cpp-BLJN0umi.js → cpp-CO_nPfdr.js} +1 -1
  22. package/dist/web/assets/{crystal-BXR-9fGw.js → crystal-D-UygAAF.js} +1 -1
  23. package/dist/web/assets/{csv-preview-DzhSC0fd.js → csv-preview-CvP4xzug.js} +1 -1
  24. package/dist/web/assets/data-grid-overlay-editor-CUlFsD-D.js +1 -0
  25. package/dist/web/assets/database-viewer-5oNTPgjF.js +1 -0
  26. package/dist/web/assets/{diff-viewer-DvXxlk47.js → diff-viewer-BfWixe_z.js} +1 -1
  27. package/dist/web/assets/dist-BsziT-tR.js +11 -0
  28. package/dist/web/assets/{docx-preview-DfjH-dIr.js → docx-preview-CguUoTKe.js} +1 -1
  29. package/dist/web/assets/{edge-rWOlCmXT.js → edge-BSzxzX11.js} +1 -1
  30. package/dist/web/assets/{elixir-E7Y82okW.js → elixir-DH1-Mrep.js} +1 -1
  31. package/dist/web/assets/{elm-DTPGbc-w.js → elm-B0ln5J70.js} +1 -1
  32. package/dist/web/assets/{erb-DHqLHrE6.js → erb-GIz6NnlZ.js} +1 -1
  33. package/dist/web/assets/{erlang-Byg0nNiV.js → erlang-B8MgYhib.js} +1 -1
  34. package/dist/web/assets/esm-CjVeOTNQ.js +2 -0
  35. package/dist/web/assets/{extension-webview-wuMQ8pD7.js → extension-webview-DTpFt1eL.js} +1 -1
  36. package/dist/web/assets/{fortran-fixed-form-CY1n0Xf6.js → fortran-fixed-form-D_-TrK6U.js} +1 -1
  37. package/dist/web/assets/{fsharp-_vEDSCJz.js → fsharp-C9cLCk2b.js} +1 -1
  38. package/dist/web/assets/{gdresource-B6XT0wAC.js → gdresource-CsZ3lXwY.js} +1 -1
  39. package/dist/web/assets/{git-commit-Wk9ovq59.js → git-commit-xmq0KqrA.js} +1 -1
  40. package/dist/web/assets/{git-log-panel-SPPYmbCr.js → git-log-panel-DUX7N5tN.js} +1 -1
  41. package/dist/web/assets/{git-rebase-DSarGPvK.js → git-rebase-D3O-jsSX.js} +1 -1
  42. package/dist/web/assets/gitGraph-HDMCJU4V-B4I3L4Sf.js +1 -0
  43. package/dist/web/assets/glide-data-grid-7vB1SNne.js +138 -0
  44. package/dist/web/assets/{glimmer-js-CkYI35_P.js → glimmer-js-g74gESrC.js} +1 -1
  45. package/dist/web/assets/{glimmer-ts-BqmIZcds.js → glimmer-ts-DF4aDWHT.js} +1 -1
  46. package/dist/web/assets/{glsl-Be-yBCF5.js → glsl-D5LmfW7l.js} +1 -1
  47. package/dist/web/assets/{graphql-a5DrENHY.js → graphql-_KI4RuXL.js} +1 -1
  48. package/dist/web/assets/group-chat-tab-CNECY-zg.js +1 -0
  49. package/dist/web/assets/{hack-BLAg20aD.js → hack-B1NaTC39.js} +1 -1
  50. package/dist/web/assets/{haml-Dj6bGOQH.js → haml-DDFXadZ4.js} +1 -1
  51. package/dist/web/assets/{handlebars-dmEa36Oh.js → handlebars-Bp-Jq3K9.js} +1 -1
  52. package/dist/web/assets/{html-yacZYzSE.js → html-DyB9_5Tj.js} +1 -1
  53. package/dist/web/assets/{html-derivative-lLi3-RNT.js → html-derivative-CC60wi-3.js} +1 -1
  54. package/dist/web/assets/{http-1KaxcE4e.js → http-C-9qngH4.js} +1 -1
  55. package/dist/web/assets/{hurl-ST-dEEZR.js → hurl-BtxgpNDs.js} +1 -1
  56. package/dist/web/assets/{hxml-CpDtuq__.js → hxml-DOoOS9op.js} +1 -1
  57. package/dist/web/assets/{image-preview-D_8o6OLx.js → image-preview-CZg6FQ3w.js} +1 -1
  58. package/dist/web/assets/{index-C1Q59prB.js → index-D2G6kmTs.js} +7 -7
  59. package/dist/web/assets/index-DCmrZnq0.css +2 -0
  60. package/dist/web/assets/info-3K5VOQVL-CBbbOe3C.js +1 -0
  61. package/dist/web/assets/{jinja-Cjw-evAn.js → jinja-cN-150ao.js} +1 -1
  62. package/dist/web/assets/{jison-DfATMYoY.js → jison-CqjsqPq5.js} +1 -1
  63. package/dist/web/assets/{julia-DDCaxiqT.js → julia-C-I5m8W4.js} +1 -1
  64. package/dist/web/assets/{just-CJL529u6.js → just-CgsSW9zs.js} +1 -1
  65. package/dist/web/assets/keybindings-store-D8Cppv4w.js +1 -0
  66. package/dist/web/assets/{latex-Zc4EpLpW.js → latex-BFzR9N2d.js} +1 -1
  67. package/dist/web/assets/{liquid-B_6KMNYS.js → liquid-BWfr-_iC.js} +1 -1
  68. package/dist/web/assets/{lua-BtS2idK7.js → lua-DsXVun6g.js} +1 -1
  69. package/dist/web/assets/{markdown-renderer-DVVx3WCU.js → markdown-renderer-CiQkvWP_.js} +3 -3
  70. package/dist/web/assets/{marko-Wk6LBnck.js → marko-DWBbo09n.js} +1 -1
  71. package/dist/web/assets/{mdc-cRaXBrzL.js → mdc-CUMe9LOG.js} +1 -1
  72. package/dist/web/assets/{nextflow-Bos2wvDV.js → nextflow-CoYbADOm.js} +1 -1
  73. package/dist/web/assets/{nginx-DMlOwzdr.js → nginx-z-JRZREw.js} +1 -1
  74. package/dist/web/assets/{nim-D2dZQA88.js → nim-Ci4LHyBm.js} +1 -1
  75. package/dist/web/assets/notification-store-DOGxkWih.js +1 -0
  76. package/dist/web/assets/{number-overlay-editor-Du_UgiD3.js → number-overlay-editor-lnnuUpPI.js} +1 -1
  77. package/dist/web/assets/packet-RMMSAZCW-fr8-QSTF.js +1 -0
  78. package/dist/web/assets/{pdf-preview-HTC73FyK.js → pdf-preview-B6ZqANpw.js} +1 -1
  79. package/dist/web/assets/{perl-C5-Z6fPn.js → perl-pbDimKOO.js} +1 -1
  80. package/dist/web/assets/{php-BXNNhkMH.js → php-B003E5v7.js} +1 -1
  81. package/dist/web/assets/pie-UPGHQEXC-Biu7_Pbb.js +1 -0
  82. package/dist/web/assets/postgres-viewer-B23xTCSs.js +3 -0
  83. package/dist/web/assets/{pug-C1zf1yWy.js → pug-AoueAWJo.js} +1 -1
  84. package/dist/web/assets/{qml-OW58jGpD.js → qml-CepxioQA.js} +1 -1
  85. package/dist/web/assets/radar-KQ55EAFF-CMtNRpK6.js +1 -0
  86. package/dist/web/assets/{razor-DzjSaobM.js → razor-lIvU-Gu-.js} +1 -1
  87. package/dist/web/assets/{rst-RfuihOUW.js → rst-Dn-dwElE.js} +1 -1
  88. package/dist/web/assets/{ruby-CNO3pli1.js → ruby-DmsD1Iz5.js} +1 -1
  89. package/dist/web/assets/{sas-DZY5BtXx.js → sas-6IM2P4YP.js} +1 -1
  90. package/dist/web/assets/{scss--4g-REcN.js → scss-RgYEZQqh.js} +1 -1
  91. package/dist/web/assets/{settings-store-mWnY4Kt0.js → settings-store-BkSf4SPQ.js} +2 -2
  92. package/dist/web/assets/settings-tab-D5hAA1bY.js +1 -0
  93. package/dist/web/assets/{shaderlab-Cu4sBiVn.js → shaderlab-B0MNEwt4.js} +1 -1
  94. package/dist/web/assets/{shellsession-DWzJfEv7.js → shellsession-F8S4LrQI.js} +1 -1
  95. package/dist/web/assets/{soy-BnqE-5Ff.js → soy-DDlMbX7u.js} +1 -1
  96. package/dist/web/assets/{sparql-Ctg__NhZ.js → sparql-kthmGAAe.js} +1 -1
  97. package/dist/web/assets/{sql-query-editor-CJdpO95g.js → sql-query-editor-BYNM0RRl.js} +1 -1
  98. package/dist/web/assets/sqlite-viewer-DW9f2Hqj.js +1 -0
  99. package/dist/web/assets/{stata-Qk2h66XW.js → stata-Tfbew8La.js} +1 -1
  100. package/dist/web/assets/{surrealql-8QEX7EfH.js → surrealql-C0LIGqRx.js} +1 -1
  101. package/dist/web/assets/{svelte-D_mubC5-.js → svelte-CfTy8CGF.js} +1 -1
  102. package/dist/web/assets/{system-monitor-tab-BA9gqJRW.js → system-monitor-tab-B5f4pgdX.js} +1 -1
  103. package/dist/web/assets/{templ-C1jV0fsO.js → templ-V5H1Sbfy.js} +1 -1
  104. package/dist/web/assets/{terminal-tab-DWncjHEA.js → terminal-tab-CK3lX-0Y.js} +2 -2
  105. package/dist/web/assets/{tex-D_StFXy_.js → tex-C3H3uMZf.js} +1 -1
  106. package/dist/web/assets/treemap-KZPCXAKY-ZYVFjoaN.js +1 -0
  107. package/dist/web/assets/{ts-tags-B5m47rEm.js → ts-tags-7AXgG5YS.js} +1 -1
  108. package/dist/web/assets/{twig-C_br6GIl.js → twig-BSyS38T3.js} +1 -1
  109. package/dist/web/assets/{use-monaco-theme-Ch2jRiGj.js → use-monaco-theme-Jj2OxkAE.js} +1 -1
  110. package/dist/web/assets/{use-websocket-MvxbuTdy.js → use-websocket-DrDBgIWU.js} +1 -1
  111. package/dist/web/assets/{vendor-mermaid-DP1CEcGn.js → vendor-mermaid-DGOXKrJC.js} +193 -193
  112. package/dist/web/assets/{video-preview-rWrNCfZX.js → video-preview-BOHxkwKG.js} +1 -1
  113. package/dist/web/assets/{vue-DQwCnLdr.js → vue-C4d_br9u.js} +1 -1
  114. package/dist/web/assets/{vue-html-T_EoGpPJ.js → vue-html-CGdoz4vW.js} +1 -1
  115. package/dist/web/assets/{vue-vine-DmxLqX50.js → vue-vine-CqNolQlN.js} +1 -1
  116. package/dist/web/assets/{xml-Bs6Bw8is.js → xml-UmCmu-Od.js} +1 -1
  117. package/dist/web/assets/{xsl-f5ZNhRCc.js → xsl-DJG6USGh.js} +1 -1
  118. package/dist/web/index.html +14 -14
  119. package/dist/web/monacoeditorwork/css.worker.bundle.js +122 -122
  120. package/dist/web/monacoeditorwork/editor.worker.bundle.js +78 -78
  121. package/dist/web/monacoeditorwork/html.worker.bundle.js +110 -110
  122. package/dist/web/monacoeditorwork/json.worker.bundle.js +108 -108
  123. package/dist/web/monacoeditorwork/ts.worker.bundle.js +81 -81
  124. package/dist/web/sw.js +1 -1
  125. package/package.json +1 -1
  126. package/schemas/ppm-config.schema.json +3 -3
  127. package/src/cli/commands/init.ts +8 -5
  128. package/src/providers/claude-agent-sdk-query-options.ts +57 -0
  129. package/src/providers/claude-agent-sdk.ts +21 -9
  130. package/src/server/ws/chat.ts +91 -10
  131. package/src/services/account.service.ts +13 -7
  132. package/src/services/db.service.ts +31 -1
  133. package/src/types/api.ts +4 -2
  134. package/src/types/chat.ts +8 -0
  135. package/src/types/config.ts +4 -9
  136. package/src/web/components/chat/chat-tab.tsx +8 -0
  137. package/src/web/components/chat/message-input.tsx +27 -7
  138. package/src/web/components/chat/message-list.tsx +48 -3
  139. package/src/web/components/chat/model-thinking-selector-helpers.ts +33 -0
  140. package/src/web/components/chat/model-thinking-selector.tsx +189 -0
  141. package/src/web/components/settings/ai-settings-section.tsx +2 -0
  142. package/src/web/components/settings/proxy-test-section.tsx +3 -1
  143. package/src/web/hooks/use-chat.ts +45 -0
  144. package/C:/Users/PC/AppData/Local/Temp/ppmbuild/index.js +0 -118043
  145. package/dist/web/assets/architecture-PBZL5I3N-CqTF9Xn6.js +0 -1
  146. package/dist/web/assets/chat-tab-C6nMDb9l.js +0 -18
  147. package/dist/web/assets/code-editor-C38IIs_y.js +0 -10
  148. package/dist/web/assets/data-grid-overlay-editor-cOzDcGkl.js +0 -1
  149. package/dist/web/assets/data-grid-types-CWHnFOc-.js +0 -1
  150. package/dist/web/assets/database-viewer-DxmL2veb.js +0 -1
  151. package/dist/web/assets/dist-B5ErTtYs.js +0 -11
  152. package/dist/web/assets/esm-DU7axMjq.js +0 -2
  153. package/dist/web/assets/gitGraph-HDMCJU4V-X12vfQ3i.js +0 -1
  154. package/dist/web/assets/glide-data-grid-BC0AHzMn.js +0 -138
  155. package/dist/web/assets/group-chat-tab-D20bF8q5.js +0 -1
  156. package/dist/web/assets/index-CMJ6whqq.css +0 -2
  157. package/dist/web/assets/info-3K5VOQVL-Bcz-Qhua.js +0 -1
  158. package/dist/web/assets/keybindings-store-TINaziU9.js +0 -1
  159. package/dist/web/assets/notification-store-DN8oDV7o.js +0 -1
  160. package/dist/web/assets/packet-RMMSAZCW-BTwjB70W.js +0 -1
  161. package/dist/web/assets/pie-UPGHQEXC-Cn-lrQYZ.js +0 -1
  162. package/dist/web/assets/postgres-viewer-pWjwP3GD.js +0 -3
  163. package/dist/web/assets/radar-KQ55EAFF-Cmppm_Ia.js +0 -1
  164. package/dist/web/assets/settings-tab-BoRuss3O.js +0 -1
  165. package/dist/web/assets/sqlite-viewer-BgewX3tM.js +0 -1
  166. package/dist/web/assets/treemap-KZPCXAKY-BLWus1wm.js +0 -1
  167. package/docs/journal/binary-self-upgrade-260724.md +0 -66
  168. package/nul/docs/claude-agent-sdk-reference.md +0 -780
  169. package/nul/docs/code-standards.md +0 -1080
  170. package/nul/docs/codebase-summary.md +0 -916
  171. package/nul/docs/deployment-guide.md +0 -702
  172. package/nul/docs/design-guidelines.md +0 -767
  173. package/nul/docs/extension-development-guide.md +0 -629
  174. package/nul/docs/journals/260414-1400-ext-git-graph-port-complete.md +0 -147
  175. package/nul/docs/journals/260414-1452-git-graph-faithful-port.md +0 -144
  176. package/nul/docs/journals/260414-1810-git-graph-ui-improvements-complete.md +0 -261
  177. package/nul/docs/journals/260414-2001-bundled-extensions.md +0 -219
  178. package/nul/docs/journals/260415-frontend-memory-optimization.md +0 -73
  179. package/nul/docs/lessons-learned.md +0 -70
  180. package/nul/docs/project-changelog.md +0 -574
  181. package/nul/docs/project-overview-pdr.md +0 -205
  182. package/nul/docs/project-roadmap.md +0 -222
  183. package/nul/docs/system-architecture.md +0 -1961
  184. package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
  185. package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
  186. package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
  187. package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
  188. package/spike-group-channel.mjs +0 -156
  189. package/spike-group-chat.mjs +0 -181
  190. /package/dist/web/assets/{abap-tkptwpsK.js → abap-BZ3J5hF3.js} +0 -0
  191. /package/dist/web/assets/{actionscript-3-Di9TMGwg.js → actionscript-3-CkyGfT-8.js} +0 -0
  192. /package/dist/web/assets/{ada-CB9F079D.js → ada-CxNLBoe7.js} +0 -0
  193. /package/dist/web/assets/{andromeeda-Dcl8jpb7.js → andromeeda-BPN5rsDz.js} +0 -0
  194. /package/dist/web/assets/{apache-D0Nk0qsH.js → apache-C1F5wHL6.js} +0 -0
  195. /package/dist/web/assets/{apex-mQIoWncD.js → apex-BaNixdO-.js} +0 -0
  196. /package/dist/web/assets/{api-themes-BdQCjXQk.js → api-themes-84MT-XqR.js} +0 -0
  197. /package/dist/web/assets/{applescript-C6ljbcsI.js → applescript-Cl_pdcch.js} +0 -0
  198. /package/dist/web/assets/{ara-WFqRPGPe.js → ara-B6UAE7M2.js} +0 -0
  199. /package/dist/web/assets/{asciidoc-bNd8w4nf.js → asciidoc-D9c9Twki.js} +0 -0
  200. /package/dist/web/assets/{asm-BQ1_F580.js → asm-CNmtv7Y9.js} +0 -0
  201. /package/dist/web/assets/{aurora-x-Ciqs_Dbu.js → aurora-x-C9z-NyzR.js} +0 -0
  202. /package/dist/web/assets/{awk-GCR-6KZV.js → awk-BfLHEnKa.js} +0 -0
  203. /package/dist/web/assets/{ayu-dark-DxJXuj99.js → ayu-dark-Bn7trkt_.js} +0 -0
  204. /package/dist/web/assets/{ayu-light-jvSyJWDV.js → ayu-light-Dpya9hPf.js} +0 -0
  205. /package/dist/web/assets/{ayu-mirage-Cg3BPO6H.js → ayu-mirage-Cc0jfABD.js} +0 -0
  206. /package/dist/web/assets/{ballerina-BPz4CrX6.js → ballerina-BtiCmN7T.js} +0 -0
  207. /package/dist/web/assets/{bat-CSTs2hIG.js → bat-tmFM76zR.js} +0 -0
  208. /package/dist/web/assets/{beancount-DMateAZX.js → beancount-BjPqRrcH.js} +0 -0
  209. /package/dist/web/assets/{berry-9lXg0GRM.js → berry-D0SQBxN2.js} +0 -0
  210. /package/dist/web/assets/{bibtex-DIbqmvFg.js → bibtex-CkjRWQKr.js} +0 -0
  211. /package/dist/web/assets/{bicep-02WGsoJ8.js → bicep-Bhq28Cxc.js} +0 -0
  212. /package/dist/web/assets/{bird2-BY0tbu3k.js → bird2-DFGInYb3.js} +0 -0
  213. /package/dist/web/assets/{c-jMBX_9Je.js → c-CP8cB4k_.js} +0 -0
  214. /package/dist/web/assets/{c3-B8JVbNjW.js → c3-oRytyeWo.js} +0 -0
  215. /package/dist/web/assets/{cadence-DUIf1tvL.js → cadence-Inf1rGb7.js} +0 -0
  216. /package/dist/web/assets/{catppuccin-frappe-FhUCVxex.js → catppuccin-frappe-DAzribQo.js} +0 -0
  217. /package/dist/web/assets/{catppuccin-latte-CzfrtmgL.js → catppuccin-latte-B6Y_mCCQ.js} +0 -0
  218. /package/dist/web/assets/{catppuccin-macchiato-6xL0lOtj.js → catppuccin-macchiato-COLbYqVL.js} +0 -0
  219. /package/dist/web/assets/{catppuccin-mocha-D39-xS3P.js → catppuccin-mocha-DKWaML1B.js} +0 -0
  220. /package/dist/web/assets/{clarity-D8TeGvoT.js → clarity-_ZLLrrsX.js} +0 -0
  221. /package/dist/web/assets/{clojure-Dx_acSX7.js → clojure-DWGVCg_P.js} +0 -0
  222. /package/dist/web/assets/{cmake-CyeYPq8o.js → cmake-Cwh3mug7.js} +0 -0
  223. /package/dist/web/assets/{codeowners-DrTI0lmI.js → codeowners-BdV6CFYi.js} +0 -0
  224. /package/dist/web/assets/{codeql-CPkFxVW-.js → codeql-NvupDIDf.js} +0 -0
  225. /package/dist/web/assets/{common-lisp-B0k-3LTj.js → common-lisp-B-vtBh5k.js} +0 -0
  226. /package/dist/web/assets/{coq-uygpo7to.js → coq-M8-FTfiZ.js} +0 -0
  227. /package/dist/web/assets/{csharp-DKUYGfSp.js → csharp-B7Ugdtd-.js} +0 -0
  228. /package/dist/web/assets/{css-DoOUp7v4.js → css-86k3Z-YA.js} +0 -0
  229. /package/dist/web/assets/{csv-B3YE13gi.js → csv-BX5XYhfH.js} +0 -0
  230. /package/dist/web/assets/{csv-parser-CB6bK93y.js → csv-parser-d56Fzpwc.js} +0 -0
  231. /package/dist/web/assets/{cue-DViO2wvn.js → cue-B7099gQa.js} +0 -0
  232. /package/dist/web/assets/{cypher-4BMCIW5N.js → cypher-D99mWVIu.js} +0 -0
  233. /package/dist/web/assets/{d-BT_sTHas.js → d-CFE8oQwh.js} +0 -0
  234. /package/dist/web/assets/{dark-plus-DVVXu-1N.js → dark-plus-BEeeDwdg.js} +0 -0
  235. /package/dist/web/assets/{dart-DHz6f6_6.js → dart-HVSWGnI5.js} +0 -0
  236. /package/dist/web/assets/{dax-ChYCjweK.js → dax-DjDgSJkh.js} +0 -0
  237. /package/dist/web/assets/{desktop-D6Lt4p04.js → desktop-B5A3i7J1.js} +0 -0
  238. /package/dist/web/assets/{diff-D8TDe4hP.js → diff-CpTrlaE9.js} +0 -0
  239. /package/dist/web/assets/{dist-D1CjMuoa.js → dist-BSCgJs-V.js} +0 -0
  240. /package/dist/web/assets/{docker-Bsp0YbPx.js → docker-xBhmJeHj.js} +0 -0
  241. /package/dist/web/assets/{dotenv-B_7giSY_.js → dotenv-DKKhLEv5.js} +0 -0
  242. /package/dist/web/assets/{dracula-TrQL2iB5.js → dracula-CVwQuzra.js} +0 -0
  243. /package/dist/web/assets/{dracula-soft-n2XOlgh-.js → dracula-soft-CG6mB-lf.js} +0 -0
  244. /package/dist/web/assets/{dream-maker-CdIEdhpT.js → dream-maker-SC-IdYY3.js} +0 -0
  245. /package/dist/web/assets/{edit-diff-preview-Cj6-iplb.js → edit-diff-preview-C50i1H63.js} +0 -0
  246. /package/dist/web/assets/{emacs-lisp-CSbixs6u.js → emacs-lisp-CIBFq6W8.js} +0 -0
  247. /package/dist/web/assets/{everforest-dark-BuZahZYp.js → everforest-dark-odRT_lec.js} +0 -0
  248. /package/dist/web/assets/{everforest-light-DPH53z5H.js → everforest-light-or1Voqjl.js} +0 -0
  249. /package/dist/web/assets/{fennel-B1-K_hlJ.js → fennel-tQd1z3iu.js} +0 -0
  250. /package/dist/web/assets/{fish-Cy12Dbua.js → fish-DSuZQG0k.js} +0 -0
  251. /package/dist/web/assets/{fluent-B_82ys8E.js → fluent-D7xI8a8e.js} +0 -0
  252. /package/dist/web/assets/{fortran-free-form-BRQdNzZF.js → fortran-free-form-BlAtcPd3.js} +0 -0
  253. /package/dist/web/assets/{gdscript-XBDmLUm9.js → gdscript-VsEQXBPm.js} +0 -0
  254. /package/dist/web/assets/{gdshader-DhVfB3u4.js → gdshader-iqHMOdwW.js} +0 -0
  255. /package/dist/web/assets/{genie-X3K29Y49.js → genie-C4XU4g1a.js} +0 -0
  256. /package/dist/web/assets/{gherkin-DKIx-6cX.js → gherkin-C4nfQzAB.js} +0 -0
  257. /package/dist/web/assets/{github-dark-Bf7zdp5s.js → github-dark-B_pbG3CC.js} +0 -0
  258. /package/dist/web/assets/{github-dark-default-DqsBBV11.js → github-dark-default-kFbx7C95.js} +0 -0
  259. /package/dist/web/assets/{github-dark-dimmed-X2gqRz6w.js → github-dark-dimmed-CpVfQEqs.js} +0 -0
  260. /package/dist/web/assets/{github-dark-high-contrast-Z7tvbGX4.js → github-dark-high-contrast-DYKqQwZh.js} +0 -0
  261. /package/dist/web/assets/{github-light-default-B0liF4d4.js → github-light-default-DVHfMPQ2.js} +0 -0
  262. /package/dist/web/assets/{github-light-BKxt-7zZ.js → github-light-gEYBmKaj.js} +0 -0
  263. /package/dist/web/assets/{github-light-high-contrast-F4encJwr.js → github-light-high-contrast-ClVJDu-q.js} +0 -0
  264. /package/dist/web/assets/{gleam-Pz2bHgBB.js → gleam-BLaPu7ft.js} +0 -0
  265. /package/dist/web/assets/{gn-CgmdNsPU.js → gn-BKgerUyI.js} +0 -0
  266. /package/dist/web/assets/{gnuplot-qLNF5yZ9.js → gnuplot-cqJuEFb-.js} +0 -0
  267. /package/dist/web/assets/{go-CSDUNhE7.js → go-B2EHdyD8.js} +0 -0
  268. /package/dist/web/assets/{groovy-B3NEnOHF.js → groovy-DdImoj8s.js} +0 -0
  269. /package/dist/web/assets/{gruvbox-dark-hard-DcoftiUX.js → gruvbox-dark-hard-DlwstAds.js} +0 -0
  270. /package/dist/web/assets/{gruvbox-dark-medium-D1wVSuD8.js → gruvbox-dark-medium-CiYEd1vd.js} +0 -0
  271. /package/dist/web/assets/{gruvbox-dark-soft-DWpunymH.js → gruvbox-dark-soft-C-wEa4h4.js} +0 -0
  272. /package/dist/web/assets/{gruvbox-light-hard-rHMvyUdS.js → gruvbox-light-hard-BqYmfna-.js} +0 -0
  273. /package/dist/web/assets/{gruvbox-light-medium-3O2KiXO7.js → gruvbox-light-medium-CxmfalT2.js} +0 -0
  274. /package/dist/web/assets/{gruvbox-light-soft-lNlXJPwH.js → gruvbox-light-soft-DGWXXMCB.js} +0 -0
  275. /package/dist/web/assets/{haskell-aaG3aC0h.js → haskell-H_C_IuVb.js} +0 -0
  276. /package/dist/web/assets/{haxe-CPcHhUDd.js → haxe-CGNSMpeZ.js} +0 -0
  277. /package/dist/web/assets/{hcl-CMQNlR_4.js → hcl-B7bSTSQf.js} +0 -0
  278. /package/dist/web/assets/{hjson-DeuklPFj.js → hjson-DlJ-glQZ.js} +0 -0
  279. /package/dist/web/assets/{hlsl-BI3hlsaM.js → hlsl-CehW5SJN.js} +0 -0
  280. /package/dist/web/assets/{horizon-C7-gOcjs.js → horizon-Beabcz2d.js} +0 -0
  281. /package/dist/web/assets/{horizon-bright-Cxt9bRW7.js → horizon-bright-BC87RXPa.js} +0 -0
  282. /package/dist/web/assets/{houston-DbF2G7iD.js → houston-Da7RFwUy.js} +0 -0
  283. /package/dist/web/assets/{hy-DRG6Hs2I.js → hy-m1H70w19.js} +0 -0
  284. /package/dist/web/assets/{imba-CxKv_2TW.js → imba-MExFsdAA.js} +0 -0
  285. /package/dist/web/assets/{ini-BiHsyCdO.js → ini-CJy_zmwy.js} +0 -0
  286. /package/dist/web/assets/{java-D3RZzgDB.js → java-DqDFvJBH.js} +0 -0
  287. /package/dist/web/assets/{javascript-4FmSqG-T.js → javascript-C3Wyv22X.js} +0 -0
  288. /package/dist/web/assets/{json-CjB236_E.js → json-DnGBw_DZ.js} +0 -0
  289. /package/dist/web/assets/{json5-bkfO-Rco.js → json5-CRN-zoN4.js} +0 -0
  290. /package/dist/web/assets/{jsonc-BwaTeLyv.js → jsonc-CKRUZNRo.js} +0 -0
  291. /package/dist/web/assets/{jsonl-CfxNSwGd.js → jsonl-CGfD6FrH.js} +0 -0
  292. /package/dist/web/assets/{jsonnet-CQETCYrp.js → jsonnet-nbFuDj0o.js} +0 -0
  293. /package/dist/web/assets/{jssm-D5o3Zzdz.js → jssm-D0ShzIqD.js} +0 -0
  294. /package/dist/web/assets/{jsx-BAMILPLo.js → jsx-D27hbRbs.js} +0 -0
  295. /package/dist/web/assets/{kanagawa-dragon-BhGVxu3R.js → kanagawa-dragon-Ov3f8K0T.js} +0 -0
  296. /package/dist/web/assets/{kanagawa-lotus-FH4Y59ro.js → kanagawa-lotus-CLyOqh-g.js} +0 -0
  297. /package/dist/web/assets/{kanagawa-wave-eilvP9MB.js → kanagawa-wave-Kj3dzabH.js} +0 -0
  298. /package/dist/web/assets/{kdl-BQ-yvXUK.js → kdl-DFF58Gu4.js} +0 -0
  299. /package/dist/web/assets/{kotlin-BuCx0-VT.js → kotlin-BM4PKaB4.js} +0 -0
  300. /package/dist/web/assets/{kusto-DAN_n_Cy.js → kusto-DrvHLCv5.js} +0 -0
  301. /package/dist/web/assets/{laserwave-Cq2BlxrT.js → laserwave-Db6i6ZkO.js} +0 -0
  302. /package/dist/web/assets/{lean-Dhq7uXKw.js → lean-D0hEjzwk.js} +0 -0
  303. /package/dist/web/assets/{less-CxaMQb8j.js → less-BEj4npGG.js} +0 -0
  304. /package/dist/web/assets/{lib-MIEszzkI.js → lib-CBdlQ75W.js} +0 -0
  305. /package/dist/web/assets/{light-plus-B4sMAend.js → light-plus-DLIIbDea.js} +0 -0
  306. /package/dist/web/assets/{llvm-DQ6-B_6Y.js → llvm-DMt6umsO.js} +0 -0
  307. /package/dist/web/assets/{log-Bb_vqvu7.js → log-BopvdtPW.js} +0 -0
  308. /package/dist/web/assets/{logo-BzfYv3A_.js → logo-CYSUFPFR.js} +0 -0
  309. /package/dist/web/assets/{luau-BnAeNR77.js → luau-XC611HNO.js} +0 -0
  310. /package/dist/web/assets/{make-B6IFuxpC.js → make-BMYZIfBj.js} +0 -0
  311. /package/dist/web/assets/{markdown-Z0xi77Fn.js → markdown-BLza5nvF.js} +0 -0
  312. /package/dist/web/assets/{material-theme-1scy1SYn.js → material-theme-Uw27UfJW.js} +0 -0
  313. /package/dist/web/assets/{material-theme-darker-G-JykXQP.js → material-theme-darker-dfqt8XBY.js} +0 -0
  314. /package/dist/web/assets/{material-theme-lighter-BtKkCMVq.js → material-theme-lighter-CPtBTblV.js} +0 -0
  315. /package/dist/web/assets/{material-theme-ocean-irrDC89L.js → material-theme-ocean-BfZgVqC-.js} +0 -0
  316. /package/dist/web/assets/{material-theme-palenight-Eq5_K4LM.js → material-theme-palenight-DAZoVYg8.js} +0 -0
  317. /package/dist/web/assets/{matlab-BE3oCXZC.js → matlab-cSzmquiW.js} +0 -0
  318. /package/dist/web/assets/{mdx-DYiuFTGw.js → mdx-Dq0kW5VM.js} +0 -0
  319. /package/dist/web/assets/{mermaid-DVlaEvtw.js → mermaid-DoIKF0yS.js} +0 -0
  320. /package/dist/web/assets/{min-dark-DSkeTpQa.js → min-dark-DyraimDU.js} +0 -0
  321. /package/dist/web/assets/{min-light-CFv2Q0uF.js → min-light-Co9cbcUv.js} +0 -0
  322. /package/dist/web/assets/{mipsasm-CiAFuZQ2.js → mipsasm-ph6cKgHn.js} +0 -0
  323. /package/dist/web/assets/{mojo-ARshcaSQ.js → mojo-BBT0XwmY.js} +0 -0
  324. /package/dist/web/assets/{monokai-CPTV-SOg.js → monokai-IP0T5Rtg.js} +0 -0
  325. /package/dist/web/assets/{moonbit-D57B0dZr.js → moonbit-B8cogNXl.js} +0 -0
  326. /package/dist/web/assets/{move-qgy3G_o9.js → move-DkY26NtM.js} +0 -0
  327. /package/dist/web/assets/{narrat-CZ3rC-oc.js → narrat-rBs3byG0.js} +0 -0
  328. /package/dist/web/assets/{nextflow-groovy-BxxIOcI4.js → nextflow-groovy-DkO9wMLP.js} +0 -0
  329. /package/dist/web/assets/{night-owl-B1ryGCda.js → night-owl-jVR4lFji.js} +0 -0
  330. /package/dist/web/assets/{night-owl-light-BZvNnvMF.js → night-owl-light-fBYJ7s3U.js} +0 -0
  331. /package/dist/web/assets/{nix-BVBQi8yv.js → nix-WX9oavu6.js} +0 -0
  332. /package/dist/web/assets/{nord-3NXw613h.js → nord-Cf7G21Pu.js} +0 -0
  333. /package/dist/web/assets/{nushell-BMOLRalb.js → nushell-DQdzcJ1H.js} +0 -0
  334. /package/dist/web/assets/{objective-c-AxruEUgh.js → objective-c-JSO2uvZ-.js} +0 -0
  335. /package/dist/web/assets/{objective-cpp-cFT0qRsD.js → objective-cpp-CZMGJ9Fb.js} +0 -0
  336. /package/dist/web/assets/{ocaml-_8JH6O8J.js → ocaml-C4S4NSDo.js} +0 -0
  337. /package/dist/web/assets/{odin-nwYvR0O6.js → odin-Y2jXCgVq.js} +0 -0
  338. /package/dist/web/assets/{one-dark-pro-C1LaYJaH.js → one-dark-pro-dVIxuoJY.js} +0 -0
  339. /package/dist/web/assets/{one-light-B7rMc__c.js → one-light-BQ1IKfD1.js} +0 -0
  340. /package/dist/web/assets/{openscad-Cwes8bKO.js → openscad-Bddw4I3z.js} +0 -0
  341. /package/dist/web/assets/{pascal-DMt-6tdZ.js → pascal-BKVXrzC1.js} +0 -0
  342. /package/dist/web/assets/{pkl-QBTyYQmB.js → pkl-BTd-YRsO.js} +0 -0
  343. /package/dist/web/assets/{plastic-BTSUp8Fk.js → plastic-eiGvBIxV.js} +0 -0
  344. /package/dist/web/assets/{plsql-DQv3IFXP.js → plsql-C290tieP.js} +0 -0
  345. /package/dist/web/assets/{po-CNwZx4tW.js → po-DyDwh0tx.js} +0 -0
  346. /package/dist/web/assets/{poimandres-8Os7Qequ.js → poimandres-B87zc_g-.js} +0 -0
  347. /package/dist/web/assets/{polar-b4yK8oD8.js → polar-Cdub1YMT.js} +0 -0
  348. /package/dist/web/assets/{postcss-sFctwpxx.js → postcss-BcI_3K0v.js} +0 -0
  349. /package/dist/web/assets/{powerquery-Cg_WrtuN.js → powerquery-OdMrkJSe.js} +0 -0
  350. /package/dist/web/assets/{powershell-C7Ifz95h.js → powershell-C8auT6xg.js} +0 -0
  351. /package/dist/web/assets/{prisma-Z52HUJzQ.js → prisma-DIbVv8PA.js} +0 -0
  352. /package/dist/web/assets/{prolog-DLqW-zR1.js → prolog-DbTOH3Ld.js} +0 -0
  353. /package/dist/web/assets/{proto-BOIzxCCJ.js → proto-C4Cq2dCD.js} +0 -0
  354. /package/dist/web/assets/{puppet-De7TjZIf.js → puppet-DJp3uqum.js} +0 -0
  355. /package/dist/web/assets/{purescript-R76ou1WT.js → purescript-CLsV4rPU.js} +0 -0
  356. /package/dist/web/assets/{python-Dprm0tNP.js → python-2gBtEza2.js} +0 -0
  357. /package/dist/web/assets/{qmldir-Clp_jpNw.js → qmldir-DfhULcua.js} +0 -0
  358. /package/dist/web/assets/{qss-eQPYYzSo.js → qss-DK--VTTV.js} +0 -0
  359. /package/dist/web/assets/{r-CCcRHIf5.js → r-BArBO2Sa.js} +0 -0
  360. /package/dist/web/assets/{racket-CzE472yp.js → racket-5mijHsVy.js} +0 -0
  361. /package/dist/web/assets/{raku-DQwXrTSi.js → raku-ir0suElk.js} +0 -0
  362. /package/dist/web/assets/{red-KCS6wyop.js → red-DSecpIOT.js} +0 -0
  363. /package/dist/web/assets/{reg-CcrAddUh.js → reg-Dp30FusS.js} +0 -0
  364. /package/dist/web/assets/{regexp-DDbud-Ri.js → regexp-DXJnEM_6.js} +0 -0
  365. /package/dist/web/assets/{rel-99GDgaHp.js → rel-Dr483ozj.js} +0 -0
  366. /package/dist/web/assets/{riscv-Dm2eNv0R.js → riscv-ZfBy5IA1.js} +0 -0
  367. /package/dist/web/assets/{ron-CzFt0ygH.js → ron-ZJ_CljGP.js} +0 -0
  368. /package/dist/web/assets/{rose-pine-Ck6lCrCP.js → rose-pine-CcW_eJ6G.js} +0 -0
  369. /package/dist/web/assets/{rose-pine-dawn-vtALRJNj.js → rose-pine-dawn-v2l_UF-j.js} +0 -0
  370. /package/dist/web/assets/{rose-pine-moon-DPto8qXw.js → rose-pine-moon-CNXkwf3D.js} +0 -0
  371. /package/dist/web/assets/{rosmsg-NtS6429H.js → rosmsg-BMYMVW84.js} +0 -0
  372. /package/dist/web/assets/{rust-BjIXvF9h.js → rust-BR-zJh5q.js} +0 -0
  373. /package/dist/web/assets/{sass-CQ23wf5E.js → sass-BukPOBFz.js} +0 -0
  374. /package/dist/web/assets/{scala-LfKLM143.js → scala-DUFY7D6D.js} +0 -0
  375. /package/dist/web/assets/{scheme-D3SLBXlF.js → scheme-Dl-dNNxQ.js} +0 -0
  376. /package/dist/web/assets/{sdbl-ODRd2rGN.js → sdbl-DdmlQhia.js} +0 -0
  377. /package/dist/web/assets/{shellscript-3KB1G_oA.js → shellscript-UyhrvGcd.js} +0 -0
  378. /package/dist/web/assets/{slack-dark-DTtyWmIy.js → slack-dark-Cv6Szr-q.js} +0 -0
  379. /package/dist/web/assets/{slack-ochin-Bu0PApk3.js → slack-ochin-V6Ii3lAm.js} +0 -0
  380. /package/dist/web/assets/{smalltalk-haMT-Sbe.js → smalltalk-BUCv5G91.js} +0 -0
  381. /package/dist/web/assets/{snazzy-light-DXJzefE9.js → snazzy-light-B67a78qi.js} +0 -0
  382. /package/dist/web/assets/{solarized-dark-B6LyYa18.js → solarized-dark-ccWnfYyA.js} +0 -0
  383. /package/dist/web/assets/{solarized-light-QLADebkv.js → solarized-light-C3WyRO5I.js} +0 -0
  384. /package/dist/web/assets/{solidity-mzfq1aDc.js → solidity-BFbRPNi_.js} +0 -0
  385. /package/dist/web/assets/{splunk-CyH4RWBp.js → splunk-zdpwCJLE.js} +0 -0
  386. /package/dist/web/assets/{sql-CWVlT5D3.js → sql-B2IPUsfz.js} +0 -0
  387. /package/dist/web/assets/{ssh-config-DNvQJ1Qx.js → ssh-config-Co4cXifq.js} +0 -0
  388. /package/dist/web/assets/{stylus-ByQQdtmf.js → stylus-CmI75XY8.js} +0 -0
  389. /package/dist/web/assets/{swift-D1cpY4ow.js → swift-Dfks9YQI.js} +0 -0
  390. /package/dist/web/assets/{synthwave-84-BDF_-QiW.js → synthwave-84-B3LERzNS.js} +0 -0
  391. /package/dist/web/assets/{system-verilog-BYrkMydC.js → system-verilog-BFvldiwl.js} +0 -0
  392. /package/dist/web/assets/{systemd-CQm3zyK0.js → systemd-Cu4Vvgbu.js} +0 -0
  393. /package/dist/web/assets/{talonscript-DMW5CzE1.js → talonscript-Bnq32pUB.js} +0 -0
  394. /package/dist/web/assets/{tasl-BhFzMCr2.js → tasl-Nwe2K3J1.js} +0 -0
  395. /package/dist/web/assets/{tcl-D7VEAF-9.js → tcl-zOnpywrl.js} +0 -0
  396. /package/dist/web/assets/{terraform-DdT5A0Vy.js → terraform-Bc9Vj-n3.js} +0 -0
  397. /package/dist/web/assets/{tokyo-night-WGLMM6Q9.js → tokyo-night-9_KyM8M2.js} +0 -0
  398. /package/dist/web/assets/{toml-CZ7ipXHZ.js → toml-ByH-fxOY.js} +0 -0
  399. /package/dist/web/assets/{tsv-B1zVvoTr.js → tsv-DrCnDClP.js} +0 -0
  400. /package/dist/web/assets/{tsx-D4HwRUBq.js → tsx-B8LafSYr.js} +0 -0
  401. /package/dist/web/assets/{turtle-B4r8KEJH.js → turtle-DuyP_QCJ.js} +0 -0
  402. /package/dist/web/assets/{typescript-BnHhxMtp.js → typescript-BTBJb5RD.js} +0 -0
  403. /package/dist/web/assets/{typespec-DP2q46GT.js → typespec-DdOFo7M5.js} +0 -0
  404. /package/dist/web/assets/{typst-DFsD_yaD.js → typst-LYvnBWQu.js} +0 -0
  405. /package/dist/web/assets/{use-blob-url-DpDVcTeK.js → use-blob-url-CpyRr7Cx.js} +0 -0
  406. /package/dist/web/assets/{v-Bji8hSVT.js → v-BuBYA1_x.js} +0 -0
  407. /package/dist/web/assets/{vala-D3TIgGmU.js → vala-vRIBYYe3.js} +0 -0
  408. /package/dist/web/assets/{vb-DvcxFS2q.js → vb-DwGi-IYM.js} +0 -0
  409. /package/dist/web/assets/{vendor-xterm-DfNMj6xt.js → vendor-xterm-i6SHFTfU.js} +0 -0
  410. /package/dist/web/assets/{verilog-Dy7cF35d.js → verilog-6B1X4G2-.js} +0 -0
  411. /package/dist/web/assets/{vesper-BzjwUv9J.js → vesper-Dw1y_Ae7.js} +0 -0
  412. /package/dist/web/assets/{vhdl-DuFnFNmW.js → vhdl-DK8JwBzJ.js} +0 -0
  413. /package/dist/web/assets/{viml-yAPgKlbz.js → viml-BTKIEIqm.js} +0 -0
  414. /package/dist/web/assets/{vitesse-black-oSSQdyIZ.js → vitesse-black-BqqolhEg.js} +0 -0
  415. /package/dist/web/assets/{vitesse-dark-BZxwPihB.js → vitesse-dark-B9JL5WQA.js} +0 -0
  416. /package/dist/web/assets/{vitesse-light-uIigycvt.js → vitesse-light-DYJKj2se.js} +0 -0
  417. /package/dist/web/assets/{vyper-CX3NAxm5.js → vyper-D-jDI3WH.js} +0 -0
  418. /package/dist/web/assets/{wasm-Coen1MOg.js → wasm-1-GlNdpk.js} +0 -0
  419. /package/dist/web/assets/{wasm-D9td37qO.js → wasm-BBW4WmT2.js} +0 -0
  420. /package/dist/web/assets/{wenyan-lwNIHgk6.js → wenyan-B6cM7sDO.js} +0 -0
  421. /package/dist/web/assets/{wgsl-DQAzCfog.js → wgsl-FaHGQgko.js} +0 -0
  422. /package/dist/web/assets/{wikitext-DTXmt5NE.js → wikitext-DtIyPUrk.js} +0 -0
  423. /package/dist/web/assets/{wit-Bdw_7WDH.js → wit-BMVRif5Y.js} +0 -0
  424. /package/dist/web/assets/{wolfram-DqyHDZ07.js → wolfram-DQsCGohn.js} +0 -0
  425. /package/dist/web/assets/{yaml-CPXhdByd.js → yaml-C-Va56Gt.js} +0 -0
  426. /package/dist/web/assets/{zenscript-6s_i5zek.js → zenscript-DdobKGI-.js} +0 -0
  427. /package/dist/web/assets/{zig-B2htezJ_.js → zig-vqDFwj6q.js} +0 -0
@@ -575,16 +575,19 @@ class AccountService {
575
575
  if (!res.ok) {
576
576
  const errorBody = await res.text().catch(() => "");
577
577
  console.error(`[accounts] Refresh failed for ${accountId}: ${res.status} ${errorBody}`);
578
- // invalid_grant or invalid_request = refresh token permanently dead → clear it so account becomes temporary
579
578
  if (errorBody.includes("invalid_grant") || errorBody.includes("invalid_request")) {
580
- // Double-check: another session might have already refreshed between our read and the OAuth call
579
+ // Another session/process may have refreshed (and rotated) the token between
580
+ // our read and this OAuth call — if the DB token is now fresh, this failure is stale.
581
581
  const recheckAccount = this.getWithTokens(accountId);
582
582
  if (recheckAccount?.expiresAt && recheckAccount.expiresAt - Math.floor(Date.now() / 1000) > 60) {
583
583
  console.log(`[accounts] Refresh failed with invalid_grant but DB token is now fresh — another session refreshed it`);
584
584
  return;
585
585
  }
586
- console.log(`[accounts] Clearing invalid refresh token for ${account.email ?? accountId} account is now temporary`);
587
- updateAccount(accountId, { refresh_token: encrypt("") });
586
+ // Do NOT wipe the refresh token. On multi-device/multi-process setups the token is
587
+ // usually rotated elsewhere, not truly dead; clearing it bricks the local copy
588
+ // permanently with no recovery path (esp. for parked/disabled accounts). Preserve
589
+ // it so re-enable / re-import / re-sync can restore access.
590
+ console.warn(`[accounts] Refresh token rejected for ${account.email ?? accountId} — preserving token for recovery (not clearing)`);
588
591
  }
589
592
  if (disableOnFail) {
590
593
  this.setDisabled(accountId);
@@ -743,9 +746,12 @@ class AccountService {
743
746
  const accounts = this.list();
744
747
  const nowS = Math.floor(Date.now() / 1000);
745
748
  for (const acc of accounts) {
746
- // Disabled accounts are still refreshed to keep the refresh token alive.
747
- // Disable only removes an account from the chat rotation; skipping refresh
748
- // lets the token rotation lapse and eventually expires the account for good.
749
+ // Freeze disabled accounts: skip background refresh entirely.
750
+ // Refreshing rotates the OAuth refresh token; when the same account is
751
+ // shared across machines/processes the rotation races and one side gets
752
+ // invalid_grant, killing an account the user only meant to park. Leaving
753
+ // a disabled account untouched keeps its token intact until re-enabled.
754
+ if (acc.status === "disabled") continue;
749
755
  if (!acc.expiresAt) continue;
750
756
  if (acc.expiresAt - nowS > REFRESH_BUFFER_S) continue;
751
757
  // Skip temporary accounts (no refresh token) — they can't be refreshed
@@ -3,7 +3,7 @@ import { resolve } from "node:path";
3
3
  import { mkdirSync, existsSync } from "node:fs";
4
4
  import { encrypt, decrypt } from "../lib/account-crypto.ts";
5
5
  import { getPpmDir } from "./ppm-dir.ts";
6
- export const CURRENT_SCHEMA_VERSION = 35;
6
+ export const CURRENT_SCHEMA_VERSION = 36;
7
7
 
8
8
  let db: Database | null = null;
9
9
  let dbProfile: string | null = null;
@@ -831,6 +831,12 @@ function runMigrations(database: Database): void {
831
831
  PRAGMA user_version = 35;
832
832
  `);
833
833
  }
834
+
835
+ if (current < 36) {
836
+ try { database.exec("ALTER TABLE session_metadata ADD COLUMN effort TEXT"); } catch {}
837
+ try { database.exec("ALTER TABLE session_metadata ADD COLUMN thinking_budget INTEGER"); } catch {}
838
+ database.exec("PRAGMA user_version = 36;");
839
+ }
834
840
  }
835
841
 
836
842
  // ---------------------------------------------------------------------------
@@ -1023,6 +1029,30 @@ export function setSessionModel(sessionId: string, model: string): void {
1023
1029
  ).run(sessionId, model);
1024
1030
  }
1025
1031
 
1032
+ /** Per-session effort override; null when session uses provider default */
1033
+ export function getSessionEffort(sessionId: string): string | null {
1034
+ const row = getDb().query("SELECT effort FROM session_metadata WHERE session_id = ?").get(sessionId) as { effort: string | null } | null;
1035
+ return row?.effort ?? null;
1036
+ }
1037
+
1038
+ export function setSessionEffort(sessionId: string, effort: string): void {
1039
+ getDb().query(
1040
+ "INSERT INTO session_metadata (session_id, effort) VALUES (?, ?) ON CONFLICT(session_id) DO UPDATE SET effort = excluded.effort",
1041
+ ).run(sessionId, effort);
1042
+ }
1043
+
1044
+ /** Per-session thinking budget (maxThinkingTokens); null = thinking OFF / use provider default */
1045
+ export function getSessionThinking(sessionId: string): number | null {
1046
+ const row = getDb().query("SELECT thinking_budget FROM session_metadata WHERE session_id = ?").get(sessionId) as { thinking_budget: number | null } | null;
1047
+ return row?.thinking_budget ?? null;
1048
+ }
1049
+
1050
+ export function setSessionThinking(sessionId: string, budget: number | null): void {
1051
+ getDb().query(
1052
+ "INSERT INTO session_metadata (session_id, thinking_budget) VALUES (?, ?) ON CONFLICT(session_id) DO UPDATE SET thinking_budget = excluded.thinking_budget",
1053
+ ).run(sessionId, budget);
1054
+ }
1055
+
1026
1056
  // ---------------------------------------------------------------------------
1027
1057
  // Unread tracking
1028
1058
  // ---------------------------------------------------------------------------
package/src/types/api.ts CHANGED
@@ -23,9 +23,11 @@ export type TerminalWsMessage =
23
23
 
24
24
  /** WebSocket message types (chat) */
25
25
  export type ChatWsClientMessage =
26
- | { type: "message"; content: string; permissionMode?: string; priority?: 'now' | 'next' | 'later'; images?: Array<{ data: string; mediaType: string }>; model?: string }
26
+ | { type: "message"; content: string; permissionMode?: string; priority?: 'now' | 'next' | 'later'; images?: Array<{ data: string; mediaType: string }>; model?: string; effort?: string; thinking?: boolean }
27
27
  | { type: "cancel" }
28
28
  | { type: "set_model"; model: string }
29
+ | { type: "set_effort"; effort: string }
30
+ | { type: "set_thinking"; enabled: boolean }
29
31
  | { type: "approval_response"; requestId: string; approved: boolean; reason?: string; data?: unknown }
30
32
  | { type: "kill_background_shell"; shellId: string }
31
33
  | { type: "ready" };
@@ -57,7 +59,7 @@ export type ChatWsServerMessage =
57
59
  | { type: "error"; message: string }
58
60
  | { type: "account_info"; accountId: string; accountLabel: string }
59
61
  | { type: "phase_changed"; phase: SessionPhase; elapsed?: number }
60
- | { type: "session_state"; sessionId: string; phase: SessionPhase; pendingApproval: { requestId: string; tool: string; input: unknown } | null; sessionTitle: string | null; model?: string }
62
+ | { type: "session_state"; sessionId: string; phase: SessionPhase; pendingApproval: { requestId: string; tool: string; input: unknown } | null; sessionTitle: string | null; model?: string; effort?: string; thinking?: boolean }
61
63
  | { type: "turn_events"; events: unknown[] }
62
64
  | { type: "title_updated"; title: string }
63
65
  | { type: "compact_status"; status: "compacting" | "done" }
package/src/types/chat.ts CHANGED
@@ -4,8 +4,16 @@ export interface SendMessageOpts {
4
4
  images?: Array<{ data: string; mediaType: string }>;
5
5
  /** Per-session model override; falls back to provider config model when absent */
6
6
  model?: string;
7
+ /** Override the provider's 1M-context setting for this call (false = never add the
8
+ * [1m] suffix). Used by lightweight calls (e.g. the group-chat router) whose small
9
+ * model may not support a 1M window. Falls back to provider config when absent. */
10
+ oneMContext?: boolean;
7
11
  /** Per-query turn cap; falls back to provider config max_turns when absent */
8
12
  maxTurns?: number;
13
+ /** Per-session effort override (low|medium|high|xhigh|max); falls back to provider config */
14
+ effort?: string;
15
+ /** Per-session thinking budget → SDK maxThinkingTokens; falls back to provider config */
16
+ maxThinkingTokens?: number;
9
17
  }
10
18
 
11
19
  export interface AIProvider {
@@ -67,7 +67,7 @@ export interface AIProviderConfig {
67
67
  api_key_env?: string;
68
68
  api_key?: string;
69
69
  base_url?: string;
70
- effort?: "low" | "medium" | "high" | "max";
70
+ effort?: "low" | "medium" | "high" | "xhigh" | "max";
71
71
  max_turns?: number;
72
72
  max_budget_usd?: number;
73
73
  thinking_budget_tokens?: number;
@@ -97,7 +97,7 @@ export const DEFAULT_CONFIG: PpmConfig = {
97
97
  claude: {
98
98
  type: "agent-sdk",
99
99
  api_key_env: "ANTHROPIC_API_KEY",
100
- model: "claude-opus-4-8",
100
+ model: "claude-opus-5",
101
101
  effort: "high",
102
102
  max_turns: 1000,
103
103
  permission_mode: "bypassPermissions",
@@ -120,8 +120,8 @@ export const DEFAULT_CONFIG: PpmConfig = {
120
120
  };
121
121
 
122
122
  const VALID_TYPES = ["agent-sdk", "cli", "mock"] as const;
123
- const VALID_EFFORTS = ["low", "medium", "high"] as const;
124
- const VALID_MODELS = ["claude-fable-5", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-4-6", "claude-sonnet-4-6", "claude-haiku-4-5"] as const;
123
+ const VALID_EFFORTS = ["low", "medium", "high", "xhigh", "max"] as const;
124
+ const VALID_MODELS = ["claude-opus-5", "claude-fable-5", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-4-6", "claude-sonnet-5", "claude-sonnet-4-6", "claude-haiku-4-5"] as const;
125
125
  /** Allowed CLI commands for CLI providers (prevents command injection) */
126
126
  const VALID_CLI_COMMANDS = ["cursor-agent", "codex", "gemini"] as const;
127
127
  /** Only these values are allowed for default_provider in config */
@@ -241,12 +241,7 @@ export function sanitizeConfig(config: PpmConfig): boolean {
241
241
  dirty = true;
242
242
  }
243
243
 
244
- // Downgrade "max" effort → "high" (not available for Claude.ai subscribers)
245
244
  for (const provider of Object.values(config.ai.providers)) {
246
- if ((provider as any).effort === "max") {
247
- provider.effort = "high";
248
- dirty = true;
249
- }
250
245
  // Fix invalid permission_mode
251
246
  if (provider.permission_mode != null && !["default", "acceptEdits", "plan", "bypassPermissions"].includes(provider.permission_mode)) {
252
247
  provider.permission_mode = "bypassPermissions";
@@ -112,6 +112,10 @@ export function ChatTab({ metadata, tabId }: ChatTabProps) {
112
112
  sessionTitle,
113
113
  model,
114
114
  setModel,
115
+ effort,
116
+ setEffort,
117
+ thinking,
118
+ setThinking,
115
119
  sendMessage,
116
120
  respondToApproval,
117
121
  cancelStreaming,
@@ -681,6 +685,10 @@ export function ChatTab({ metadata, tabId }: ChatTabProps) {
681
685
  onProviderChange={!sessionId ? setProviderId : undefined}
682
686
  model={model}
683
687
  onModelChange={setModel}
688
+ effort={effort}
689
+ onEffortChange={setEffort}
690
+ thinking={thinking}
691
+ onThinkingChange={setThinking}
684
692
  />
685
693
  )}
686
694
  </div>
@@ -7,7 +7,7 @@ import { isImageFile } from "@/lib/file-support";
7
7
  import { AttachmentChips } from "./attachment-chips";
8
8
  import { ModeSelector, getModeLabel, getModeIcon } from "./mode-selector";
9
9
  import { ProviderSelector } from "./provider-selector";
10
- import { ModelSelector } from "./model-selector";
10
+ import { ModelThinkingSelector } from "./model-thinking-selector";
11
11
  import type { SlashItem } from "./slash-command-picker";
12
12
  import type { FileNode } from "../../../types/project";
13
13
  import { useFileStore } from "@/stores/file-store";
@@ -69,6 +69,14 @@ interface MessageInputProps {
69
69
  model?: string | null;
70
70
  /** Model change handler — undefined when no active session */
71
71
  onModelChange?: (model: string) => void;
72
+ /** Current per-session effort (null = provider default) */
73
+ effort?: string | null;
74
+ /** Effort change handler */
75
+ onEffortChange?: (effort: string) => void;
76
+ /** Current per-session thinking on/off */
77
+ thinking?: boolean;
78
+ /** Thinking toggle handler */
79
+ onThinkingChange?: (enabled: boolean) => void;
72
80
  }
73
81
 
74
82
  export const MessageInput = memo(function MessageInput({
@@ -96,6 +104,10 @@ export const MessageInput = memo(function MessageInput({
96
104
  onProviderChange,
97
105
  model,
98
106
  onModelChange,
107
+ effort,
108
+ onEffortChange,
109
+ thinking,
110
+ onThinkingChange,
99
111
  }: MessageInputProps) {
100
112
  // Uncontrolled textarea: value lives in DOM + ref, not React state.
101
113
  // Only `hasText` state triggers re-renders (empty↔non-empty for send button).
@@ -700,9 +712,13 @@ export const MessageInput = memo(function MessageInput({
700
712
  />
701
713
  )}
702
714
  {onModelChange && projectName && (
703
- <ModelSelector
704
- value={model ?? null}
705
- onChange={onModelChange}
715
+ <ModelThinkingSelector
716
+ model={model ?? null}
717
+ effort={effort ?? null}
718
+ thinking={thinking ?? false}
719
+ onModelChange={onModelChange}
720
+ onEffortChange={onEffortChange ?? (() => {})}
721
+ onThinkingChange={onThinkingChange ?? (() => {})}
706
722
  projectName={projectName}
707
723
  providerId={providerId ?? "claude"}
708
724
  disabled={isStreaming}
@@ -795,9 +811,13 @@ export const MessageInput = memo(function MessageInput({
795
811
  />
796
812
  )}
797
813
  {onModelChange && projectName && (
798
- <ModelSelector
799
- value={model ?? null}
800
- onChange={onModelChange}
814
+ <ModelThinkingSelector
815
+ model={model ?? null}
816
+ effort={effort ?? null}
817
+ thinking={thinking ?? false}
818
+ onModelChange={onModelChange}
819
+ onEffortChange={onEffortChange ?? (() => {})}
820
+ onThinkingChange={onThinkingChange ?? (() => {})}
801
821
  projectName={projectName}
802
822
  providerId={providerId ?? "claude"}
803
823
  disabled={isStreaming}
@@ -637,12 +637,15 @@ function parseIdeOpenedFile(text: string): { idePath: string | null; cleanText:
637
637
  /** Parse user message content, extracting attached file paths and the actual text */
638
638
  function parseUserAttachments(content: string): { files: string[]; text: string } {
639
639
  // Match: [Attached file: /path] or [Attached files:\n/path1\n/path2\n]
640
- const singleMatch = content.match(/^\[Attached file: (.+?)\]\n\n?/);
640
+ // Trailing newlines are optional — an attachment-only message has the marker
641
+ // trimmed to the end of the string (extractTerminalBlocks trims), so the
642
+ // separator newlines may be absent.
643
+ const singleMatch = content.match(/^\[Attached file: (.+?)\]\n*/);
641
644
  if (singleMatch) {
642
645
  return { files: [singleMatch[1]!], text: content.slice(singleMatch[0].length) };
643
646
  }
644
647
 
645
- const multiMatch = content.match(/^\[Attached files:\n([\s\S]+?)\]\n\n?/);
648
+ const multiMatch = content.match(/^\[Attached files:\n([\s\S]+?)\]\n*/);
646
649
  if (multiMatch) {
647
650
  const files = multiMatch[1]!.split("\n").map((l) => l.trim()).filter(Boolean);
648
651
  return { files, text: content.slice(multiMatch[0].length) };
@@ -815,7 +818,7 @@ function UserBubble({ content, messageId, timestamp, projectName, onFork, onEdit
815
818
  expanded && "max-h-[50vh] overflow-y-auto",
816
819
  )}
817
820
  >
818
- {isSystemContext ? <TextWithFilePaths text={text} projectName={projectName} /> : text}
821
+ {isSystemContext ? <TextWithFilePaths text={text} projectName={projectName} /> : <TextWithLinks text={text} />}
819
822
  </div>
820
823
  )}
821
824
  {(isOverflowing || expanded) && (
@@ -1002,6 +1005,48 @@ function FilePathChip({ path, projectName }: { path: string; projectName?: strin
1002
1005
  );
1003
1006
  }
1004
1007
 
1008
+ /** Render plain text with http(s) URLs turned into clickable links. Preserves
1009
+ * whitespace/newlines via the surrounding `whitespace-pre-wrap` container. */
1010
+ function TextWithLinks({ text }: { text: string }) {
1011
+ const parts = useMemo(() => {
1012
+ const re = /(https?:\/\/[^\s<>()]+[^\s<>().,;:!?'"])/g;
1013
+ const result: { kind: "text" | "url"; value: string }[] = [];
1014
+ let last = 0;
1015
+ let m;
1016
+ while ((m = re.exec(text)) !== null) {
1017
+ if (m.index > last) result.push({ kind: "text", value: text.slice(last, m.index) });
1018
+ result.push({ kind: "url", value: m[1]! });
1019
+ last = m.index + m[0].length;
1020
+ }
1021
+ if (last < text.length) result.push({ kind: "text", value: text.slice(last) });
1022
+ return result;
1023
+ }, [text]);
1024
+
1025
+ // No URLs — return the raw string so nothing about the layout changes.
1026
+ if (parts.every((p) => p.kind === "text")) return <>{text}</>;
1027
+
1028
+ return (
1029
+ <>
1030
+ {parts.map((p, i) =>
1031
+ p.kind === "url" ? (
1032
+ <a
1033
+ key={i}
1034
+ href={p.value}
1035
+ target="_blank"
1036
+ rel="noopener noreferrer"
1037
+ className="text-primary underline underline-offset-2 hover:text-primary/80 break-all"
1038
+ onClick={(e) => e.stopPropagation()}
1039
+ >
1040
+ {p.value}
1041
+ </a>
1042
+ ) : (
1043
+ <span key={i}>{p.value}</span>
1044
+ ),
1045
+ )}
1046
+ </>
1047
+ );
1048
+ }
1049
+
1005
1050
  /** Render text with absolute file paths detected and turned into clickable chips */
1006
1051
  function TextWithFilePaths({ text, projectName }: { text: string; projectName?: string }) {
1007
1052
  const parts = useMemo(() => {
@@ -0,0 +1,33 @@
1
+ // Pure helpers for the unified model + thinking picker. Kept DOM-free so the
2
+ // label↔value mapping (the crash-prone "Extra"→"xhigh" contract) is unit-testable
3
+ // without a browser harness.
4
+ //
5
+ // SDK effort enum = low | medium | high | xhigh | max. The app UI shows "Extra"
6
+ // for the SDK value "xhigh"; the literal "extra" would crash the CLI subprocess,
7
+ // so it must NEVER appear as a value here.
8
+
9
+ export interface EffortOption {
10
+ label: string;
11
+ value: "low" | "medium" | "high" | "xhigh" | "max";
12
+ default?: boolean;
13
+ }
14
+
15
+ export const EFFORT_OPTIONS: EffortOption[] = [
16
+ { label: "Low", value: "low" },
17
+ { label: "Medium", value: "medium" },
18
+ { label: "High", value: "high", default: true },
19
+ { label: "Extra", value: "xhigh" },
20
+ { label: "Max", value: "max" },
21
+ ];
22
+
23
+ /** UI label for an effort value; falls back to the raw value when unknown. */
24
+ export function effortLabel(value: string | null | undefined): string {
25
+ if (!value) return "";
26
+ return EFFORT_OPTIONS.find((o) => o.value === value)?.label ?? value;
27
+ }
28
+
29
+ /** Chip text: model display, plus " · <Effort>" when an effort is set. */
30
+ export function chipLabel(modelDisplay: string, effortValue: string | null | undefined): string {
31
+ const eff = effortLabel(effortValue);
32
+ return eff ? `${modelDisplay} · ${eff}` : modelDisplay;
33
+ }
@@ -0,0 +1,189 @@
1
+ import { useState, useEffect, useRef, type ReactNode } from "react";
2
+ import { Check, Sparkles, Brain } from "lucide-react";
3
+ import { api, projectUrl } from "@/lib/api-client";
4
+ import { useIsMobile } from "@/hooks/use-is-mobile";
5
+ import { BottomSheet } from "@/components/ui/mobile-bottom-sheet";
6
+ import { EFFORT_OPTIONS, chipLabel } from "./model-thinking-selector-helpers";
7
+
8
+ interface ModelOption {
9
+ value: string;
10
+ label: string;
11
+ }
12
+
13
+ interface ModelThinkingSelectorProps {
14
+ model: string | null;
15
+ effort: string | null;
16
+ thinking: boolean;
17
+ onModelChange: (model: string) => void;
18
+ onEffortChange: (effort: string) => void;
19
+ onThinkingChange: (enabled: boolean) => void;
20
+ projectName: string;
21
+ providerId: string;
22
+ /** Locked while a turn is streaming (model/effort can't change mid-turn). */
23
+ disabled?: boolean;
24
+ }
25
+
26
+ /** Strip the leading "Claude " so the chip stays compact: "Claude Opus 5" → "Opus 5" */
27
+ function shortLabel(label: string): string {
28
+ return label.replace(/^Claude\s+/i, "");
29
+ }
30
+
31
+ const DEFAULT_EFFORT = EFFORT_OPTIONS.find((o) => o.default)!.value;
32
+
33
+ /**
34
+ * Unified model + thinking picker — one chip, one popup. Mirrors Anthropic's native
35
+ * picker: model list, effort levels (Extra→SDK "xhigh"), and a thinking on/off toggle.
36
+ * Desktop → absolute popover; mobile (<md) → bottom sheet with 44px targets.
37
+ */
38
+ export function ModelThinkingSelector({
39
+ model,
40
+ effort,
41
+ thinking,
42
+ onModelChange,
43
+ onEffortChange,
44
+ onThinkingChange,
45
+ projectName,
46
+ providerId,
47
+ disabled,
48
+ }: ModelThinkingSelectorProps) {
49
+ const [models, setModels] = useState<ModelOption[]>([]);
50
+ const [open, setOpen] = useState(false);
51
+ const panelRef = useRef<HTMLDivElement>(null);
52
+ const isMobile = useIsMobile();
53
+
54
+ useEffect(() => {
55
+ if (!projectName || !providerId) return;
56
+ api
57
+ .get<ModelOption[]>(`${projectUrl(projectName)}/chat/providers/${providerId}/models`)
58
+ .then(setModels)
59
+ .catch(() => {});
60
+ }, [projectName, providerId]);
61
+
62
+ useEffect(() => {
63
+ if (disabled) setOpen(false);
64
+ }, [disabled]);
65
+
66
+ // Desktop popover: close on click outside (mobile bottom sheet handles its own backdrop).
67
+ useEffect(() => {
68
+ if (!open || isMobile) return;
69
+ const handler = (e: MouseEvent) => {
70
+ if (panelRef.current && !panelRef.current.contains(e.target as Node)) setOpen(false);
71
+ };
72
+ document.addEventListener("mousedown", handler);
73
+ return () => document.removeEventListener("mousedown", handler);
74
+ }, [open, isMobile]);
75
+
76
+ const current = models.find((m) => m.value === model);
77
+ const modelDisplay = current ? shortLabel(current.label) : model ? shortLabel(model) : "Model";
78
+ const effortValue = effort ?? DEFAULT_EFFORT;
79
+ const showModelList = models.length > 1;
80
+ const chipText = chipLabel(modelDisplay, effortValue);
81
+
82
+ const pick = (fn: () => void) => {
83
+ fn();
84
+ if (!isMobile) setOpen(false);
85
+ };
86
+
87
+ const content = (
88
+ <div className="flex divide-x divide-border">
89
+ {/* Left column: model list */}
90
+ {showModelList && (
91
+ <div className="flex-1 min-w-0 py-1">
92
+ <SectionLabel>Model</SectionLabel>
93
+ {models.map((m) => (
94
+ <OptionRow key={m.value} active={m.value === model} onClick={() => pick(() => onModelChange(m.value))}>
95
+ <span className="flex-1 truncate">{shortLabel(m.label)}</span>
96
+ {m.value === model && <Check className="size-4 shrink-0 text-primary" />}
97
+ </OptionRow>
98
+ ))}
99
+ </div>
100
+ )}
101
+ {/* Right column: effort + thinking toggle */}
102
+ <div className="flex-1 min-w-0 py-1">
103
+ <SectionLabel>Effort</SectionLabel>
104
+ {EFFORT_OPTIONS.map((o) => (
105
+ <OptionRow key={o.value} active={o.value === effortValue} onClick={() => pick(() => onEffortChange(o.value))}>
106
+ <span className="flex-1 truncate">
107
+ {o.label}
108
+ {o.default && <span className="ml-2 text-xs text-text-subtle">Default</span>}
109
+ </span>
110
+ {o.value === effortValue && <Check className="size-4 shrink-0 text-primary" />}
111
+ </OptionRow>
112
+ ))}
113
+ <Separator />
114
+ <button
115
+ type="button"
116
+ onClick={() => onThinkingChange(!thinking)}
117
+ className="w-full flex items-center gap-3 px-3 min-h-[44px] text-left text-sm hover:bg-surface-elevated"
118
+ role="switch"
119
+ aria-checked={thinking}
120
+ >
121
+ <Brain className="size-4 shrink-0" />
122
+ <span className="flex-1">Thinking</span>
123
+ <span className={`inline-flex h-5 w-9 items-center rounded-full transition-colors ${thinking ? "bg-primary" : "bg-border"}`}>
124
+ <span className={`h-4 w-4 rounded-full bg-white transition-transform ${thinking ? "translate-x-4" : "translate-x-0.5"}`} />
125
+ </span>
126
+ </button>
127
+ </div>
128
+ </div>
129
+ );
130
+
131
+ return (
132
+ <div className="relative">
133
+ <button
134
+ type="button"
135
+ disabled={disabled}
136
+ onClick={(e) => {
137
+ e.stopPropagation();
138
+ if (!disabled) setOpen((v) => !v);
139
+ }}
140
+ className="inline-flex items-center gap-1.5 px-[9px] py-1 rounded-full text-[11.5px] text-primary bg-accent-wash border border-accent-wash-border hover:brightness-110 transition-[filter] disabled:opacity-50 disabled:cursor-default"
141
+ aria-label={`Model ${modelDisplay}, effort ${effortValue}${thinking ? ", thinking on" : ""}`}
142
+ title={disabled ? "Can't change while running" : chipText}
143
+ >
144
+ <Sparkles className="h-3.5 w-3.5 shrink-0" />
145
+ <span className="max-w-[140px] truncate">{chipText}</span>
146
+ {thinking && <Brain className="h-3 w-3 shrink-0" />}
147
+ </button>
148
+
149
+ {open && !disabled && (
150
+ isMobile ? (
151
+ <BottomSheet open={open} onClose={() => setOpen(false)}>
152
+ <div className="px-1 pb-2">{content}</div>
153
+ </BottomSheet>
154
+ ) : (
155
+ <div
156
+ ref={panelRef}
157
+ role="listbox"
158
+ aria-label="Model and thinking"
159
+ onMouseDown={(e) => e.stopPropagation()}
160
+ onClick={(e) => e.stopPropagation()}
161
+ className="absolute bottom-full left-0 mb-1 z-50 w-80 rounded-lg border border-border popover-solid shadow-[var(--shadow-panel)] max-h-[70vh] overflow-y-auto"
162
+ >
163
+ {content}
164
+ </div>
165
+ )
166
+ )}
167
+ </div>
168
+ );
169
+ }
170
+
171
+ function SectionLabel({ children }: { children: ReactNode }) {
172
+ return <div className="px-3 py-1.5 text-xs font-medium text-text-secondary">{children}</div>;
173
+ }
174
+
175
+ function Separator() {
176
+ return <div className="my-1 border-t border-border" />;
177
+ }
178
+
179
+ function OptionRow({ active, onClick, children }: { active: boolean; onClick: () => void; children: ReactNode }) {
180
+ return (
181
+ <button
182
+ type="button"
183
+ onClick={onClick}
184
+ className={`w-full flex items-center gap-3 px-3 min-h-[44px] text-left text-sm text-text-primary transition-colors hover:bg-surface-elevated ${active ? "bg-surface-elevated" : ""}`}
185
+ >
186
+ {children}
187
+ </button>
188
+ );
189
+ }
@@ -20,6 +20,8 @@ const EFFORT_OPTIONS = [
20
20
  { value: "low", label: "Low" },
21
21
  { value: "medium", label: "Medium" },
22
22
  { value: "high", label: "High" },
23
+ { value: "xhigh", label: "Extra" },
24
+ { value: "max", label: "Max" },
23
25
  ];
24
26
 
25
27
  const PERMISSION_MODE_OPTIONS = [
@@ -8,7 +8,7 @@ import {
8
8
  } from "@/components/ui/dialog";
9
9
 
10
10
  const DEFAULT_MESSAGE = "Hello! Reply briefly.";
11
- const DEFAULT_MODEL = "claude-opus-4-8";
11
+ const DEFAULT_MODEL = "claude-opus-5";
12
12
 
13
13
  type EndpointFormat = "anthropic" | "openai";
14
14
 
@@ -159,10 +159,12 @@ function ProxyTestForm({ authKey, baseUrl }: ProxyTestDialogProps) {
159
159
  onChange={(e) => setModel(e.target.value)}
160
160
  className="h-8 w-full rounded-md border bg-background px-2 text-[11px]"
161
161
  >
162
+ <option value="claude-opus-5">claude-opus-5</option>
162
163
  <option value="claude-fable-5">claude-fable-5</option>
163
164
  <option value="claude-opus-4-8">claude-opus-4-8</option>
164
165
  <option value="claude-opus-4-7">claude-opus-4-7</option>
165
166
  <option value="claude-opus-4-6">claude-opus-4-6</option>
167
+ <option value="claude-sonnet-5">claude-sonnet-5</option>
166
168
  <option value="claude-sonnet-4-6">claude-sonnet-4-6</option>
167
169
  <option value="claude-haiku-4-5">claude-haiku-4-5</option>
168
170
  </select>