@hienlh/ppm 0.19.5 → 0.19.7

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 (454) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/CLAUDE.md +15 -0
  3. package/assets/skills/ppm/SKILL.md +1 -1
  4. package/assets/skills/ppm/references/http-api.md +1 -1
  5. package/dist/web/assets/accounts-settings-section-D65EHybd.js +1 -0
  6. package/dist/web/assets/{ai-resource-editor-TVV8rOsT.js → ai-resource-editor-DmOGQ_1E.js} +1 -1
  7. package/dist/web/assets/{ai-settings-section-CutZAI-J.js → ai-settings-section-DP53HaV9.js} +1 -1
  8. package/dist/web/assets/{ai-settings-section-Whh5k2zL.js → ai-settings-section-Dlv_XYy3.js} +1 -1
  9. package/dist/web/assets/{angular-html-BuHNQIbQ.js → angular-html-C8nsn2VC.js} +1 -1
  10. package/dist/web/assets/{angular-ts-DHRWoLc-.js → angular-ts-Caw9nRCH.js} +1 -1
  11. package/dist/web/assets/{apl-C1VSWVei.js → apl-Dhu1LORF.js} +1 -1
  12. package/dist/web/assets/{appearance-settings-section-DbkXixUe.js → appearance-settings-section-WuJwZW7v.js} +1 -1
  13. package/dist/web/assets/architecture-PBZL5I3N-BZBxtErN.js +1 -0
  14. package/dist/web/assets/{astro-RX-rChsZ.js → astro-DwkX9sLZ.js} +1 -1
  15. package/dist/web/assets/{audio-preview-CCd1jdje.js → audio-preview-CkGZO8Uy.js} +1 -1
  16. package/dist/web/assets/{blade-CZ6bxMbK.js → blade-D1fC9Osx.js} +1 -1
  17. package/dist/web/assets/{bsl-BhgCXLWk.js → bsl-pur-PRip.js} +1 -1
  18. package/dist/web/assets/{cairo-BrwygPkn.js → cairo-DDJs9amR.js} +1 -1
  19. package/dist/web/assets/chat-tab-B3tKoaUT.js +15 -0
  20. package/dist/web/assets/{cobol-C5TGW1Ir.js → cobol-Bo0usdoM.js} +1 -1
  21. package/dist/web/assets/code-editor-8BjOSWul.js +7 -0
  22. package/dist/web/assets/{coffee-CFgKlmgI.js → coffee-DBBsbX1e.js} +1 -1
  23. package/dist/web/assets/{conflict-editor-B-HnPZX7.js → conflict-editor-D2JPf7dR.js} +1 -1
  24. package/dist/web/assets/{cpp-BhG5q3-d.js → cpp-6CTO78A-.js} +1 -1
  25. package/dist/web/assets/{crystal-DvuI7_tY.js → crystal-DAlvpAP7.js} +1 -1
  26. package/dist/web/assets/{csv-preview-CMIxkng3.js → csv-preview-DfHSVE7o.js} +1 -1
  27. package/dist/web/assets/{data-grid-overlay-editor-DP1xkog4.js → data-grid-overlay-editor-iRrpAV0e.js} +1 -1
  28. package/dist/web/assets/{database-viewer-CM6O4tar.js → database-viewer-BwSf-V1L.js} +1 -1
  29. package/dist/web/assets/{diff-viewer-nL4cAp1u.js → diff-viewer-CQU6j7uQ.js} +1 -1
  30. package/dist/web/assets/{edge-BSIEsmlI.js → edge-D0tZrpC7.js} +1 -1
  31. package/dist/web/assets/{edit-diff-preview-DeHb85DN.js → edit-diff-preview-DUgmjNre.js} +1 -1
  32. package/dist/web/assets/{elixir-BF-lrGXM.js → elixir-C1E6-o4G.js} +1 -1
  33. package/dist/web/assets/{elm-8mCsJOeN.js → elm-BKyTfeQX.js} +1 -1
  34. package/dist/web/assets/{erb-Dw5PUVKa.js → erb-Cdnr4BMI.js} +1 -1
  35. package/dist/web/assets/{erlang-BvjBIA6O.js → erlang-N1237mFq.js} +1 -1
  36. package/dist/web/assets/{esm-Bt9OwSnU.js → esm-ClNnmD9t.js} +1 -1
  37. package/dist/web/assets/{explorer-body-CuLBY282.js → explorer-body-B2FmdPAx.js} +2 -2
  38. package/dist/web/assets/{explorer-window-content-Cr8HYEIZ.js → explorer-window-content-CtSMepys.js} +1 -1
  39. package/dist/web/assets/{extension-manager-section-D_E1LteV.js → extension-manager-section-CBRXxG8W.js} +1 -1
  40. package/dist/web/assets/{extension-webview-BKVWrl6R.js → extension-webview-yfMof39w.js} +1 -1
  41. package/dist/web/assets/{files-settings-section-DzuWb19a.js → files-settings-section-Dxn0H4jj.js} +1 -1
  42. package/dist/web/assets/{fortran-fixed-form-CRjUJe9K.js → fortran-fixed-form-D_f9tVv0.js} +1 -1
  43. package/dist/web/assets/{fsharp-CjUIHIHp.js → fsharp-DEJmdhc2.js} +1 -1
  44. package/dist/web/assets/{gdresource-x_NUQFrZ.js → gdresource-Dmmrx2gP.js} +1 -1
  45. package/dist/web/assets/general-settings-section-C3ccyyOe.js +1 -0
  46. package/dist/web/assets/{git-commit-BOpxSbns.js → git-commit-qwJ867ig.js} +1 -1
  47. package/dist/web/assets/{git-log-panel-DRLGWrO2.js → git-log-panel-d2XBsNFP.js} +1 -1
  48. package/dist/web/assets/{git-rebase-BW4xlK7k.js → git-rebase-Dkv8Zw86.js} +1 -1
  49. package/dist/web/assets/gitGraph-HDMCJU4V-BHxJbXfV.js +1 -0
  50. package/dist/web/assets/{glide-data-grid-CUtOJQyB.js → glide-data-grid-5Un6IKEP.js} +7 -7
  51. package/dist/web/assets/{glimmer-js-CT9jrmFj.js → glimmer-js-CcrXn8lQ.js} +1 -1
  52. package/dist/web/assets/{glimmer-ts-CjQT1lxK.js → glimmer-ts-CLab3lU7.js} +1 -1
  53. package/dist/web/assets/{glsl-DsFJvtg5.js → glsl-DXhkG9dU.js} +1 -1
  54. package/dist/web/assets/{graphql-Dhlnmkn_.js → graphql-Cuqsx8r3.js} +1 -1
  55. package/dist/web/assets/group-chat-tab-COcbheaZ.js +1 -0
  56. package/dist/web/assets/{hack-BKHbsJ7u.js → hack-C_CBVdBc.js} +1 -1
  57. package/dist/web/assets/{haml-C1Ih25Y2.js → haml-CBWfzZpv.js} +1 -1
  58. package/dist/web/assets/{handlebars-CaFitvmC.js → handlebars-4e8OR-VI.js} +1 -1
  59. package/dist/web/assets/{html-BwpKIE6V.js → html-C5X4urn_.js} +1 -1
  60. package/dist/web/assets/{html-derivative-uuTEquZU.js → html-derivative-nH-jXfsL.js} +1 -1
  61. package/dist/web/assets/{http-Cv4Pg5cR.js → http-CQgaG7eu.js} +1 -1
  62. package/dist/web/assets/{hurl-DubkI6TG.js → hurl-B8gidJhu.js} +1 -1
  63. package/dist/web/assets/{hxml-B9OVZFAB.js → hxml-BAK94GX8.js} +1 -1
  64. package/dist/web/assets/{image-preview-DRbZ0FA2.js → image-preview-1kGj4W9R.js} +1 -1
  65. package/dist/web/assets/{index-C_s5DxFQ.js → index-DB-bD6Cx.js} +24 -24
  66. package/dist/web/assets/index-N-pnuwFP.css +2 -0
  67. package/dist/web/assets/info-3K5VOQVL-DI4p3vbH.js +1 -0
  68. package/dist/web/assets/{jinja-BHb1jyl6.js → jinja-BuAjvj8M.js} +1 -1
  69. package/dist/web/assets/{jira-watcher-section-B2-_4QW_.js → jira-watcher-section-BmDvZZ76.js} +1 -1
  70. package/dist/web/assets/{jison-CtpfXDzp.js → jison-Dhhs26-L.js} +1 -1
  71. package/dist/web/assets/{julia-TYjgpazU.js → julia-gZavIyll.js} +1 -1
  72. package/dist/web/assets/{just-D27bzZuW.js → just-DDHrFReO.js} +1 -1
  73. package/dist/web/assets/{keybindings-store-ehg0D6FR.js → keybindings-store-DAMW7K3e.js} +1 -1
  74. package/dist/web/assets/{keyboard-shortcuts-section-DMVcFwLJ.js → keyboard-shortcuts-section-BsZKKzf2.js} +1 -1
  75. package/dist/web/assets/{latex-D_MzopTn.js → latex-BdGZa8ov.js} +1 -1
  76. package/dist/web/assets/{liquid-BG_FG0Pe.js → liquid-urFfd9Fr.js} +1 -1
  77. package/dist/web/assets/{lua-Bl29oC2L.js → lua-CcS6tnB5.js} +1 -1
  78. package/dist/web/assets/{markdown-renderer-pDOFHEG7.js → markdown-renderer-BtrHvth9.js} +3 -3
  79. package/dist/web/assets/{markdown-renderer-CKIBtz-k.js → markdown-renderer-Dy4Vz3VW.js} +1 -1
  80. package/dist/web/assets/{marko-D-HI7dbm.js → marko-CSQqk4oG.js} +1 -1
  81. package/dist/web/assets/{mdc-y444JQTQ.js → mdc-CYIe80m_.js} +1 -1
  82. package/dist/web/assets/{mobile-bottom-sheet-BD5b7KJF.js → mobile-bottom-sheet-B3uDlD79.js} +1 -1
  83. package/dist/web/assets/{mobile-explorer-sheet-DFGPwNp0.js → mobile-explorer-sheet-BL1t1Ptr.js} +1 -1
  84. package/dist/web/assets/{nextflow-C5sKcldC.js → nextflow-C-W8vX8I.js} +1 -1
  85. package/dist/web/assets/{nginx-bXnEC3wm.js → nginx-COGi5you.js} +1 -1
  86. package/dist/web/assets/{nim-pevhf4WD.js → nim-CPitYGel.js} +1 -1
  87. package/dist/web/assets/{notification-store-CwLJtN2t.js → notification-store-DIwuBHMP.js} +1 -1
  88. package/dist/web/assets/{notifications-settings-section-C66s2JId.js → notifications-settings-section-CpnG8Ep4.js} +1 -1
  89. package/dist/web/assets/{number-overlay-editor-B7WINIW4.js → number-overlay-editor-C_eD-Bdr.js} +1 -1
  90. package/dist/web/assets/{overview-panel-mhN0qw6Q.js → overview-panel-Cm2HRtEz.js} +1 -1
  91. package/dist/web/assets/packet-RMMSAZCW-YNQWTi_-.js +1 -0
  92. package/dist/web/assets/{pdf-preview-0AwTBfeC.js → pdf-preview-9Olujr_E.js} +1 -1
  93. package/dist/web/assets/{perl-B1KUtMnW.js → perl-B0yW3hbb.js} +1 -1
  94. package/dist/web/assets/{php-BGmVZBAJ.js → php-BNMYN5Jp.js} +1 -1
  95. package/dist/web/assets/pie-UPGHQEXC-E3Wiw76n.js +1 -0
  96. package/dist/web/assets/{postgres-viewer-hDHYMHmG.js → postgres-viewer-qQtI_Qan.js} +3 -3
  97. package/dist/web/assets/{ppmbot-settings-section-DV6TMOfs.js → ppmbot-settings-section-C_yNqYo1.js} +1 -1
  98. package/dist/web/assets/{process-table-CmvwqGrQ.js → process-table-DH95ASxx.js} +1 -1
  99. package/dist/web/assets/proxy-settings-section-7OpR2hAD.js +1 -0
  100. package/dist/web/assets/{pug-BfN8CpEH.js → pug-CP5fxsxD.js} +1 -1
  101. package/dist/web/assets/{qml-D6fRdLZt.js → qml-CHGpQosY.js} +1 -1
  102. package/dist/web/assets/{query-audit-section-BgXdBaE1.js → query-audit-section-CHncxP-Z.js} +1 -1
  103. package/dist/web/assets/radar-KQ55EAFF-BPQJUKON.js +1 -0
  104. package/dist/web/assets/{razor-fg-9AScR.js → razor-Cfe0AYo4.js} +1 -1
  105. package/dist/web/assets/remote-desktop-mobile-sheet-Db21Gh-Y.js +2 -0
  106. package/dist/web/assets/{remote-desktop-mobile-view-DO5NJufM.js → remote-desktop-mobile-view-CiKtuPVS.js} +1 -1
  107. package/dist/web/assets/{remote-desktop-readiness-gate-CODu8fsP.js → remote-desktop-readiness-gate-BSBIPU4d.js} +1 -1
  108. package/dist/web/assets/{remote-desktop-window-content-DVhp7Y9T.js → remote-desktop-window-content-CJOxXllZ.js} +1 -1
  109. package/dist/web/assets/{rst-BZgx076b.js → rst-DxSSGshb.js} +1 -1
  110. package/dist/web/assets/{ruby-iUkWDcLo.js → ruby-rbK5SsJa.js} +1 -1
  111. package/dist/web/assets/{sas-CLXO0lZ6.js → sas-DDM28fbb.js} +1 -1
  112. package/dist/web/assets/schedules-settings-section-Q5X3kNJ8.js +1 -0
  113. package/dist/web/assets/{scss-DQqteGaG.js → scss-TDl-6ro4.js} +1 -1
  114. package/dist/web/assets/settings-body-5804QGDH.js +2 -0
  115. package/dist/web/assets/settings-store-DWUx3865.js +2 -0
  116. package/dist/web/assets/settings-tab-DgJP4K6b.js +1 -0
  117. package/dist/web/assets/settings-window-content-lyNwahx3.js +1 -0
  118. package/dist/web/assets/{shaderlab-CeMTqagR.js → shaderlab-CCvmDgGS.js} +1 -1
  119. package/dist/web/assets/{shellsession-BAkquZAV.js → shellsession-BzKS9yKh.js} +1 -1
  120. package/dist/web/assets/{soy-Bxm9Ez55.js → soy-QfO35nDh.js} +1 -1
  121. package/dist/web/assets/{sparql-C1phwdLc.js → sparql-D29RDfp2.js} +1 -1
  122. package/dist/web/assets/sql-query-editor-DH3H3gvx.js +1 -0
  123. package/dist/web/assets/{sqlite-viewer-Cy-H-h03.js → sqlite-viewer-DkmaTXae.js} +1 -1
  124. package/dist/web/assets/{stata-DGNMQdEb.js → stata-Be6j_SNv.js} +1 -1
  125. package/dist/web/assets/streaming-store-DDst3zA7.js +1 -0
  126. package/dist/web/assets/{surrealql-ByVrV320.js → surrealql-CykFjgNG.js} +1 -1
  127. package/dist/web/assets/{svelte-CNWjIMhl.js → svelte-CdBF8z4-.js} +1 -1
  128. package/dist/web/assets/system-monitor-body-KuahlPOb.js +2 -0
  129. package/dist/web/assets/system-monitor-tab-BK-nYh25.js +1 -0
  130. package/dist/web/assets/{system-monitor-window-content-5Kkti6yp.js → system-monitor-window-content-C5TkD158.js} +1 -1
  131. package/dist/web/assets/{tab-host-window-content-BnwmQM0I.js → tab-host-window-content-BwDnxvbx.js} +1 -1
  132. package/dist/web/assets/team-member-sheet-Cg82OxYB.js +2 -0
  133. package/dist/web/assets/{team-member-window-content-CHevmy9F.js → team-member-window-content-FxBRzgMW.js} +1 -1
  134. package/dist/web/assets/{templ-Cf0gQL4I.js → templ-BVHE2CNb.js} +1 -1
  135. package/dist/web/assets/{terminal-tab-DVb1AfrI.js → terminal-tab-Bro7kJBK.js} +2 -2
  136. package/dist/web/assets/{tex-BTIqPw_R.js → tex-C8XwrbBw.js} +1 -1
  137. package/dist/web/assets/{tool-cards-DIF_JcFj.js → tool-cards-BDmz33Y9.js} +5 -5
  138. package/dist/web/assets/treemap-KZPCXAKY-C2CvKBQR.js +1 -0
  139. package/dist/web/assets/{ts-tags-B8dN_Yf6.js → ts-tags-BIHk5AM0.js} +1 -1
  140. package/dist/web/assets/{twig-BgemonbJ.js → twig-YcE6Q2Ox.js} +1 -1
  141. package/dist/web/assets/{use-accounts-data--JHaCIoT.js → use-accounts-data-CvfdFWm3.js} +1 -1
  142. package/dist/web/assets/use-monaco-theme-D3Owwbo5.js +1 -0
  143. package/dist/web/assets/{use-remote-desktop-display-choice-DJFX_arw.js → use-remote-desktop-display-choice-DOg4xZ-8.js} +1 -1
  144. package/dist/web/assets/{use-websocket-DufdN3ZA.js → use-websocket-4y-ICdd7.js} +1 -1
  145. package/dist/web/assets/{vendor-mermaid-BKWscKt0.js → vendor-mermaid-CKKtYuTV.js} +1 -1
  146. package/dist/web/assets/{video-preview-DExfNDxI.js → video-preview-C70-MurL.js} +1 -1
  147. package/dist/web/assets/{vue-html-DYEQFAiK.js → vue-html-D1y9feOj.js} +1 -1
  148. package/dist/web/assets/{vue-D3D4lbXz.js → vue-q7m01V0h.js} +1 -1
  149. package/dist/web/assets/{vue-vine-D0OPNscN.js → vue-vine-DrIGs03v.js} +1 -1
  150. package/dist/web/assets/{xml-DHaWgpya.js → xml-oyvc1920.js} +1 -1
  151. package/dist/web/assets/{xsl-DVRN8JsA.js → xsl-BbIGdNPF.js} +1 -1
  152. package/dist/web/index.html +12 -11
  153. package/dist/web/sw.js +1 -1
  154. package/package.json +1 -1
  155. package/src/providers/registry.ts +6 -2
  156. package/src/server/routes/proxy.ts +6 -4
  157. package/src/server/routes/settings.ts +1 -0
  158. package/src/services/config.service.ts +28 -0
  159. package/src/services/db.service.ts +6 -0
  160. package/src/web/app.tsx +8 -0
  161. package/src/web/components/layout/status-bar.tsx +3 -0
  162. package/src/web/components/layout/wake-lock-indicator.tsx +50 -0
  163. package/src/web/components/settings/accounts/account-bucket-row.tsx +4 -4
  164. package/src/web/components/settings/accounts/codex-accounts-section.tsx +2 -8
  165. package/src/web/components/settings/accounts/codex-usage-rows.tsx +26 -0
  166. package/src/web/components/settings/accounts/use-codex-accounts.ts +12 -1
  167. package/src/web/components/settings/general-settings-section.tsx +37 -3
  168. package/src/web/components/settings/proxy-settings-section.tsx +27 -13
  169. package/src/web/components/settings/proxy-test-section.tsx +45 -17
  170. package/src/web/hooks/use-wake-lock.ts +148 -0
  171. package/src/web/lib/proxy-endpoints.ts +39 -0
  172. package/src/web/stores/settings-store.ts +12 -0
  173. package/src/web/stores/wake-lock-store.ts +21 -0
  174. package/dist/web/assets/accounts-settings-section-CmLGNwUl.js +0 -1
  175. package/dist/web/assets/architecture-PBZL5I3N-Ca5IpdzP.js +0 -1
  176. package/dist/web/assets/chat-tab-BYuPaeUJ.js +0 -15
  177. package/dist/web/assets/code-editor-4Lk47HbX.js +0 -7
  178. package/dist/web/assets/general-settings-section-c096J38r.js +0 -1
  179. package/dist/web/assets/gitGraph-HDMCJU4V-BloZfB0Q.js +0 -1
  180. package/dist/web/assets/group-chat-tab-Cano41wo.js +0 -1
  181. package/dist/web/assets/index-nP3uxXvR.css +0 -2
  182. package/dist/web/assets/info-3K5VOQVL-c0W8wp5o.js +0 -1
  183. package/dist/web/assets/packet-RMMSAZCW-D_BoHr_M.js +0 -1
  184. package/dist/web/assets/pie-UPGHQEXC-BaLfuEf8.js +0 -1
  185. package/dist/web/assets/proxy-settings-section-DjtXwOV_.js +0 -1
  186. package/dist/web/assets/radar-KQ55EAFF-DBIZEaIU.js +0 -1
  187. package/dist/web/assets/remote-desktop-mobile-sheet-Cakf7i6s.js +0 -2
  188. package/dist/web/assets/schedules-settings-section-IfwILuXE.js +0 -1
  189. package/dist/web/assets/settings-body-NYJVObzu.js +0 -2
  190. package/dist/web/assets/settings-store-Brjd0QnO.js +0 -2
  191. package/dist/web/assets/settings-tab-CPOI69SL.js +0 -1
  192. package/dist/web/assets/settings-window-content-BuuLt4qg.js +0 -1
  193. package/dist/web/assets/sql-query-editor-BSwL4jf9.js +0 -1
  194. package/dist/web/assets/system-monitor-body-B3jG3f5P.js +0 -2
  195. package/dist/web/assets/system-monitor-tab-Dt4wtPR0.js +0 -1
  196. package/dist/web/assets/team-member-sheet-B4TEEtVT.js +0 -2
  197. package/dist/web/assets/treemap-KZPCXAKY-DFiG9UYW.js +0 -1
  198. package/dist/web/assets/use-monaco-theme-xqDIVJcg.js +0 -1
  199. /package/dist/web/assets/{abap-h3QyH8MW.js → abap-Cq9nYQyd.js} +0 -0
  200. /package/dist/web/assets/{actionscript-3-mkxkq-FN.js → actionscript-3-DL8rUIy0.js} +0 -0
  201. /package/dist/web/assets/{ada-DhISK_EH.js → ada-BY8TLuhY.js} +0 -0
  202. /package/dist/web/assets/{andromeeda-DnlWWesX.js → andromeeda-CyVfHsS0.js} +0 -0
  203. /package/dist/web/assets/{apache-P5AK3sfA.js → apache-DTQUy73x.js} +0 -0
  204. /package/dist/web/assets/{apex-CJUPehg2.js → apex-CiSZngrZ.js} +0 -0
  205. /package/dist/web/assets/{api-settings-CTMdz_VF.js → api-settings-BVfemzZW.js} +0 -0
  206. /package/dist/web/assets/{api-themes-Cknp3Q-P.js → api-themes-BoOJPqwM.js} +0 -0
  207. /package/dist/web/assets/{applescript-Dx6GGbay.js → applescript-CzuRDd3h.js} +0 -0
  208. /package/dist/web/assets/{apply-theme-DxTXOAcV.js → apply-theme-r8tKDrCR.js} +0 -0
  209. /package/dist/web/assets/{ara-95Kx3qKb.js → ara-CSFV93kR.js} +0 -0
  210. /package/dist/web/assets/{asciidoc-Dp0RbIej.js → asciidoc-hOQNnXhz.js} +0 -0
  211. /package/dist/web/assets/{asm-C82coUjU.js → asm-DdG53NGR.js} +0 -0
  212. /package/dist/web/assets/{aurora-x-BFc3zeop.js → aurora-x-DJ7ORZG6.js} +0 -0
  213. /package/dist/web/assets/{awk-ChjC0icr.js → awk-B3FFpX_J.js} +0 -0
  214. /package/dist/web/assets/{ayu-dark-DYfUf_PB.js → ayu-dark-D_P1CfTe.js} +0 -0
  215. /package/dist/web/assets/{ayu-light-Bh6O0plO.js → ayu-light-Cz3YLUqH.js} +0 -0
  216. /package/dist/web/assets/{ayu-mirage-DlNhHTGq.js → ayu-mirage-JcMq5tgJ.js} +0 -0
  217. /package/dist/web/assets/{ballerina-Ceoll3Sk.js → ballerina-7Hs4Rfpk.js} +0 -0
  218. /package/dist/web/assets/{bat-C7QS6Lfq.js → bat-COgQdnFA.js} +0 -0
  219. /package/dist/web/assets/{beancount-5NMEAZgs.js → beancount-BJ3CutBG.js} +0 -0
  220. /package/dist/web/assets/{berry-BBL83Vbk.js → berry-D7so2Cui.js} +0 -0
  221. /package/dist/web/assets/{bibtex-L7rPkPSG.js → bibtex-Ct3acHa1.js} +0 -0
  222. /package/dist/web/assets/{bicep-BOwHIINh.js → bicep-jXDwCQcm.js} +0 -0
  223. /package/dist/web/assets/{bird2-CWLsMom2.js → bird2-CjLD2cna.js} +0 -0
  224. /package/dist/web/assets/{button-BZtEJcUv.js → button-2WCAS8dI.js} +0 -0
  225. /package/dist/web/assets/{c-CD4Ku5Cr.js → c-CdgZojnL.js} +0 -0
  226. /package/dist/web/assets/{c3-CpMl-w3G.js → c3-DtpZYego.js} +0 -0
  227. /package/dist/web/assets/{cadence-CvgF6ehN.js → cadence-CPLkixoh.js} +0 -0
  228. /package/dist/web/assets/{can-open-in-ppm-j3jh7fUo.js → can-open-in-ppm-BntPywsy.js} +0 -0
  229. /package/dist/web/assets/{catppuccin-frappe-eo_dTm3F.js → catppuccin-frappe-Xt0_qJa9.js} +0 -0
  230. /package/dist/web/assets/{catppuccin-latte-DoiMCU_7.js → catppuccin-latte-CJnbLec5.js} +0 -0
  231. /package/dist/web/assets/{catppuccin-macchiato-UQxsK2Vh.js → catppuccin-macchiato-BPHP1wYB.js} +0 -0
  232. /package/dist/web/assets/{catppuccin-mocha-J0i-8RNy.js → catppuccin-mocha-ssWJodGc.js} +0 -0
  233. /package/dist/web/assets/{clarity-DXYM8-SA.js → clarity-DB0408F6.js} +0 -0
  234. /package/dist/web/assets/{clojure-DzamsL69.js → clojure-dpRPlAO4.js} +0 -0
  235. /package/dist/web/assets/{cmake-CR6RP_T_.js → cmake-r2VkeX9y.js} +0 -0
  236. /package/dist/web/assets/{codeowners-D1s6-IyY.js → codeowners-v5nQqHiB.js} +0 -0
  237. /package/dist/web/assets/{codeql-DAqNWMkS.js → codeql-BSSEhKRR.js} +0 -0
  238. /package/dist/web/assets/{common-lisp-8e-KtitB.js → common-lisp-BXb2MMMA.js} +0 -0
  239. /package/dist/web/assets/{coq-UEq0WUcO.js → coq-BjBNi73X.js} +0 -0
  240. /package/dist/web/assets/{csharp-wxJ0TuCm.js → csharp-CdPjZRbV.js} +0 -0
  241. /package/dist/web/assets/{css-Cerub-yB.js → css-BuxbQOHL.js} +0 -0
  242. /package/dist/web/assets/{csv-Bh9_WD_h.js → csv-Dj-eoZwH.js} +0 -0
  243. /package/dist/web/assets/{csv-parser-BPIDt6ni.js → csv-parser-CBbALsFU.js} +0 -0
  244. /package/dist/web/assets/{cue-rzM1ztqU.js → cue-Dz73VksN.js} +0 -0
  245. /package/dist/web/assets/{cypher-DGaTQ8m0.js → cypher-CkVkDywZ.js} +0 -0
  246. /package/dist/web/assets/{d-DbkZGuhB.js → d-oU51Pbpf.js} +0 -0
  247. /package/dist/web/assets/{dark-plus-BO2bzZcA.js → dark-plus-DcwvjjfO.js} +0 -0
  248. /package/dist/web/assets/{dart-BDhCoqVg.js → dart-DGvu8mcX.js} +0 -0
  249. /package/dist/web/assets/{data-grid-types-CdAg-4W1.js → data-grid-types-B6kUrF-M.js} +0 -0
  250. /package/dist/web/assets/{dax-Bh03stWh.js → dax-BmbjKQ90.js} +0 -0
  251. /package/dist/web/assets/{desktop-BOdr_fwq.js → desktop-IRBSiFfh.js} +0 -0
  252. /package/dist/web/assets/{diff-Bb_gTsS2.js → diff-Bdik2JR8.js} +0 -0
  253. /package/dist/web/assets/{dist-DonmFWG8.js → dist-Bv4zQpS1.js} +0 -0
  254. /package/dist/web/assets/{dist-BUMDu0av.js → dist-C8YPBIOb.js} +0 -0
  255. /package/dist/web/assets/{docker-BDsTF5ce.js → docker-Bgdl0H8I.js} +0 -0
  256. /package/dist/web/assets/{docx-preview-CWIDVNZn.js → docx-preview-Bgw838ry.js} +0 -0
  257. /package/dist/web/assets/{dotenv-CbCWp9Ti.js → dotenv-COe5NdnA.js} +0 -0
  258. /package/dist/web/assets/{dracula-Cd1fxvoX.js → dracula-DjURaSAa.js} +0 -0
  259. /package/dist/web/assets/{dracula-soft-B7eXkfXG.js → dracula-soft-Do7d0bo-.js} +0 -0
  260. /package/dist/web/assets/{dream-maker-XlzuS21R.js → dream-maker-DYwQvJIj.js} +0 -0
  261. /package/dist/web/assets/{emacs-lisp-CXV1Ki_7.js → emacs-lisp-BXjlHyDW.js} +0 -0
  262. /package/dist/web/assets/{everforest-dark-DuqR60Dg.js → everforest-dark-h8Q2loiX.js} +0 -0
  263. /package/dist/web/assets/{everforest-light-q4BPnenD.js → everforest-light-CdsJiL-9.js} +0 -0
  264. /package/dist/web/assets/{fennel-B-e0TX2Q.js → fennel-D0CBtOvY.js} +0 -0
  265. /package/dist/web/assets/{fish-Bzb6-TtF.js → fish-DzayfrMj.js} +0 -0
  266. /package/dist/web/assets/{fluent-B-szH2-f.js → fluent-CatjkUfx.js} +0 -0
  267. /package/dist/web/assets/{format-bytes-CKXk9k2d.js → format-bytes-BulRSULX.js} +0 -0
  268. /package/dist/web/assets/{fortran-free-form-OS6SGYC0.js → fortran-free-form-DM04ud0b.js} +0 -0
  269. /package/dist/web/assets/{gdscript-FYq4OP2d.js → gdscript-BLN5iZwf.js} +0 -0
  270. /package/dist/web/assets/{gdshader-BpG6P8rw.js → gdshader-BK-1iZQs.js} +0 -0
  271. /package/dist/web/assets/{genie-BS9RLAna.js → genie-BGPOFWDN.js} +0 -0
  272. /package/dist/web/assets/{gherkin-B_9FdtGs.js → gherkin-CdVOJ_JY.js} +0 -0
  273. /package/dist/web/assets/{github-dark-cfaIlnBV.js → github-dark-B_xW8TaY.js} +0 -0
  274. /package/dist/web/assets/{github-dark-default-B2Wv65He.js → github-dark-default-h_iKq7CX.js} +0 -0
  275. /package/dist/web/assets/{github-dark-dimmed-CtM9X76s.js → github-dark-dimmed-nKDYE62T.js} +0 -0
  276. /package/dist/web/assets/{github-dark-high-contrast-DLHyk0tG.js → github-dark-high-contrast-l8I771QT.js} +0 -0
  277. /package/dist/web/assets/{github-light-DWEI10iG.js → github-light-DNhjkg8Z.js} +0 -0
  278. /package/dist/web/assets/{github-light-default-DcJkK1YN.js → github-light-default-DQ06uS3g.js} +0 -0
  279. /package/dist/web/assets/{github-light-high-contrast-Bcx9iKDt.js → github-light-high-contrast-qc2sZCVN.js} +0 -0
  280. /package/dist/web/assets/{gleam-DVpiM6b2.js → gleam-DPPatkNH.js} +0 -0
  281. /package/dist/web/assets/{gn-B80DNc0i.js → gn-BnzGQTy5.js} +0 -0
  282. /package/dist/web/assets/{gnuplot-D9i3MaT-.js → gnuplot-Ct1leoo3.js} +0 -0
  283. /package/dist/web/assets/{go-CwCBf_Pt.js → go-qysCdbrn.js} +0 -0
  284. /package/dist/web/assets/{groovy-D7mEfwmW.js → groovy-BkWIdrRQ.js} +0 -0
  285. /package/dist/web/assets/{gruvbox-dark-hard-C4R4MOoH.js → gruvbox-dark-hard-L6Iiybbl.js} +0 -0
  286. /package/dist/web/assets/{gruvbox-dark-medium-CZnFC0s8.js → gruvbox-dark-medium-DbD3yl0b.js} +0 -0
  287. /package/dist/web/assets/{gruvbox-dark-soft-DFcJlEBl.js → gruvbox-dark-soft-Ban2cHK3.js} +0 -0
  288. /package/dist/web/assets/{gruvbox-light-hard-B6IF_1L-.js → gruvbox-light-hard-CK_SjS3e.js} +0 -0
  289. /package/dist/web/assets/{gruvbox-light-medium-C19AZJv2.js → gruvbox-light-medium-Bjgvhc2w.js} +0 -0
  290. /package/dist/web/assets/{gruvbox-light-soft-BAnpDm9B.js → gruvbox-light-soft-EWnyYGUu.js} +0 -0
  291. /package/dist/web/assets/{haskell-CsXSYXRG.js → haskell-rT1N9nYr.js} +0 -0
  292. /package/dist/web/assets/{haxe-B1uyiI9t.js → haxe-Bbc91axo.js} +0 -0
  293. /package/dist/web/assets/{hcl-DlYKn5q9.js → hcl-D-3qJA4v.js} +0 -0
  294. /package/dist/web/assets/{hjson-C_0VMGJJ.js → hjson-DWtewcyQ.js} +0 -0
  295. /package/dist/web/assets/{hlsl-zt2PEzbg.js → hlsl-C7t6hCrO.js} +0 -0
  296. /package/dist/web/assets/{horizon-bright-CqI2qTim.js → horizon-bright-CRNyrJy8.js} +0 -0
  297. /package/dist/web/assets/{horizon-6wQfyOK0.js → horizon-zJAGUQ3j.js} +0 -0
  298. /package/dist/web/assets/{houston-BljpHDoG.js → houston-BFKa4W1-.js} +0 -0
  299. /package/dist/web/assets/{hy-XzuL55dw.js → hy-W1hNjMBM.js} +0 -0
  300. /package/dist/web/assets/{image-gallery-Cj8nd4xW.js → image-gallery-BycaVWOu.js} +0 -0
  301. /package/dist/web/assets/{imba-CqhhjBrP.js → imba-CPphaV-V.js} +0 -0
  302. /package/dist/web/assets/{ini-CiFDi6cY.js → ini-CayaZ4vW.js} +0 -0
  303. /package/dist/web/assets/{java-OsQgTL5-.js → java-BPAE_9Ej.js} +0 -0
  304. /package/dist/web/assets/{javascript-qWAOScxl.js → javascript-C5SKIVqe.js} +0 -0
  305. /package/dist/web/assets/{json-RiAKsaD1.js → json-C-0EUYmu.js} +0 -0
  306. /package/dist/web/assets/{json5-BeCnS3H2.js → json5-BqVetEZL.js} +0 -0
  307. /package/dist/web/assets/{jsonc-CbTW1Mka.js → jsonc-DnjIzkUB.js} +0 -0
  308. /package/dist/web/assets/{jsonl-BLSi_669.js → jsonl-rbV-3EqO.js} +0 -0
  309. /package/dist/web/assets/{jsonnet-C3xAggou.js → jsonnet-9hvXw4qr.js} +0 -0
  310. /package/dist/web/assets/{jssm-CLdiagC9.js → jssm-1ifXyIhu.js} +0 -0
  311. /package/dist/web/assets/{jsx-lYE1lb50.js → jsx-hPumywTY.js} +0 -0
  312. /package/dist/web/assets/{kanagawa-dragon-Cd1vcrpD.js → kanagawa-dragon-BCPjmoMO.js} +0 -0
  313. /package/dist/web/assets/{kanagawa-lotus-Dw3QKtk9.js → kanagawa-lotus-DN2VNjy7.js} +0 -0
  314. /package/dist/web/assets/{kanagawa-wave-DIq5Zv5G.js → kanagawa-wave-B8RZEsgc.js} +0 -0
  315. /package/dist/web/assets/{kdl-BfDV0825.js → kdl-CkvjWQIa.js} +0 -0
  316. /package/dist/web/assets/{kotlin-DONxR4wD.js → kotlin-D8cnRi5o.js} +0 -0
  317. /package/dist/web/assets/{kusto-BDP63Fh5.js → kusto-CmeeBEJG.js} +0 -0
  318. /package/dist/web/assets/{laserwave-BeBrWApL.js → laserwave--rtV8Mv9.js} +0 -0
  319. /package/dist/web/assets/{lean-DOZc0N1A.js → lean-CS-Pyi42.js} +0 -0
  320. /package/dist/web/assets/{less-C3H9NlDv.js → less-Ddi_7qGm.js} +0 -0
  321. /package/dist/web/assets/{lib-xrSJ4EZX.js → lib-DIrxSyLb.js} +0 -0
  322. /package/dist/web/assets/{libesm-DLBE59ul.js → libesm-CYLrAeW3.js} +0 -0
  323. /package/dist/web/assets/{light-plus-C_kTL608.js → light-plus-CrEjpkkX.js} +0 -0
  324. /package/dist/web/assets/{llvm-Dsp27U3P.js → llvm-Cm7ZXmAO.js} +0 -0
  325. /package/dist/web/assets/{log-BywQaTCy.js → log-lW2sYxtp.js} +0 -0
  326. /package/dist/web/assets/{logo-BirJgciO.js → logo-B-PiRb53.js} +0 -0
  327. /package/dist/web/assets/{luau-Btrz5kJB.js → luau-8St0pC-R.js} +0 -0
  328. /package/dist/web/assets/{make-Kl7nFQrS.js → make-DbNdhH54.js} +0 -0
  329. /package/dist/web/assets/{markdown-qsC4P8S-.js → markdown-CYocYSGd.js} +0 -0
  330. /package/dist/web/assets/{material-theme-CC__ui3p.js → material-theme-CVBF1Cbi.js} +0 -0
  331. /package/dist/web/assets/{material-theme-darker-D4FxG2FZ.js → material-theme-darker-HFrlNZD8.js} +0 -0
  332. /package/dist/web/assets/{material-theme-lighter-zGqiWcxn.js → material-theme-lighter-BM-uz2ft.js} +0 -0
  333. /package/dist/web/assets/{material-theme-ocean-CZIdTTB1.js → material-theme-ocean-PbvUez8m.js} +0 -0
  334. /package/dist/web/assets/{material-theme-palenight-CEIs0GcK.js → material-theme-palenight-B22Ck6qd.js} +0 -0
  335. /package/dist/web/assets/{matlab-Cf0aUjN9.js → matlab-GFFNzucw.js} +0 -0
  336. /package/dist/web/assets/{mdx-CIsXjH86.js → mdx-BVnJzMDx.js} +0 -0
  337. /package/dist/web/assets/{media-url-VzecHk9g.js → media-url-DBmHJRft.js} +0 -0
  338. /package/dist/web/assets/{mermaid-B06WO9Qc.js → mermaid-BlCmSTCM.js} +0 -0
  339. /package/dist/web/assets/{min-dark-z8fyp0FT.js → min-dark-B0PwlAfC.js} +0 -0
  340. /package/dist/web/assets/{min-light-Dr-qesbW.js → min-light-C_H2ABKu.js} +0 -0
  341. /package/dist/web/assets/{mipsasm-CWHzYLcE.js → mipsasm-C3rf2fo6.js} +0 -0
  342. /package/dist/web/assets/{mojo-D9zXrKmv.js → mojo-CDRuzM3o.js} +0 -0
  343. /package/dist/web/assets/{monokai-4b-AKOpX.js → monokai-KiebNy_Y.js} +0 -0
  344. /package/dist/web/assets/{moonbit-Dl4dhOZJ.js → moonbit-CdVUHoWl.js} +0 -0
  345. /package/dist/web/assets/{move-DTYKJmXy.js → move-Dq9iKZRY.js} +0 -0
  346. /package/dist/web/assets/{narrat-DnvXOS-o.js → narrat-7y5L5sGM.js} +0 -0
  347. /package/dist/web/assets/{nextflow-groovy-Di8QnEXg.js → nextflow-groovy-Cwcbkcrx.js} +0 -0
  348. /package/dist/web/assets/{night-owl-Czh0yq-H.js → night-owl-TBgLPzj4.js} +0 -0
  349. /package/dist/web/assets/{night-owl-light-D_OpZqOR.js → night-owl-light-Dehb9My2.js} +0 -0
  350. /package/dist/web/assets/{nix-2MvcjpK3.js → nix-BKj-gzoX.js} +0 -0
  351. /package/dist/web/assets/{nord-CG_r4cyk.js → nord-BF_r8PeX.js} +0 -0
  352. /package/dist/web/assets/{nushell-DINskMcU.js → nushell-CeAjk9_E.js} +0 -0
  353. /package/dist/web/assets/{objective-c-Dv7BIicR.js → objective-c-Xl1OMcDp.js} +0 -0
  354. /package/dist/web/assets/{objective-cpp-CpqsCxPb.js → objective-cpp-C4ZgzrRq.js} +0 -0
  355. /package/dist/web/assets/{ocaml-DwTsYSmW.js → ocaml-CGj8IYTq.js} +0 -0
  356. /package/dist/web/assets/{odin-G-4O4k4t.js → odin-C4veqvW2.js} +0 -0
  357. /package/dist/web/assets/{one-dark-pro-13Pv5SjI.js → one-dark-pro-gAcWejsV.js} +0 -0
  358. /package/dist/web/assets/{one-light-Bi2e86mS.js → one-light-B7E-UUXy.js} +0 -0
  359. /package/dist/web/assets/{openscad-D0WsOTij.js → openscad-C-wN9BEv.js} +0 -0
  360. /package/dist/web/assets/{pascal-DmDStuXr.js → pascal-C8WBtxMs.js} +0 -0
  361. /package/dist/web/assets/{pkl-Bl6Qjtuo.js → pkl-BBfF4G2A.js} +0 -0
  362. /package/dist/web/assets/{plastic-UeSVSjTI.js → plastic-DFOAb89P.js} +0 -0
  363. /package/dist/web/assets/{plsql-DreFC689.js → plsql-BS2CEMMV.js} +0 -0
  364. /package/dist/web/assets/{po-ZIjccxsX.js → po-BKJDtPmy.js} +0 -0
  365. /package/dist/web/assets/{poimandres-CvQHJPrI.js → poimandres-Cg3hL13e.js} +0 -0
  366. /package/dist/web/assets/{polar-BrMB0Kgh.js → polar-B9ebiXUU.js} +0 -0
  367. /package/dist/web/assets/{postcss-pgUsil1T.js → postcss-B5REwNY_.js} +0 -0
  368. /package/dist/web/assets/{powerquery-CTsZkCg_.js → powerquery-stc0Gzkf.js} +0 -0
  369. /package/dist/web/assets/{powershell-CcwVuBAp.js → powershell-jgd0ahJN.js} +0 -0
  370. /package/dist/web/assets/{prisma-spjnAI5W.js → prisma-CWuZjRhI.js} +0 -0
  371. /package/dist/web/assets/{prolog-ChCkZpDO.js → prolog-D5zNFE63.js} +0 -0
  372. /package/dist/web/assets/{proto-wVGqK4gB.js → proto-B-6RrU7n.js} +0 -0
  373. /package/dist/web/assets/{puppet-CED7iwPQ.js → puppet-DONP8TDR.js} +0 -0
  374. /package/dist/web/assets/{purescript-u9lGiQKV.js → purescript-DDJITf-A.js} +0 -0
  375. /package/dist/web/assets/{python-DeqTx6ef.js → python-bmWy9j1-.js} +0 -0
  376. /package/dist/web/assets/{qmldir-BH1uoPrX.js → qmldir-CKDwMt7X.js} +0 -0
  377. /package/dist/web/assets/{qss-CUVKA_13.js → qss-DptQQzBn.js} +0 -0
  378. /package/dist/web/assets/{r-BqdPzqYH.js → r-BorKpJ8r.js} +0 -0
  379. /package/dist/web/assets/{racket-C2eTgPN3.js → racket-BaHpYVsZ.js} +0 -0
  380. /package/dist/web/assets/{raku-uAay1sWx.js → raku-DFJIV4k_.js} +0 -0
  381. /package/dist/web/assets/{red-DTZP1ZfC.js → red-70oJGrkb.js} +0 -0
  382. /package/dist/web/assets/{reg-Cdk3YsxY.js → reg-C4g235Dv.js} +0 -0
  383. /package/dist/web/assets/{regexp-Bpa2aS7K.js → regexp-Cw1UVmti.js} +0 -0
  384. /package/dist/web/assets/{rel-bNsb1-3L.js → rel-DeLhIz5L.js} +0 -0
  385. /package/dist/web/assets/{resolve-theme-DQk_YcsT.js → resolve-theme-b_yGlUFQ.js} +0 -0
  386. /package/dist/web/assets/{riscv-DSaubByW.js → riscv-ChnTiBRK.js} +0 -0
  387. /package/dist/web/assets/{ron-DbQzYM6i.js → ron-C5IWeqDn.js} +0 -0
  388. /package/dist/web/assets/{rose-pine-C7RsprTu.js → rose-pine-DCR0ohYW.js} +0 -0
  389. /package/dist/web/assets/{rose-pine-dawn-VP976YzL.js → rose-pine-dawn-DvGZs1PR.js} +0 -0
  390. /package/dist/web/assets/{rose-pine-moon-XHZNhOqd.js → rose-pine-moon-BWACHjeS.js} +0 -0
  391. /package/dist/web/assets/{rosmsg-BVQlx0Lj.js → rosmsg-CQlIVazE.js} +0 -0
  392. /package/dist/web/assets/{run-in-terminal-bKRwuO2z.js → run-in-terminal-DHAvC1AG.js} +0 -0
  393. /package/dist/web/assets/{rust-VHaQ3rh3.js → rust-DGGVzWI8.js} +0 -0
  394. /package/dist/web/assets/{sass-CO-kMkwD.js → sass-bj1C0rFI.js} +0 -0
  395. /package/dist/web/assets/{scala-cY0GXkiz.js → scala-MU1tLKDi.js} +0 -0
  396. /package/dist/web/assets/{scheme-D4LNZE0X.js → scheme-CeGXtv7t.js} +0 -0
  397. /package/dist/web/assets/{sdbl-Bh2Fd2cn.js → sdbl-D0HLSGKp.js} +0 -0
  398. /package/dist/web/assets/{send-to-chat-S8LCNX7V.js → send-to-chat-BOyUWNKw.js} +0 -0
  399. /package/dist/web/assets/{separator-DqGg3f9c.js → separator-BzGoTlR7.js} +0 -0
  400. /package/dist/web/assets/{shellscript-KKclmCnt.js → shellscript-DkYiDvh1.js} +0 -0
  401. /package/dist/web/assets/{slack-dark-D6YQ-fqf.js → slack-dark-YqeHiGWH.js} +0 -0
  402. /package/dist/web/assets/{slack-ochin-CDf66CDj.js → slack-ochin-9Oe0DljJ.js} +0 -0
  403. /package/dist/web/assets/{smalltalk-D2OH_QIl.js → smalltalk-CaaxedR7.js} +0 -0
  404. /package/dist/web/assets/{snazzy-light-CQeF8G1K.js → snazzy-light-C8s2FHNC.js} +0 -0
  405. /package/dist/web/assets/{solarized-dark-LTPf1iLZ.js → solarized-dark-0ryY6oN3.js} +0 -0
  406. /package/dist/web/assets/{solarized-light-Ose1n88k.js → solarized-light-bltgZeNh.js} +0 -0
  407. /package/dist/web/assets/{solidity-lFuOMHki.js → solidity-DOf5HmLZ.js} +0 -0
  408. /package/dist/web/assets/{splunk-Bov-sB5S.js → splunk-D1u4WHDW.js} +0 -0
  409. /package/dist/web/assets/{sql-BKyZ6wmk.js → sql-G8uQZljX.js} +0 -0
  410. /package/dist/web/assets/{ssh-config-CqJoMGMb.js → ssh-config-rbXvly7Q.js} +0 -0
  411. /package/dist/web/assets/{stylus-Bf5pWRLI.js → stylus-Cii1iADy.js} +0 -0
  412. /package/dist/web/assets/{swift-D5d1hn_u.js → swift-DpIgonN4.js} +0 -0
  413. /package/dist/web/assets/{synthwave-84-B4c6YAgO.js → synthwave-84-DjGLzU2b.js} +0 -0
  414. /package/dist/web/assets/{system-verilog-D7fXyDsI.js → system-verilog-_Z0M0Hs1.js} +0 -0
  415. /package/dist/web/assets/{systemd-oNagzlBK.js → systemd-BhyDCh9P.js} +0 -0
  416. /package/dist/web/assets/{talonscript-C6Nqm9Dm.js → talonscript-CNchgCRD.js} +0 -0
  417. /package/dist/web/assets/{tasl-CaWy-cBX.js → tasl-m--W7Pyr.js} +0 -0
  418. /package/dist/web/assets/{tcl-C435P5Mq.js → tcl-gY-M_2BC.js} +0 -0
  419. /package/dist/web/assets/{terraform-CVDxqdPf.js → terraform-CB6CzMwo.js} +0 -0
  420. /package/dist/web/assets/{tokyo-night-Uhs17tQ3.js → tokyo-night-COh9oRYi.js} +0 -0
  421. /package/dist/web/assets/{toml-j6fPOJ6P.js → toml-Bg2bsY-v.js} +0 -0
  422. /package/dist/web/assets/{tsv-h78O6xrL.js → tsv-DceGDiJC.js} +0 -0
  423. /package/dist/web/assets/{tsx-Bol-vCrQ.js → tsx-EccDYa7i.js} +0 -0
  424. /package/dist/web/assets/{turtle-Dw8eFf04.js → turtle-C_l2JhvX.js} +0 -0
  425. /package/dist/web/assets/{typescript-Dtz7DPci.js → typescript-C1ytmMcr.js} +0 -0
  426. /package/dist/web/assets/{typespec-BIOQ7dMP.js → typespec-De2ztzG5.js} +0 -0
  427. /package/dist/web/assets/{typst-CoaGMjzu.js → typst-DNcS7gSr.js} +0 -0
  428. /package/dist/web/assets/{use-blob-url-Gfi69PtP.js → use-blob-url-De-ZtcpX.js} +0 -0
  429. /package/dist/web/assets/{use-open-team-member-CruUTqzD.js → use-open-team-member-DWhhWdmJ.js} +0 -0
  430. /package/dist/web/assets/{use-visual-viewport-rnvuooQZ.js → use-visual-viewport-D9O48HQt.js} +0 -0
  431. /package/dist/web/assets/{v-BoqFdpJ7.js → v-DSMUsdMO.js} +0 -0
  432. /package/dist/web/assets/{vala-COBpNnCC.js → vala-BEazLpkO.js} +0 -0
  433. /package/dist/web/assets/{vb-DxI86znh.js → vb-CV9pEJzW.js} +0 -0
  434. /package/dist/web/assets/{vendor-xterm-BaMOj65g.js → vendor-xterm-cuGQmUjN.js} +0 -0
  435. /package/dist/web/assets/{verilog-DcTAamuQ.js → verilog-DhXkLVMk.js} +0 -0
  436. /package/dist/web/assets/{vesper-DO298JSv.js → vesper-n4IltYq-.js} +0 -0
  437. /package/dist/web/assets/{vhdl-Dq-bDVSN.js → vhdl-CePjFbvs.js} +0 -0
  438. /package/dist/web/assets/{viml-zHTRWuQh.js → viml-ChndFsm5.js} +0 -0
  439. /package/dist/web/assets/{vitesse-black-jlYMJCBf.js → vitesse-black-BytVdvhC.js} +0 -0
  440. /package/dist/web/assets/{vitesse-dark-DS0sUlSZ.js → vitesse-dark-83Wech0N.js} +0 -0
  441. /package/dist/web/assets/{vitesse-light-HSeZ2YhG.js → vitesse-light-Xg4wbeMO.js} +0 -0
  442. /package/dist/web/assets/{vyper-BQfKVO3M.js → vyper-eW1NC3FG.js} +0 -0
  443. /package/dist/web/assets/{wasm-B6mCuI8h.js → wasm-Bhucqu1z.js} +0 -0
  444. /package/dist/web/assets/{wasm-B1xp9bLp.js → wasm-BucxKwBZ.js} +0 -0
  445. /package/dist/web/assets/{wenyan-CfpS05sP.js → wenyan-BJFBuXuH.js} +0 -0
  446. /package/dist/web/assets/{wgsl-14GDsWRD.js → wgsl-6z4FUyMK.js} +0 -0
  447. /package/dist/web/assets/{wikitext-Ccbq5EVX.js → wikitext-BoDU6teJ.js} +0 -0
  448. /package/dist/web/assets/{window-pip-registry-BEN0QNSW.js → window-pip-registry-CSLhJfpL.js} +0 -0
  449. /package/dist/web/assets/{wit-C19hb3R5.js → wit-DerMPpgt.js} +0 -0
  450. /package/dist/web/assets/{wolfram-B-ZSwGwP.js → wolfram-D78v0Ap-.js} +0 -0
  451. /package/dist/web/assets/{ws-auth-Dawx17PM.js → ws-auth-ZSZkAT6p.js} +0 -0
  452. /package/dist/web/assets/{yaml-mw_JUeio.js → yaml-C4TIgIw4.js} +0 -0
  453. /package/dist/web/assets/{zenscript-WbzDRjvF.js → zenscript-BydW-dLC.js} +0 -0
  454. /package/dist/web/assets/{zig-F0vvImTJ.js → zig-b9lTqL5E.js} +0 -0
@@ -0,0 +1,50 @@
1
+ /**
2
+ * "Screen awake" indicator — shown only while a wake lock is actually held.
3
+ *
4
+ * Two mounts, because the two viewports have no shared chrome: the status bar is `hidden md:flex`
5
+ * and never renders on the phones and tablets this feature exists for, while a fixed badge would
6
+ * collide with the desktop status bar. Both read the same store, so they can never disagree.
7
+ *
8
+ * The state is reported by the browser, not assumed: `use-wake-lock.ts` only flips the store
9
+ * after a request resolves, so this chip disappearing means the platform really did take the
10
+ * lock back (battery saver, low battery) rather than the setting being off.
11
+ */
12
+
13
+ import { memo } from "react";
14
+ import { Sun } from "lucide-react";
15
+ import { useWakeLockStore } from "@/stores/wake-lock-store";
16
+
17
+ const LABEL = "Screen awake";
18
+ const TITLE = "Screen is being kept on while this turn runs";
19
+
20
+ /** Desktop: a plain entry that inherits the status bar's own type scale. */
21
+ export const WakeLockStatusBarItem = memo(function WakeLockStatusBarItem() {
22
+ const active = useWakeLockStore((s) => s.active);
23
+ if (!active) return null;
24
+
25
+ return (
26
+ <span className="flex items-center gap-1 text-warning shrink-0" title={TITLE}>
27
+ <Sun className="size-3 shrink-0" />
28
+ <span>awake</span>
29
+ </span>
30
+ );
31
+ });
32
+
33
+ /**
34
+ * Mobile: a pill at the top edge. Top-left and top-right are already taken by the device-name
35
+ * badge and the BETA ribbon, so this sits centred between them.
36
+ */
37
+ export const WakeLockMobileBadge = memo(function WakeLockMobileBadge() {
38
+ const active = useWakeLockStore((s) => s.active);
39
+ if (!active) return null;
40
+
41
+ return (
42
+ <div
43
+ className="md:hidden fixed left-1/2 -translate-x-1/2 top-0 z-50 flex items-center gap-1 px-2 py-0.5 rounded-b bg-warning/85 text-white text-[10px] font-medium pointer-events-none"
44
+ title={TITLE}
45
+ >
46
+ <Sun className="size-3 shrink-0" />
47
+ <span>{LABEL}</span>
48
+ </div>
49
+ );
50
+ });
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * The usage bar, and the rate-limit-bucket adapter over it.
3
3
  *
4
- * Two callers with different data: a Claude bucket knows its reset time and window, a Codex
5
- * usage figure is a bare percentage. `AccountUsageBar` is the shared visual so both read the
6
- * same; the bucket adapter adds what only a bucket has. Fabricating a reset time to force
7
- * Codex through the bucket shape would have put invented data on screen.
4
+ * `AccountUsageBar` is the shared visual, so Claude and Codex rows read the same; it takes
5
+ * the reset text already formatted, because a caller may hold a percentage whose bucket is
6
+ * missing and must render the bar without inventing a reset time. `AccountBucketRow` is the
7
+ * adapter for callers that do have a whole bucket, and it drops the row when they do not.
8
8
  */
9
9
 
10
10
  import type { LimitBucket } from "../../../../types/chat";
@@ -10,15 +10,12 @@ import { useState } from "react";
10
10
  import { Download, KeyRound, Loader2, Plus, Settings, Trash2, Upload } from "lucide-react";
11
11
  import { Button } from "@/components/ui/button";
12
12
  import { AccountCardRow, AccountCardShell, AccountsPaneHeader, AccountsPaneMessage } from "./accounts-pane-header";
13
- import { AccountUsageBar } from "./account-bucket-row";
14
13
  import { CodexAddAccountDialog } from "./codex-add-account-dialog";
15
14
  import { CodexBackupDialog } from "./codex-backup-dialog";
16
15
  import { CodexRotationDialog } from "./codex-rotation-dialog";
16
+ import { CodexUsageRows } from "./codex-usage-rows";
17
17
  import { useCodexAccounts } from "./use-codex-accounts";
18
18
 
19
- /** Usage arrives as a 0-1 fraction; the shared bar wants whole percent. */
20
- function toPct(v?: number): number | null { return v != null ? Math.round(v * 100) : null; }
21
-
22
19
  /** Codex multi-account management, separate from Claude accounts because codex auth is owned
23
20
  * by the app-server per CODEX_HOME. Added by API key or ChatGPT device code. */
24
21
  export function CodexAccountsSection() {
@@ -98,10 +95,7 @@ export function CodexAccountsSection() {
98
95
  <Trash2 className="size-4" />
99
96
  </button>
100
97
  </div>
101
- <div className="space-y-2">
102
- <AccountUsageBar label="5-Hour Session" pct={toPct(u.fiveHour)} />
103
- <AccountUsageBar label="Weekly" pct={toPct(u.sevenDay)} />
104
- </div>
98
+ <CodexUsageRows usage={u} />
105
99
  </AccountCardShell>
106
100
  );
107
101
  })}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The two quota rows of a Codex account card.
3
+ *
4
+ * Split out so the wiring is testable on its own: the reset clock is the part that keeps
5
+ * getting dropped, because the percentages render fine without it.
6
+ *
7
+ * Unlike the Claude card's `AccountBucketRow`, a row here stays on screen with an em dash
8
+ * when the quota read failed instead of disappearing — a card that silently loses half its
9
+ * height reads as a broken account rather than as missing data.
10
+ */
11
+
12
+ import { AccountUsageBar } from "./account-bucket-row";
13
+ import { formatResetTime } from "./account-usage-format";
14
+ import type { Usage } from "./use-codex-accounts";
15
+
16
+ /** Usage arrives as a 0-1 fraction; the shared bar wants whole percent. */
17
+ function toPct(v?: number): number | null { return v != null ? Math.round(v * 100) : null; }
18
+
19
+ export function CodexUsageRows({ usage }: { usage: Usage }) {
20
+ return (
21
+ <div className="space-y-2">
22
+ <AccountUsageBar label="5-Hour Session" pct={toPct(usage.fiveHour)} reset={formatResetTime(usage.session)} />
23
+ <AccountUsageBar label="Weekly" pct={toPct(usage.sevenDay)} reset={formatResetTime(usage.weekly)} />
24
+ </div>
25
+ );
26
+ }
@@ -11,11 +11,22 @@
11
11
 
12
12
  import { useCallback, useEffect, useRef, useState } from "react";
13
13
  import { api, getAuthToken } from "@/lib/api-client";
14
+ import type { LimitBucket } from "../../../../types/chat";
14
15
  import type { CodexStrategy } from "./codex-rotation-dialog";
15
16
 
16
17
  export type Strategy = CodexStrategy;
17
18
  export interface CodexAccount { id: string; label: string; type: string; planType?: string | null }
18
- export interface Usage { fiveHour?: number; sevenDay?: number }
19
+ /**
20
+ * One account's quota. The two percentages are what the bars read; the buckets carry the
21
+ * reset clock the server already sends, so the Codex card can show "resets in" the way the
22
+ * Claude card does.
23
+ */
24
+ export interface Usage {
25
+ fiveHour?: number;
26
+ sevenDay?: number;
27
+ session?: LimitBucket;
28
+ weekly?: LimitBucket;
29
+ }
19
30
  interface DevicePending { id: string; userCode: string; verificationUrl: string }
20
31
  type DeviceStatus = { state: "pending" } | { state: "done" } | { state: "error"; error: string };
21
32
 
@@ -6,19 +6,30 @@
6
6
  */
7
7
 
8
8
  import { useCallback, useRef, useState } from "react";
9
- import { Check } from "lucide-react";
9
+ import { Check, Sun } from "lucide-react";
10
10
  import { useShallow } from "zustand/react/shallow";
11
11
  import { Button } from "@/components/ui/button";
12
12
  import { Input } from "@/components/ui/input";
13
13
  import { Label } from "@/components/ui/label";
14
14
  import { Separator } from "@/components/ui/separator";
15
+ import { Switch } from "@/components/ui/switch";
15
16
  import { useSettingsStore } from "@/stores/settings-store";
17
+ import { wakeLockSupport } from "@/hooks/use-wake-lock";
16
18
  import { ChangePasswordSection } from "./change-password-section";
17
19
 
18
20
  export function GeneralSettingsSection() {
19
- const { deviceName, setDeviceName, version } = useSettingsStore(
20
- useShallow((s) => ({ deviceName: s.deviceName, setDeviceName: s.setDeviceName, version: s.version })),
21
+ const { deviceName, setDeviceName, version, keepScreenAwake, setKeepScreenAwake } = useSettingsStore(
22
+ useShallow((s) => ({
23
+ deviceName: s.deviceName,
24
+ setDeviceName: s.setDeviceName,
25
+ version: s.version,
26
+ keepScreenAwake: s.keepScreenAwake,
27
+ setKeepScreenAwake: s.setKeepScreenAwake,
28
+ })),
21
29
  );
30
+ // Computed once per mount: neither the browser nor the origin's secure-context status can
31
+ // change while the pane is open.
32
+ const [support] = useState(wakeLockSupport);
22
33
  const [nameInput, setNameInput] = useState(deviceName ?? "");
23
34
  const [nameSaving, setNameSaving] = useState(false);
24
35
  const [nameSaved, setNameSaved] = useState(false);
@@ -68,6 +79,29 @@ export function GeneralSettingsSection() {
68
79
 
69
80
  <Separator />
70
81
 
82
+ <section className="flex items-center justify-between gap-4">
83
+ <div className="flex items-center gap-3 min-w-0">
84
+ <Sun className="size-4 text-muted-foreground shrink-0" />
85
+ <div className="min-w-0">
86
+ <p className="text-sm font-medium">Keep Screen Awake</p>
87
+ <p className="text-xs text-muted-foreground">
88
+ {support === "insecure"
89
+ ? "Unavailable over plain HTTP — reach PPM through its HTTPS tunnel address to use this."
90
+ : support === "unsupported"
91
+ ? "This browser does not support screen wake locks."
92
+ : "Stop this device dimming while a chat turn is running."}
93
+ </p>
94
+ </div>
95
+ </div>
96
+ <Switch
97
+ checked={keepScreenAwake && support === "ok"}
98
+ disabled={support !== "ok"}
99
+ onCheckedChange={setKeepScreenAwake}
100
+ />
101
+ </section>
102
+
103
+ <Separator />
104
+
71
105
  <ChangePasswordSection />
72
106
 
73
107
  <Separator />
@@ -7,6 +7,7 @@ import { Switch } from "@/components/ui/switch";
7
7
  import { getProxySettings, updateProxySettings, getAISettings, type ProxySettings } from "@/lib/api-settings";
8
8
  import { copyToClipboard } from "@/lib/clipboard";
9
9
  import { ProxyTestButton } from "./proxy-test-section";
10
+ import { proxyEndpoints } from "@/lib/proxy-endpoints";
10
11
 
11
12
  export function ProxySettingsSection() {
12
13
  /** Provider the connection info targets; "" is the unscoped Claude path. */
@@ -70,22 +71,22 @@ export function ProxySettingsSection() {
70
71
  const localEndpoint = settings.localEndpoint;
71
72
  const localBaseUrl = localEndpoint.replace(/\/proxy\/v1\/messages$/, "");
72
73
 
73
- // Both dialects hang off one prefix, so selecting a provider moves them
74
- // together and the card cannot show a mismatched pair.
75
- // default: <root>/proxy → /v1/messages, /v1/chat/completions
76
- // provider: <root>/proxy/codex → same two paths underneath
77
- const prefix = `${hasTunnel ? settings.tunnelUrl : localBaseUrl}/proxy${provider ? `/${provider}` : ""}`;
78
- const anthropicEndpoint = `${prefix}/v1/messages`;
79
- const openAiEndpoint = `${prefix}/v1/chat/completions`;
80
- const anthropicEnv = `ANTHROPIC_BASE_URL=${prefix}\nANTHROPIC_API_KEY=${settings.authKey}`;
81
- const openAiEnv = `OPENAI_BASE_URL=${prefix}/v1\nOPENAI_API_KEY=${settings.authKey}`;
74
+ // Every URL below comes from the shared helper, which the Test dialog also
75
+ // uses that is what keeps the card and the request it fires in agreement.
76
+ const ep = proxyEndpoints(hasTunnel ? settings.tunnelUrl! : localBaseUrl, provider);
77
+ const anthropicEndpoint = ep.anthropicMessages;
78
+ const openAiEndpoint = ep.openAiChatCompletions;
79
+ const anthropicEnv = `ANTHROPIC_BASE_URL=${ep.anthropicBase}\nANTHROPIC_API_KEY=${settings.authKey}`;
80
+ const openAiEnv = `OPENAI_BASE_URL=${ep.openAiBase}\nOPENAI_API_KEY=${settings.authKey}`;
82
81
 
83
82
  return (
84
83
  <div className="space-y-4">
85
84
  <div className="space-y-1.5">
86
85
  <p className="text-[11px] text-muted-foreground">
87
- Expose your Claude accounts as an Anthropic-compatible API endpoint.
88
- External tools (OpenCode, Cursor, etc.) can use your accounts via this proxy.
86
+ Expose your accounts as an API that speaks both the Anthropic and OpenAI
87
+ formats, so most SDKs need only a new base URL. The default path answers
88
+ from your Claude accounts; pick a provider below to run its agent instead,
89
+ which also unlocks image generation.
89
90
  </p>
90
91
  </div>
91
92
 
@@ -94,7 +95,7 @@ export function ProxySettingsSection() {
94
95
  <div className="space-y-0.5">
95
96
  <Label className="text-xs">Enable Proxy</Label>
96
97
  <p className="text-[11px] text-muted-foreground">
97
- Accept API requests on /proxy/v1/messages
98
+ Accept API requests under /proxy
98
99
  </p>
99
100
  </div>
100
101
  <Switch
@@ -153,7 +154,7 @@ export function ProxySettingsSection() {
153
154
  <div className="space-y-2 rounded-md border p-3 bg-muted/30">
154
155
  <div className="flex items-center justify-between">
155
156
  <h4 className="text-[11px] font-medium">Connection Info</h4>
156
- <ProxyTestButton authKey={settings.authKey!} baseUrl={window.location.origin} />
157
+ <ProxyTestButton authKey={settings.authKey!} baseUrl={window.location.origin} provider={provider} />
157
158
  </div>
158
159
 
159
160
  {/* Target provider — the only thing that differs between the two
@@ -217,6 +218,19 @@ export function ProxySettingsSection() {
217
218
  </div>
218
219
  </div>
219
220
 
221
+ {/* Images live only under a provider — the unscoped path has no such route. */}
222
+ {ep.imagesGenerations && ep.imagesEdits && (
223
+ <div className="space-y-1">
224
+ <Label className="text-[10px] text-muted-foreground">Image Endpoints</Label>
225
+ <code className="block text-[10px] font-mono bg-muted px-1.5 py-0.5 rounded truncate">
226
+ {ep.imagesGenerations}
227
+ </code>
228
+ <code className="block text-[10px] font-mono bg-muted px-1.5 py-0.5 rounded truncate">
229
+ {ep.imagesEdits}
230
+ </code>
231
+ </div>
232
+ )}
233
+
220
234
  {!hasTunnel && (
221
235
  <p className="text-[10px] text-muted-foreground">
222
236
  Start a Cloudflare tunnel (Share) to get a public URL.
@@ -4,6 +4,7 @@ import { Button } from "@/components/ui/button";
4
4
  import { Input } from "@/components/ui/input";
5
5
  import { Label } from "@/components/ui/label";
6
6
  import { CLAUDE_MODELS } from "../../../types/claude-models";
7
+ import { proxyEndpoints } from "@/lib/proxy-endpoints";
7
8
  import {
8
9
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogTrigger,
9
10
  } from "@/components/ui/dialog";
@@ -16,6 +17,8 @@ type EndpointFormat = "anthropic" | "openai";
16
17
  interface ProxyTestDialogProps {
17
18
  authKey: string;
18
19
  baseUrl: string;
20
+ /** Provider prefix to test; empty means the unscoped Claude path. */
21
+ provider?: string;
19
22
  }
20
23
 
21
24
  export function ProxyTestButton(props: ProxyTestDialogProps) {
@@ -42,10 +45,12 @@ export function ProxyTestButton(props: ProxyTestDialogProps) {
42
45
  );
43
46
  }
44
47
 
45
- function ProxyTestForm({ authKey, baseUrl }: ProxyTestDialogProps) {
48
+ function ProxyTestForm({ authKey, baseUrl, provider }: ProxyTestDialogProps) {
46
49
  const [format, setFormat] = useState<EndpointFormat>("anthropic");
47
50
  const [message, setMessage] = useState(DEFAULT_MESSAGE);
48
- const [model, setModel] = useState(DEFAULT_MODEL);
51
+ // Only the unscoped path is Claude's. Another provider rejects a Claude model
52
+ // name outright, so the test starts with none and lets that provider choose.
53
+ const [model, setModel] = useState(provider ? "" : DEFAULT_MODEL);
49
54
  const [streaming, setStreaming] = useState(true);
50
55
  const [testing, setTesting] = useState(false);
51
56
  const [output, setOutput] = useState<string | null>(null);
@@ -75,11 +80,18 @@ function ProxyTestForm({ authKey, baseUrl }: ProxyTestDialogProps) {
75
80
  const start = Date.now();
76
81
 
77
82
  const isOpenAi = format === "openai";
78
- const endpoint = isOpenAi
79
- ? `${baseUrl}/proxy/v1/chat/completions`
80
- : `${baseUrl}/proxy/v1/messages`;
83
+ // Same helper the Connection Info card uses. Testing the unscoped path while
84
+ // the card showed a provider was exactly the bug: the answer came back from
85
+ // Claude and looked like the proxy returning the wrong thing.
86
+ const ep = proxyEndpoints(baseUrl, provider);
87
+ const endpoint = isOpenAi ? ep.openAiChatCompletions : ep.anthropicMessages;
81
88
 
82
- const body = JSON.stringify({ model, max_tokens: 256, stream: streaming, messages: [{ role: "user", content: message }] });
89
+ const body = JSON.stringify({
90
+ ...(model ? { model } : {}),
91
+ max_tokens: 256,
92
+ stream: streaming,
93
+ messages: [{ role: "user", content: message }],
94
+ });
83
95
 
84
96
  const headers: Record<string, string> = { "Content-Type": "application/json" };
85
97
  if (isOpenAi) {
@@ -147,23 +159,39 @@ function ProxyTestForm({ authKey, baseUrl }: ProxyTestDialogProps) {
147
159
  </button>
148
160
  ))}
149
161
  </div>
150
- <p className="text-[9px] text-muted-foreground">
162
+ <p className="text-[9px] text-muted-foreground break-all">
151
163
  {format === "anthropic" ? "x-api-key header" : "Authorization: Bearer header"}
164
+ {" · "}
165
+ <code>{`/proxy${provider ? `/${provider}` : ""}/v1/${format === "anthropic" ? "messages" : "chat/completions"}`}</code>
152
166
  </p>
153
167
  </div>
154
168
 
155
- {/* Model */}
169
+ {/* Model — the Claude list only applies to the unscoped path. */}
156
170
  <div className="space-y-1.5">
157
171
  <Label className="text-[11px]">Model</Label>
158
- <select
159
- value={model}
160
- onChange={(e) => setModel(e.target.value)}
161
- className="h-8 w-full rounded-md border bg-background px-2 text-[11px]"
162
- >
163
- {CLAUDE_MODELS.map((m) => (
164
- <option key={m.value} value={m.value}>{m.value}</option>
165
- ))}
166
- </select>
172
+ {provider ? (
173
+ <>
174
+ <Input
175
+ value={model}
176
+ onChange={(e) => setModel(e.target.value)}
177
+ placeholder="leave empty to let the provider choose"
178
+ className="h-8 text-[11px] font-mono"
179
+ />
180
+ <p className="text-[9px] text-muted-foreground">
181
+ Names come from <code>GET /proxy/{provider}/v1/models</code>.
182
+ </p>
183
+ </>
184
+ ) : (
185
+ <select
186
+ value={model}
187
+ onChange={(e) => setModel(e.target.value)}
188
+ className="h-8 w-full rounded-md border bg-background px-2 text-[11px]"
189
+ >
190
+ {CLAUDE_MODELS.map((m) => (
191
+ <option key={m.value} value={m.value}>{m.value}</option>
192
+ ))}
193
+ </select>
194
+ )}
167
195
  </div>
168
196
 
169
197
  {/* Streaming toggle */}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Keeps the device screen lit while a chat turn is in flight.
3
+ *
4
+ * The whole point is a tablet or phone propped up next to you: a long turn produces no touch
5
+ * input, so the OS dims and locks the screen mid-answer and you lose the thread. The browser's
6
+ * Screen Wake Lock API asks the OS not to do that, and this hook holds the lock exactly for as
7
+ * long as something is running.
8
+ *
9
+ * Scoped to the *device*, not the project. Favicon and title are per-project because a window
10
+ * shows one project, but there is one screen — scoping the lock to the active project would
11
+ * dim the display while another project's turn is still running.
12
+ *
13
+ * "Running" is `phase !== "idle"`, which is what `streaming-store` records. That deliberately
14
+ * includes the wait on an approval or an AskUserQuestion card: the server leaves the phase at
15
+ * `thinking` while the SDK blocks on the answer, and a screen that dies right as the agent asks
16
+ * you something is the worst moment to lose it.
17
+ */
18
+
19
+ import { useEffect } from "react";
20
+ import { useStreamingStore } from "@/stores/streaming-store";
21
+ import { useSettingsStore } from "@/stores/settings-store";
22
+ import { useWakeLockStore } from "@/stores/wake-lock-store";
23
+
24
+ /** The slice of `WakeLockSentinel` this code touches. Declared structurally so the file does
25
+ * not depend on the DOM lib shipping the type. */
26
+ export interface WakeLockSentinelLike {
27
+ release: () => Promise<void>;
28
+ addEventListener: (type: "release", listener: () => void) => void;
29
+ }
30
+
31
+ /** Why the feature is or is not available here — the Settings switch explains itself with this. */
32
+ export type WakeLockSupport = "ok" | "insecure" | "unsupported";
33
+
34
+ /**
35
+ * The API is gated on a secure context, so PPM reached over plain HTTP — the usual
36
+ * `http://192.168.x.x:3211` LAN address — has no `navigator.wakeLock` at all. That is by far the
37
+ * likeliest reason this does nothing on someone's tablet, and it deserves a distinct answer
38
+ * from "your browser is too old".
39
+ */
40
+ export function wakeLockSupport(): WakeLockSupport {
41
+ if (typeof navigator !== "undefined" && "wakeLock" in navigator) return "ok";
42
+ if (typeof window !== "undefined" && window.isSecureContext === false) return "insecure";
43
+ return "unsupported";
44
+ }
45
+
46
+ export interface WakeLockSessionDeps {
47
+ /** Acquire a lock. Rejects when the platform refuses (battery saver, low battery, hidden tab). */
48
+ request: () => Promise<WakeLockSentinelLike>;
49
+ isVisible: () => boolean;
50
+ /** Subscribe to visibility changes; returns an unsubscribe. */
51
+ onVisibilityChange: (listener: () => void) => () => void;
52
+ /** Reports whether a lock is actually held, for the indicator. */
53
+ onActive: (active: boolean) => void;
54
+ }
55
+
56
+ /**
57
+ * Holds a wake lock until the returned teardown runs.
58
+ *
59
+ * The re-acquire on `visibilitychange` is not optional. Browsers release the lock every time the
60
+ * document is hidden — switching tabs, switching apps, a manual screen lock — and never restore
61
+ * it. Without this listener the feature works once and then silently stops for the rest of the
62
+ * session, which is the classic way to get this wrong.
63
+ *
64
+ * A refusal is a normal outcome, not an error: the platform is allowed to say no when the
65
+ * battery is low or a power-saving mode is on. Retrying in a loop would only burn what little
66
+ * battery prompted the refusal, so a failed attempt just waits for the next visibility change.
67
+ */
68
+ export function startWakeLockSession(deps: WakeLockSessionDeps): () => void {
69
+ let sentinel: WakeLockSentinelLike | null = null;
70
+ let stopped = false;
71
+ // `sentinel` is only assigned after the request resolves, so it cannot by itself stop a second
72
+ // attempt started while the first is still in flight — which is exactly what rapid tab
73
+ // flapping produces, and it would leak the lock the second attempt overwrites.
74
+ let acquiring = false;
75
+
76
+ const acquire = async (): Promise<void> => {
77
+ if (stopped || sentinel || acquiring || !deps.isVisible()) return;
78
+ acquiring = true;
79
+ try {
80
+ const next = await deps.request();
81
+ // Teardown may have run while the request was in flight; do not leak the lock.
82
+ if (stopped) {
83
+ void next.release().catch(() => {});
84
+ return;
85
+ }
86
+ sentinel = next;
87
+ next.addEventListener("release", () => {
88
+ // The platform took it back. Drop our handle so a later visibility change can re-acquire.
89
+ if (sentinel === next) sentinel = null;
90
+ if (!stopped) deps.onActive(false);
91
+ });
92
+ deps.onActive(true);
93
+ } catch {
94
+ deps.onActive(false);
95
+ } finally {
96
+ acquiring = false;
97
+ }
98
+ };
99
+
100
+ const unsubscribe = deps.onVisibilityChange(() => {
101
+ if (deps.isVisible()) {
102
+ void acquire();
103
+ return;
104
+ }
105
+ // Hidden: the browser always releases the lock here. Drop our handle now instead of waiting
106
+ // for the `release` event, because the two are separate tasks with no guaranteed order — if
107
+ // `visibilitychange` fires first on the way back, a stale handle would make `acquire` think
108
+ // a lock is still held and skip the re-acquire for the rest of the session.
109
+ sentinel = null;
110
+ deps.onActive(false);
111
+ });
112
+
113
+ void acquire();
114
+
115
+ return () => {
116
+ stopped = true;
117
+ unsubscribe();
118
+ deps.onActive(false);
119
+ const held = sentinel;
120
+ sentinel = null;
121
+ if (held) void held.release().catch(() => {});
122
+ };
123
+ }
124
+
125
+ /** Mount once, app-wide. */
126
+ export function useWakeLock(): void {
127
+ const anyRunning = useStreamingStore((s) => s.sessions.size > 0);
128
+ const enabled = useSettingsStore((s) => s.keepScreenAwake);
129
+
130
+ useEffect(() => {
131
+ if (!enabled || !anyRunning) return;
132
+ if (wakeLockSupport() !== "ok") return;
133
+
134
+ const wakeLock = (navigator as Navigator & {
135
+ wakeLock: { request: (type: "screen") => Promise<WakeLockSentinelLike> };
136
+ }).wakeLock;
137
+
138
+ return startWakeLockSession({
139
+ request: () => wakeLock.request("screen"),
140
+ isVisible: () => document.visibilityState === "visible",
141
+ onVisibilityChange: (listener) => {
142
+ document.addEventListener("visibilitychange", listener);
143
+ return () => document.removeEventListener("visibilitychange", listener);
144
+ },
145
+ onActive: (active) => useWakeLockStore.getState().setActive(active),
146
+ });
147
+ }, [enabled, anyRunning]);
148
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The one place that knows how a proxy URL is shaped.
3
+ *
4
+ * The Connection Info card and the Test dialog both need these. They used to
5
+ * build them separately, and the Test dialog never learned about provider
6
+ * prefixes — so picking a provider showed one set of URLs while Test quietly
7
+ * called another, and the answer came back from the wrong engine.
8
+ */
9
+
10
+ /** `<root>/proxy` for the default Claude path, `<root>/proxy/<provider>` otherwise. */
11
+ export function proxyPrefix(root: string, provider?: string): string {
12
+ return `${root}/proxy${provider ? `/${provider}` : ""}`;
13
+ }
14
+
15
+ export interface ProxyEndpoints {
16
+ /** Anthropic SDK base — the SDK appends `/v1/messages` itself. */
17
+ anthropicBase: string;
18
+ /** OpenAI SDK base — the SDK appends `/chat/completions` itself. */
19
+ openAiBase: string;
20
+ anthropicMessages: string;
21
+ openAiChatCompletions: string;
22
+ models: string;
23
+ /** Images live only under a provider; the default path has no such route. */
24
+ imagesGenerations: string | null;
25
+ imagesEdits: string | null;
26
+ }
27
+
28
+ export function proxyEndpoints(root: string, provider?: string): ProxyEndpoints {
29
+ const prefix = proxyPrefix(root, provider);
30
+ return {
31
+ anthropicBase: prefix,
32
+ openAiBase: `${prefix}/v1`,
33
+ anthropicMessages: `${prefix}/v1/messages`,
34
+ openAiChatCompletions: `${prefix}/v1/chat/completions`,
35
+ models: `${prefix}/v1/models`,
36
+ imagesGenerations: provider ? `${prefix}/v1/images/generations` : null,
37
+ imagesEdits: provider ? `${prefix}/v1/images/edits` : null,
38
+ };
39
+ }
@@ -47,6 +47,9 @@ interface SettingsState {
47
47
  /** User ticked "don't show again" on the remote-desktop warning that precedes every open
48
48
  * (`remote-desktop-warning-gate.tsx`); once true the viewer connects straight away. */
49
49
  remoteDesktopWarningDismissed: boolean;
50
+ /** Hold a screen wake lock while any chat turn is running, so a propped-up tablet does not
51
+ * dim mid-answer. Defaults on; see `hooks/use-wake-lock.ts`. */
52
+ keepScreenAwake: boolean;
50
53
  deviceName: string | null;
51
54
  version: string | null;
52
55
  tunnelActive: boolean;
@@ -73,6 +76,7 @@ interface SettingsState {
73
76
  setExplorerSkin: (pref: ExplorerSkinPref) => void;
74
77
  toggleRemoteDesktopStatsVisible: () => void;
75
78
  setRemoteDesktopWarningDismissed: (dismissed: boolean) => void;
79
+ setKeepScreenAwake: (enabled: boolean) => void;
76
80
  fetchServerInfo: () => Promise<void>;
77
81
  /** Re-push the in-memory theme selection to the server (see the action for why). */
78
82
  syncThemeToServer: () => Promise<void>;
@@ -98,6 +102,7 @@ interface PersistedSettings {
98
102
  explorerSkin?: ExplorerSkinPref;
99
103
  remoteDesktopStatsVisible?: boolean;
100
104
  remoteDesktopWarningDismissed?: boolean;
105
+ keepScreenAwake?: boolean;
101
106
  }
102
107
 
103
108
  const VALID_STYLES: PpmThemeStyle[] = ["aurora", "slate", "precision", "custom"];
@@ -252,6 +257,7 @@ function applyServerUiPrefs(data: Record<string, unknown>) {
252
257
  }
253
258
  if (typeof data.remoteDesktopStatsVisible === "boolean") patch.remoteDesktopStatsVisible = data.remoteDesktopStatsVisible;
254
259
  if (typeof data.remoteDesktopWarningDismissed === "boolean") patch.remoteDesktopWarningDismissed = data.remoteDesktopWarningDismissed;
260
+ if (typeof data.keepScreenAwake === "boolean") patch.keepScreenAwake = data.keepScreenAwake;
255
261
  const dbExpanded = sanitizeDbExpanded(data.dbSidebarExpanded);
256
262
  if (dbExpanded) patch.dbSidebarExpanded = dbExpanded;
257
263
  if (Object.keys(patch).length === 0) return;
@@ -281,6 +287,7 @@ export const useSettingsStore = create<SettingsState>((set, get) => ({
281
287
  explorerSkin: (_initial.explorerSkin === "windows" || _initial.explorerSkin === "macos") ? _initial.explorerSkin : "auto",
282
288
  remoteDesktopStatsVisible: _initial.remoteDesktopStatsVisible ?? false,
283
289
  remoteDesktopWarningDismissed: _initial.remoteDesktopWarningDismissed ?? false,
290
+ keepScreenAwake: _initial.keepScreenAwake ?? true,
284
291
  deviceName: null,
285
292
  version: null,
286
293
  tunnelActive: false,
@@ -405,6 +412,11 @@ export const useSettingsStore = create<SettingsState>((set, get) => ({
405
412
  set({ remoteDesktopWarningDismissed: dismissed });
406
413
  },
407
414
 
415
+ setKeepScreenAwake: (enabled) => {
416
+ persistUiPref({ keepScreenAwake: enabled });
417
+ set({ keepScreenAwake: enabled });
418
+ },
419
+
408
420
  setEditorTabStyle: (style) => {
409
421
  persistUiPref({ editorTabStyle: style });
410
422
  set({ editorTabStyle: style });