@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.
- package/CHANGELOG.md +14 -0
- package/CLAUDE.md +15 -0
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/http-api.md +1 -1
- package/dist/web/assets/accounts-settings-section-D65EHybd.js +1 -0
- package/dist/web/assets/{ai-resource-editor-TVV8rOsT.js → ai-resource-editor-DmOGQ_1E.js} +1 -1
- package/dist/web/assets/{ai-settings-section-CutZAI-J.js → ai-settings-section-DP53HaV9.js} +1 -1
- package/dist/web/assets/{ai-settings-section-Whh5k2zL.js → ai-settings-section-Dlv_XYy3.js} +1 -1
- package/dist/web/assets/{angular-html-BuHNQIbQ.js → angular-html-C8nsn2VC.js} +1 -1
- package/dist/web/assets/{angular-ts-DHRWoLc-.js → angular-ts-Caw9nRCH.js} +1 -1
- package/dist/web/assets/{apl-C1VSWVei.js → apl-Dhu1LORF.js} +1 -1
- package/dist/web/assets/{appearance-settings-section-DbkXixUe.js → appearance-settings-section-WuJwZW7v.js} +1 -1
- package/dist/web/assets/architecture-PBZL5I3N-BZBxtErN.js +1 -0
- package/dist/web/assets/{astro-RX-rChsZ.js → astro-DwkX9sLZ.js} +1 -1
- package/dist/web/assets/{audio-preview-CCd1jdje.js → audio-preview-CkGZO8Uy.js} +1 -1
- package/dist/web/assets/{blade-CZ6bxMbK.js → blade-D1fC9Osx.js} +1 -1
- package/dist/web/assets/{bsl-BhgCXLWk.js → bsl-pur-PRip.js} +1 -1
- package/dist/web/assets/{cairo-BrwygPkn.js → cairo-DDJs9amR.js} +1 -1
- package/dist/web/assets/chat-tab-B3tKoaUT.js +15 -0
- package/dist/web/assets/{cobol-C5TGW1Ir.js → cobol-Bo0usdoM.js} +1 -1
- package/dist/web/assets/code-editor-8BjOSWul.js +7 -0
- package/dist/web/assets/{coffee-CFgKlmgI.js → coffee-DBBsbX1e.js} +1 -1
- package/dist/web/assets/{conflict-editor-B-HnPZX7.js → conflict-editor-D2JPf7dR.js} +1 -1
- package/dist/web/assets/{cpp-BhG5q3-d.js → cpp-6CTO78A-.js} +1 -1
- package/dist/web/assets/{crystal-DvuI7_tY.js → crystal-DAlvpAP7.js} +1 -1
- package/dist/web/assets/{csv-preview-CMIxkng3.js → csv-preview-DfHSVE7o.js} +1 -1
- package/dist/web/assets/{data-grid-overlay-editor-DP1xkog4.js → data-grid-overlay-editor-iRrpAV0e.js} +1 -1
- package/dist/web/assets/{database-viewer-CM6O4tar.js → database-viewer-BwSf-V1L.js} +1 -1
- package/dist/web/assets/{diff-viewer-nL4cAp1u.js → diff-viewer-CQU6j7uQ.js} +1 -1
- package/dist/web/assets/{edge-BSIEsmlI.js → edge-D0tZrpC7.js} +1 -1
- package/dist/web/assets/{edit-diff-preview-DeHb85DN.js → edit-diff-preview-DUgmjNre.js} +1 -1
- package/dist/web/assets/{elixir-BF-lrGXM.js → elixir-C1E6-o4G.js} +1 -1
- package/dist/web/assets/{elm-8mCsJOeN.js → elm-BKyTfeQX.js} +1 -1
- package/dist/web/assets/{erb-Dw5PUVKa.js → erb-Cdnr4BMI.js} +1 -1
- package/dist/web/assets/{erlang-BvjBIA6O.js → erlang-N1237mFq.js} +1 -1
- package/dist/web/assets/{esm-Bt9OwSnU.js → esm-ClNnmD9t.js} +1 -1
- package/dist/web/assets/{explorer-body-CuLBY282.js → explorer-body-B2FmdPAx.js} +2 -2
- package/dist/web/assets/{explorer-window-content-Cr8HYEIZ.js → explorer-window-content-CtSMepys.js} +1 -1
- package/dist/web/assets/{extension-manager-section-D_E1LteV.js → extension-manager-section-CBRXxG8W.js} +1 -1
- package/dist/web/assets/{extension-webview-BKVWrl6R.js → extension-webview-yfMof39w.js} +1 -1
- package/dist/web/assets/{files-settings-section-DzuWb19a.js → files-settings-section-Dxn0H4jj.js} +1 -1
- package/dist/web/assets/{fortran-fixed-form-CRjUJe9K.js → fortran-fixed-form-D_f9tVv0.js} +1 -1
- package/dist/web/assets/{fsharp-CjUIHIHp.js → fsharp-DEJmdhc2.js} +1 -1
- package/dist/web/assets/{gdresource-x_NUQFrZ.js → gdresource-Dmmrx2gP.js} +1 -1
- package/dist/web/assets/general-settings-section-C3ccyyOe.js +1 -0
- package/dist/web/assets/{git-commit-BOpxSbns.js → git-commit-qwJ867ig.js} +1 -1
- package/dist/web/assets/{git-log-panel-DRLGWrO2.js → git-log-panel-d2XBsNFP.js} +1 -1
- package/dist/web/assets/{git-rebase-BW4xlK7k.js → git-rebase-Dkv8Zw86.js} +1 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-BHxJbXfV.js +1 -0
- package/dist/web/assets/{glide-data-grid-CUtOJQyB.js → glide-data-grid-5Un6IKEP.js} +7 -7
- package/dist/web/assets/{glimmer-js-CT9jrmFj.js → glimmer-js-CcrXn8lQ.js} +1 -1
- package/dist/web/assets/{glimmer-ts-CjQT1lxK.js → glimmer-ts-CLab3lU7.js} +1 -1
- package/dist/web/assets/{glsl-DsFJvtg5.js → glsl-DXhkG9dU.js} +1 -1
- package/dist/web/assets/{graphql-Dhlnmkn_.js → graphql-Cuqsx8r3.js} +1 -1
- package/dist/web/assets/group-chat-tab-COcbheaZ.js +1 -0
- package/dist/web/assets/{hack-BKHbsJ7u.js → hack-C_CBVdBc.js} +1 -1
- package/dist/web/assets/{haml-C1Ih25Y2.js → haml-CBWfzZpv.js} +1 -1
- package/dist/web/assets/{handlebars-CaFitvmC.js → handlebars-4e8OR-VI.js} +1 -1
- package/dist/web/assets/{html-BwpKIE6V.js → html-C5X4urn_.js} +1 -1
- package/dist/web/assets/{html-derivative-uuTEquZU.js → html-derivative-nH-jXfsL.js} +1 -1
- package/dist/web/assets/{http-Cv4Pg5cR.js → http-CQgaG7eu.js} +1 -1
- package/dist/web/assets/{hurl-DubkI6TG.js → hurl-B8gidJhu.js} +1 -1
- package/dist/web/assets/{hxml-B9OVZFAB.js → hxml-BAK94GX8.js} +1 -1
- package/dist/web/assets/{image-preview-DRbZ0FA2.js → image-preview-1kGj4W9R.js} +1 -1
- package/dist/web/assets/{index-C_s5DxFQ.js → index-DB-bD6Cx.js} +24 -24
- package/dist/web/assets/index-N-pnuwFP.css +2 -0
- package/dist/web/assets/info-3K5VOQVL-DI4p3vbH.js +1 -0
- package/dist/web/assets/{jinja-BHb1jyl6.js → jinja-BuAjvj8M.js} +1 -1
- package/dist/web/assets/{jira-watcher-section-B2-_4QW_.js → jira-watcher-section-BmDvZZ76.js} +1 -1
- package/dist/web/assets/{jison-CtpfXDzp.js → jison-Dhhs26-L.js} +1 -1
- package/dist/web/assets/{julia-TYjgpazU.js → julia-gZavIyll.js} +1 -1
- package/dist/web/assets/{just-D27bzZuW.js → just-DDHrFReO.js} +1 -1
- package/dist/web/assets/{keybindings-store-ehg0D6FR.js → keybindings-store-DAMW7K3e.js} +1 -1
- package/dist/web/assets/{keyboard-shortcuts-section-DMVcFwLJ.js → keyboard-shortcuts-section-BsZKKzf2.js} +1 -1
- package/dist/web/assets/{latex-D_MzopTn.js → latex-BdGZa8ov.js} +1 -1
- package/dist/web/assets/{liquid-BG_FG0Pe.js → liquid-urFfd9Fr.js} +1 -1
- package/dist/web/assets/{lua-Bl29oC2L.js → lua-CcS6tnB5.js} +1 -1
- package/dist/web/assets/{markdown-renderer-pDOFHEG7.js → markdown-renderer-BtrHvth9.js} +3 -3
- package/dist/web/assets/{markdown-renderer-CKIBtz-k.js → markdown-renderer-Dy4Vz3VW.js} +1 -1
- package/dist/web/assets/{marko-D-HI7dbm.js → marko-CSQqk4oG.js} +1 -1
- package/dist/web/assets/{mdc-y444JQTQ.js → mdc-CYIe80m_.js} +1 -1
- package/dist/web/assets/{mobile-bottom-sheet-BD5b7KJF.js → mobile-bottom-sheet-B3uDlD79.js} +1 -1
- package/dist/web/assets/{mobile-explorer-sheet-DFGPwNp0.js → mobile-explorer-sheet-BL1t1Ptr.js} +1 -1
- package/dist/web/assets/{nextflow-C5sKcldC.js → nextflow-C-W8vX8I.js} +1 -1
- package/dist/web/assets/{nginx-bXnEC3wm.js → nginx-COGi5you.js} +1 -1
- package/dist/web/assets/{nim-pevhf4WD.js → nim-CPitYGel.js} +1 -1
- package/dist/web/assets/{notification-store-CwLJtN2t.js → notification-store-DIwuBHMP.js} +1 -1
- package/dist/web/assets/{notifications-settings-section-C66s2JId.js → notifications-settings-section-CpnG8Ep4.js} +1 -1
- package/dist/web/assets/{number-overlay-editor-B7WINIW4.js → number-overlay-editor-C_eD-Bdr.js} +1 -1
- package/dist/web/assets/{overview-panel-mhN0qw6Q.js → overview-panel-Cm2HRtEz.js} +1 -1
- package/dist/web/assets/packet-RMMSAZCW-YNQWTi_-.js +1 -0
- package/dist/web/assets/{pdf-preview-0AwTBfeC.js → pdf-preview-9Olujr_E.js} +1 -1
- package/dist/web/assets/{perl-B1KUtMnW.js → perl-B0yW3hbb.js} +1 -1
- package/dist/web/assets/{php-BGmVZBAJ.js → php-BNMYN5Jp.js} +1 -1
- package/dist/web/assets/pie-UPGHQEXC-E3Wiw76n.js +1 -0
- package/dist/web/assets/{postgres-viewer-hDHYMHmG.js → postgres-viewer-qQtI_Qan.js} +3 -3
- package/dist/web/assets/{ppmbot-settings-section-DV6TMOfs.js → ppmbot-settings-section-C_yNqYo1.js} +1 -1
- package/dist/web/assets/{process-table-CmvwqGrQ.js → process-table-DH95ASxx.js} +1 -1
- package/dist/web/assets/proxy-settings-section-7OpR2hAD.js +1 -0
- package/dist/web/assets/{pug-BfN8CpEH.js → pug-CP5fxsxD.js} +1 -1
- package/dist/web/assets/{qml-D6fRdLZt.js → qml-CHGpQosY.js} +1 -1
- package/dist/web/assets/{query-audit-section-BgXdBaE1.js → query-audit-section-CHncxP-Z.js} +1 -1
- package/dist/web/assets/radar-KQ55EAFF-BPQJUKON.js +1 -0
- package/dist/web/assets/{razor-fg-9AScR.js → razor-Cfe0AYo4.js} +1 -1
- package/dist/web/assets/remote-desktop-mobile-sheet-Db21Gh-Y.js +2 -0
- package/dist/web/assets/{remote-desktop-mobile-view-DO5NJufM.js → remote-desktop-mobile-view-CiKtuPVS.js} +1 -1
- package/dist/web/assets/{remote-desktop-readiness-gate-CODu8fsP.js → remote-desktop-readiness-gate-BSBIPU4d.js} +1 -1
- package/dist/web/assets/{remote-desktop-window-content-DVhp7Y9T.js → remote-desktop-window-content-CJOxXllZ.js} +1 -1
- package/dist/web/assets/{rst-BZgx076b.js → rst-DxSSGshb.js} +1 -1
- package/dist/web/assets/{ruby-iUkWDcLo.js → ruby-rbK5SsJa.js} +1 -1
- package/dist/web/assets/{sas-CLXO0lZ6.js → sas-DDM28fbb.js} +1 -1
- package/dist/web/assets/schedules-settings-section-Q5X3kNJ8.js +1 -0
- package/dist/web/assets/{scss-DQqteGaG.js → scss-TDl-6ro4.js} +1 -1
- package/dist/web/assets/settings-body-5804QGDH.js +2 -0
- package/dist/web/assets/settings-store-DWUx3865.js +2 -0
- package/dist/web/assets/settings-tab-DgJP4K6b.js +1 -0
- package/dist/web/assets/settings-window-content-lyNwahx3.js +1 -0
- package/dist/web/assets/{shaderlab-CeMTqagR.js → shaderlab-CCvmDgGS.js} +1 -1
- package/dist/web/assets/{shellsession-BAkquZAV.js → shellsession-BzKS9yKh.js} +1 -1
- package/dist/web/assets/{soy-Bxm9Ez55.js → soy-QfO35nDh.js} +1 -1
- package/dist/web/assets/{sparql-C1phwdLc.js → sparql-D29RDfp2.js} +1 -1
- package/dist/web/assets/sql-query-editor-DH3H3gvx.js +1 -0
- package/dist/web/assets/{sqlite-viewer-Cy-H-h03.js → sqlite-viewer-DkmaTXae.js} +1 -1
- package/dist/web/assets/{stata-DGNMQdEb.js → stata-Be6j_SNv.js} +1 -1
- package/dist/web/assets/streaming-store-DDst3zA7.js +1 -0
- package/dist/web/assets/{surrealql-ByVrV320.js → surrealql-CykFjgNG.js} +1 -1
- package/dist/web/assets/{svelte-CNWjIMhl.js → svelte-CdBF8z4-.js} +1 -1
- package/dist/web/assets/system-monitor-body-KuahlPOb.js +2 -0
- package/dist/web/assets/system-monitor-tab-BK-nYh25.js +1 -0
- package/dist/web/assets/{system-monitor-window-content-5Kkti6yp.js → system-monitor-window-content-C5TkD158.js} +1 -1
- package/dist/web/assets/{tab-host-window-content-BnwmQM0I.js → tab-host-window-content-BwDnxvbx.js} +1 -1
- package/dist/web/assets/team-member-sheet-Cg82OxYB.js +2 -0
- package/dist/web/assets/{team-member-window-content-CHevmy9F.js → team-member-window-content-FxBRzgMW.js} +1 -1
- package/dist/web/assets/{templ-Cf0gQL4I.js → templ-BVHE2CNb.js} +1 -1
- package/dist/web/assets/{terminal-tab-DVb1AfrI.js → terminal-tab-Bro7kJBK.js} +2 -2
- package/dist/web/assets/{tex-BTIqPw_R.js → tex-C8XwrbBw.js} +1 -1
- package/dist/web/assets/{tool-cards-DIF_JcFj.js → tool-cards-BDmz33Y9.js} +5 -5
- package/dist/web/assets/treemap-KZPCXAKY-C2CvKBQR.js +1 -0
- package/dist/web/assets/{ts-tags-B8dN_Yf6.js → ts-tags-BIHk5AM0.js} +1 -1
- package/dist/web/assets/{twig-BgemonbJ.js → twig-YcE6Q2Ox.js} +1 -1
- package/dist/web/assets/{use-accounts-data--JHaCIoT.js → use-accounts-data-CvfdFWm3.js} +1 -1
- package/dist/web/assets/use-monaco-theme-D3Owwbo5.js +1 -0
- package/dist/web/assets/{use-remote-desktop-display-choice-DJFX_arw.js → use-remote-desktop-display-choice-DOg4xZ-8.js} +1 -1
- package/dist/web/assets/{use-websocket-DufdN3ZA.js → use-websocket-4y-ICdd7.js} +1 -1
- package/dist/web/assets/{vendor-mermaid-BKWscKt0.js → vendor-mermaid-CKKtYuTV.js} +1 -1
- package/dist/web/assets/{video-preview-DExfNDxI.js → video-preview-C70-MurL.js} +1 -1
- package/dist/web/assets/{vue-html-DYEQFAiK.js → vue-html-D1y9feOj.js} +1 -1
- package/dist/web/assets/{vue-D3D4lbXz.js → vue-q7m01V0h.js} +1 -1
- package/dist/web/assets/{vue-vine-D0OPNscN.js → vue-vine-DrIGs03v.js} +1 -1
- package/dist/web/assets/{xml-DHaWgpya.js → xml-oyvc1920.js} +1 -1
- package/dist/web/assets/{xsl-DVRN8JsA.js → xsl-BbIGdNPF.js} +1 -1
- package/dist/web/index.html +12 -11
- package/dist/web/sw.js +1 -1
- package/package.json +1 -1
- package/src/providers/registry.ts +6 -2
- package/src/server/routes/proxy.ts +6 -4
- package/src/server/routes/settings.ts +1 -0
- package/src/services/config.service.ts +28 -0
- package/src/services/db.service.ts +6 -0
- package/src/web/app.tsx +8 -0
- package/src/web/components/layout/status-bar.tsx +3 -0
- package/src/web/components/layout/wake-lock-indicator.tsx +50 -0
- package/src/web/components/settings/accounts/account-bucket-row.tsx +4 -4
- package/src/web/components/settings/accounts/codex-accounts-section.tsx +2 -8
- package/src/web/components/settings/accounts/codex-usage-rows.tsx +26 -0
- package/src/web/components/settings/accounts/use-codex-accounts.ts +12 -1
- package/src/web/components/settings/general-settings-section.tsx +37 -3
- package/src/web/components/settings/proxy-settings-section.tsx +27 -13
- package/src/web/components/settings/proxy-test-section.tsx +45 -17
- package/src/web/hooks/use-wake-lock.ts +148 -0
- package/src/web/lib/proxy-endpoints.ts +39 -0
- package/src/web/stores/settings-store.ts +12 -0
- package/src/web/stores/wake-lock-store.ts +21 -0
- package/dist/web/assets/accounts-settings-section-CmLGNwUl.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-Ca5IpdzP.js +0 -1
- package/dist/web/assets/chat-tab-BYuPaeUJ.js +0 -15
- package/dist/web/assets/code-editor-4Lk47HbX.js +0 -7
- package/dist/web/assets/general-settings-section-c096J38r.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-BloZfB0Q.js +0 -1
- package/dist/web/assets/group-chat-tab-Cano41wo.js +0 -1
- package/dist/web/assets/index-nP3uxXvR.css +0 -2
- package/dist/web/assets/info-3K5VOQVL-c0W8wp5o.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-D_BoHr_M.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-BaLfuEf8.js +0 -1
- package/dist/web/assets/proxy-settings-section-DjtXwOV_.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-DBIZEaIU.js +0 -1
- package/dist/web/assets/remote-desktop-mobile-sheet-Cakf7i6s.js +0 -2
- package/dist/web/assets/schedules-settings-section-IfwILuXE.js +0 -1
- package/dist/web/assets/settings-body-NYJVObzu.js +0 -2
- package/dist/web/assets/settings-store-Brjd0QnO.js +0 -2
- package/dist/web/assets/settings-tab-CPOI69SL.js +0 -1
- package/dist/web/assets/settings-window-content-BuuLt4qg.js +0 -1
- package/dist/web/assets/sql-query-editor-BSwL4jf9.js +0 -1
- package/dist/web/assets/system-monitor-body-B3jG3f5P.js +0 -2
- package/dist/web/assets/system-monitor-tab-Dt4wtPR0.js +0 -1
- package/dist/web/assets/team-member-sheet-B4TEEtVT.js +0 -2
- package/dist/web/assets/treemap-KZPCXAKY-DFiG9UYW.js +0 -1
- package/dist/web/assets/use-monaco-theme-xqDIVJcg.js +0 -1
- /package/dist/web/assets/{abap-h3QyH8MW.js → abap-Cq9nYQyd.js} +0 -0
- /package/dist/web/assets/{actionscript-3-mkxkq-FN.js → actionscript-3-DL8rUIy0.js} +0 -0
- /package/dist/web/assets/{ada-DhISK_EH.js → ada-BY8TLuhY.js} +0 -0
- /package/dist/web/assets/{andromeeda-DnlWWesX.js → andromeeda-CyVfHsS0.js} +0 -0
- /package/dist/web/assets/{apache-P5AK3sfA.js → apache-DTQUy73x.js} +0 -0
- /package/dist/web/assets/{apex-CJUPehg2.js → apex-CiSZngrZ.js} +0 -0
- /package/dist/web/assets/{api-settings-CTMdz_VF.js → api-settings-BVfemzZW.js} +0 -0
- /package/dist/web/assets/{api-themes-Cknp3Q-P.js → api-themes-BoOJPqwM.js} +0 -0
- /package/dist/web/assets/{applescript-Dx6GGbay.js → applescript-CzuRDd3h.js} +0 -0
- /package/dist/web/assets/{apply-theme-DxTXOAcV.js → apply-theme-r8tKDrCR.js} +0 -0
- /package/dist/web/assets/{ara-95Kx3qKb.js → ara-CSFV93kR.js} +0 -0
- /package/dist/web/assets/{asciidoc-Dp0RbIej.js → asciidoc-hOQNnXhz.js} +0 -0
- /package/dist/web/assets/{asm-C82coUjU.js → asm-DdG53NGR.js} +0 -0
- /package/dist/web/assets/{aurora-x-BFc3zeop.js → aurora-x-DJ7ORZG6.js} +0 -0
- /package/dist/web/assets/{awk-ChjC0icr.js → awk-B3FFpX_J.js} +0 -0
- /package/dist/web/assets/{ayu-dark-DYfUf_PB.js → ayu-dark-D_P1CfTe.js} +0 -0
- /package/dist/web/assets/{ayu-light-Bh6O0plO.js → ayu-light-Cz3YLUqH.js} +0 -0
- /package/dist/web/assets/{ayu-mirage-DlNhHTGq.js → ayu-mirage-JcMq5tgJ.js} +0 -0
- /package/dist/web/assets/{ballerina-Ceoll3Sk.js → ballerina-7Hs4Rfpk.js} +0 -0
- /package/dist/web/assets/{bat-C7QS6Lfq.js → bat-COgQdnFA.js} +0 -0
- /package/dist/web/assets/{beancount-5NMEAZgs.js → beancount-BJ3CutBG.js} +0 -0
- /package/dist/web/assets/{berry-BBL83Vbk.js → berry-D7so2Cui.js} +0 -0
- /package/dist/web/assets/{bibtex-L7rPkPSG.js → bibtex-Ct3acHa1.js} +0 -0
- /package/dist/web/assets/{bicep-BOwHIINh.js → bicep-jXDwCQcm.js} +0 -0
- /package/dist/web/assets/{bird2-CWLsMom2.js → bird2-CjLD2cna.js} +0 -0
- /package/dist/web/assets/{button-BZtEJcUv.js → button-2WCAS8dI.js} +0 -0
- /package/dist/web/assets/{c-CD4Ku5Cr.js → c-CdgZojnL.js} +0 -0
- /package/dist/web/assets/{c3-CpMl-w3G.js → c3-DtpZYego.js} +0 -0
- /package/dist/web/assets/{cadence-CvgF6ehN.js → cadence-CPLkixoh.js} +0 -0
- /package/dist/web/assets/{can-open-in-ppm-j3jh7fUo.js → can-open-in-ppm-BntPywsy.js} +0 -0
- /package/dist/web/assets/{catppuccin-frappe-eo_dTm3F.js → catppuccin-frappe-Xt0_qJa9.js} +0 -0
- /package/dist/web/assets/{catppuccin-latte-DoiMCU_7.js → catppuccin-latte-CJnbLec5.js} +0 -0
- /package/dist/web/assets/{catppuccin-macchiato-UQxsK2Vh.js → catppuccin-macchiato-BPHP1wYB.js} +0 -0
- /package/dist/web/assets/{catppuccin-mocha-J0i-8RNy.js → catppuccin-mocha-ssWJodGc.js} +0 -0
- /package/dist/web/assets/{clarity-DXYM8-SA.js → clarity-DB0408F6.js} +0 -0
- /package/dist/web/assets/{clojure-DzamsL69.js → clojure-dpRPlAO4.js} +0 -0
- /package/dist/web/assets/{cmake-CR6RP_T_.js → cmake-r2VkeX9y.js} +0 -0
- /package/dist/web/assets/{codeowners-D1s6-IyY.js → codeowners-v5nQqHiB.js} +0 -0
- /package/dist/web/assets/{codeql-DAqNWMkS.js → codeql-BSSEhKRR.js} +0 -0
- /package/dist/web/assets/{common-lisp-8e-KtitB.js → common-lisp-BXb2MMMA.js} +0 -0
- /package/dist/web/assets/{coq-UEq0WUcO.js → coq-BjBNi73X.js} +0 -0
- /package/dist/web/assets/{csharp-wxJ0TuCm.js → csharp-CdPjZRbV.js} +0 -0
- /package/dist/web/assets/{css-Cerub-yB.js → css-BuxbQOHL.js} +0 -0
- /package/dist/web/assets/{csv-Bh9_WD_h.js → csv-Dj-eoZwH.js} +0 -0
- /package/dist/web/assets/{csv-parser-BPIDt6ni.js → csv-parser-CBbALsFU.js} +0 -0
- /package/dist/web/assets/{cue-rzM1ztqU.js → cue-Dz73VksN.js} +0 -0
- /package/dist/web/assets/{cypher-DGaTQ8m0.js → cypher-CkVkDywZ.js} +0 -0
- /package/dist/web/assets/{d-DbkZGuhB.js → d-oU51Pbpf.js} +0 -0
- /package/dist/web/assets/{dark-plus-BO2bzZcA.js → dark-plus-DcwvjjfO.js} +0 -0
- /package/dist/web/assets/{dart-BDhCoqVg.js → dart-DGvu8mcX.js} +0 -0
- /package/dist/web/assets/{data-grid-types-CdAg-4W1.js → data-grid-types-B6kUrF-M.js} +0 -0
- /package/dist/web/assets/{dax-Bh03stWh.js → dax-BmbjKQ90.js} +0 -0
- /package/dist/web/assets/{desktop-BOdr_fwq.js → desktop-IRBSiFfh.js} +0 -0
- /package/dist/web/assets/{diff-Bb_gTsS2.js → diff-Bdik2JR8.js} +0 -0
- /package/dist/web/assets/{dist-DonmFWG8.js → dist-Bv4zQpS1.js} +0 -0
- /package/dist/web/assets/{dist-BUMDu0av.js → dist-C8YPBIOb.js} +0 -0
- /package/dist/web/assets/{docker-BDsTF5ce.js → docker-Bgdl0H8I.js} +0 -0
- /package/dist/web/assets/{docx-preview-CWIDVNZn.js → docx-preview-Bgw838ry.js} +0 -0
- /package/dist/web/assets/{dotenv-CbCWp9Ti.js → dotenv-COe5NdnA.js} +0 -0
- /package/dist/web/assets/{dracula-Cd1fxvoX.js → dracula-DjURaSAa.js} +0 -0
- /package/dist/web/assets/{dracula-soft-B7eXkfXG.js → dracula-soft-Do7d0bo-.js} +0 -0
- /package/dist/web/assets/{dream-maker-XlzuS21R.js → dream-maker-DYwQvJIj.js} +0 -0
- /package/dist/web/assets/{emacs-lisp-CXV1Ki_7.js → emacs-lisp-BXjlHyDW.js} +0 -0
- /package/dist/web/assets/{everforest-dark-DuqR60Dg.js → everforest-dark-h8Q2loiX.js} +0 -0
- /package/dist/web/assets/{everforest-light-q4BPnenD.js → everforest-light-CdsJiL-9.js} +0 -0
- /package/dist/web/assets/{fennel-B-e0TX2Q.js → fennel-D0CBtOvY.js} +0 -0
- /package/dist/web/assets/{fish-Bzb6-TtF.js → fish-DzayfrMj.js} +0 -0
- /package/dist/web/assets/{fluent-B-szH2-f.js → fluent-CatjkUfx.js} +0 -0
- /package/dist/web/assets/{format-bytes-CKXk9k2d.js → format-bytes-BulRSULX.js} +0 -0
- /package/dist/web/assets/{fortran-free-form-OS6SGYC0.js → fortran-free-form-DM04ud0b.js} +0 -0
- /package/dist/web/assets/{gdscript-FYq4OP2d.js → gdscript-BLN5iZwf.js} +0 -0
- /package/dist/web/assets/{gdshader-BpG6P8rw.js → gdshader-BK-1iZQs.js} +0 -0
- /package/dist/web/assets/{genie-BS9RLAna.js → genie-BGPOFWDN.js} +0 -0
- /package/dist/web/assets/{gherkin-B_9FdtGs.js → gherkin-CdVOJ_JY.js} +0 -0
- /package/dist/web/assets/{github-dark-cfaIlnBV.js → github-dark-B_xW8TaY.js} +0 -0
- /package/dist/web/assets/{github-dark-default-B2Wv65He.js → github-dark-default-h_iKq7CX.js} +0 -0
- /package/dist/web/assets/{github-dark-dimmed-CtM9X76s.js → github-dark-dimmed-nKDYE62T.js} +0 -0
- /package/dist/web/assets/{github-dark-high-contrast-DLHyk0tG.js → github-dark-high-contrast-l8I771QT.js} +0 -0
- /package/dist/web/assets/{github-light-DWEI10iG.js → github-light-DNhjkg8Z.js} +0 -0
- /package/dist/web/assets/{github-light-default-DcJkK1YN.js → github-light-default-DQ06uS3g.js} +0 -0
- /package/dist/web/assets/{github-light-high-contrast-Bcx9iKDt.js → github-light-high-contrast-qc2sZCVN.js} +0 -0
- /package/dist/web/assets/{gleam-DVpiM6b2.js → gleam-DPPatkNH.js} +0 -0
- /package/dist/web/assets/{gn-B80DNc0i.js → gn-BnzGQTy5.js} +0 -0
- /package/dist/web/assets/{gnuplot-D9i3MaT-.js → gnuplot-Ct1leoo3.js} +0 -0
- /package/dist/web/assets/{go-CwCBf_Pt.js → go-qysCdbrn.js} +0 -0
- /package/dist/web/assets/{groovy-D7mEfwmW.js → groovy-BkWIdrRQ.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-hard-C4R4MOoH.js → gruvbox-dark-hard-L6Iiybbl.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-medium-CZnFC0s8.js → gruvbox-dark-medium-DbD3yl0b.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-soft-DFcJlEBl.js → gruvbox-dark-soft-Ban2cHK3.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-hard-B6IF_1L-.js → gruvbox-light-hard-CK_SjS3e.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-medium-C19AZJv2.js → gruvbox-light-medium-Bjgvhc2w.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-soft-BAnpDm9B.js → gruvbox-light-soft-EWnyYGUu.js} +0 -0
- /package/dist/web/assets/{haskell-CsXSYXRG.js → haskell-rT1N9nYr.js} +0 -0
- /package/dist/web/assets/{haxe-B1uyiI9t.js → haxe-Bbc91axo.js} +0 -0
- /package/dist/web/assets/{hcl-DlYKn5q9.js → hcl-D-3qJA4v.js} +0 -0
- /package/dist/web/assets/{hjson-C_0VMGJJ.js → hjson-DWtewcyQ.js} +0 -0
- /package/dist/web/assets/{hlsl-zt2PEzbg.js → hlsl-C7t6hCrO.js} +0 -0
- /package/dist/web/assets/{horizon-bright-CqI2qTim.js → horizon-bright-CRNyrJy8.js} +0 -0
- /package/dist/web/assets/{horizon-6wQfyOK0.js → horizon-zJAGUQ3j.js} +0 -0
- /package/dist/web/assets/{houston-BljpHDoG.js → houston-BFKa4W1-.js} +0 -0
- /package/dist/web/assets/{hy-XzuL55dw.js → hy-W1hNjMBM.js} +0 -0
- /package/dist/web/assets/{image-gallery-Cj8nd4xW.js → image-gallery-BycaVWOu.js} +0 -0
- /package/dist/web/assets/{imba-CqhhjBrP.js → imba-CPphaV-V.js} +0 -0
- /package/dist/web/assets/{ini-CiFDi6cY.js → ini-CayaZ4vW.js} +0 -0
- /package/dist/web/assets/{java-OsQgTL5-.js → java-BPAE_9Ej.js} +0 -0
- /package/dist/web/assets/{javascript-qWAOScxl.js → javascript-C5SKIVqe.js} +0 -0
- /package/dist/web/assets/{json-RiAKsaD1.js → json-C-0EUYmu.js} +0 -0
- /package/dist/web/assets/{json5-BeCnS3H2.js → json5-BqVetEZL.js} +0 -0
- /package/dist/web/assets/{jsonc-CbTW1Mka.js → jsonc-DnjIzkUB.js} +0 -0
- /package/dist/web/assets/{jsonl-BLSi_669.js → jsonl-rbV-3EqO.js} +0 -0
- /package/dist/web/assets/{jsonnet-C3xAggou.js → jsonnet-9hvXw4qr.js} +0 -0
- /package/dist/web/assets/{jssm-CLdiagC9.js → jssm-1ifXyIhu.js} +0 -0
- /package/dist/web/assets/{jsx-lYE1lb50.js → jsx-hPumywTY.js} +0 -0
- /package/dist/web/assets/{kanagawa-dragon-Cd1vcrpD.js → kanagawa-dragon-BCPjmoMO.js} +0 -0
- /package/dist/web/assets/{kanagawa-lotus-Dw3QKtk9.js → kanagawa-lotus-DN2VNjy7.js} +0 -0
- /package/dist/web/assets/{kanagawa-wave-DIq5Zv5G.js → kanagawa-wave-B8RZEsgc.js} +0 -0
- /package/dist/web/assets/{kdl-BfDV0825.js → kdl-CkvjWQIa.js} +0 -0
- /package/dist/web/assets/{kotlin-DONxR4wD.js → kotlin-D8cnRi5o.js} +0 -0
- /package/dist/web/assets/{kusto-BDP63Fh5.js → kusto-CmeeBEJG.js} +0 -0
- /package/dist/web/assets/{laserwave-BeBrWApL.js → laserwave--rtV8Mv9.js} +0 -0
- /package/dist/web/assets/{lean-DOZc0N1A.js → lean-CS-Pyi42.js} +0 -0
- /package/dist/web/assets/{less-C3H9NlDv.js → less-Ddi_7qGm.js} +0 -0
- /package/dist/web/assets/{lib-xrSJ4EZX.js → lib-DIrxSyLb.js} +0 -0
- /package/dist/web/assets/{libesm-DLBE59ul.js → libesm-CYLrAeW3.js} +0 -0
- /package/dist/web/assets/{light-plus-C_kTL608.js → light-plus-CrEjpkkX.js} +0 -0
- /package/dist/web/assets/{llvm-Dsp27U3P.js → llvm-Cm7ZXmAO.js} +0 -0
- /package/dist/web/assets/{log-BywQaTCy.js → log-lW2sYxtp.js} +0 -0
- /package/dist/web/assets/{logo-BirJgciO.js → logo-B-PiRb53.js} +0 -0
- /package/dist/web/assets/{luau-Btrz5kJB.js → luau-8St0pC-R.js} +0 -0
- /package/dist/web/assets/{make-Kl7nFQrS.js → make-DbNdhH54.js} +0 -0
- /package/dist/web/assets/{markdown-qsC4P8S-.js → markdown-CYocYSGd.js} +0 -0
- /package/dist/web/assets/{material-theme-CC__ui3p.js → material-theme-CVBF1Cbi.js} +0 -0
- /package/dist/web/assets/{material-theme-darker-D4FxG2FZ.js → material-theme-darker-HFrlNZD8.js} +0 -0
- /package/dist/web/assets/{material-theme-lighter-zGqiWcxn.js → material-theme-lighter-BM-uz2ft.js} +0 -0
- /package/dist/web/assets/{material-theme-ocean-CZIdTTB1.js → material-theme-ocean-PbvUez8m.js} +0 -0
- /package/dist/web/assets/{material-theme-palenight-CEIs0GcK.js → material-theme-palenight-B22Ck6qd.js} +0 -0
- /package/dist/web/assets/{matlab-Cf0aUjN9.js → matlab-GFFNzucw.js} +0 -0
- /package/dist/web/assets/{mdx-CIsXjH86.js → mdx-BVnJzMDx.js} +0 -0
- /package/dist/web/assets/{media-url-VzecHk9g.js → media-url-DBmHJRft.js} +0 -0
- /package/dist/web/assets/{mermaid-B06WO9Qc.js → mermaid-BlCmSTCM.js} +0 -0
- /package/dist/web/assets/{min-dark-z8fyp0FT.js → min-dark-B0PwlAfC.js} +0 -0
- /package/dist/web/assets/{min-light-Dr-qesbW.js → min-light-C_H2ABKu.js} +0 -0
- /package/dist/web/assets/{mipsasm-CWHzYLcE.js → mipsasm-C3rf2fo6.js} +0 -0
- /package/dist/web/assets/{mojo-D9zXrKmv.js → mojo-CDRuzM3o.js} +0 -0
- /package/dist/web/assets/{monokai-4b-AKOpX.js → monokai-KiebNy_Y.js} +0 -0
- /package/dist/web/assets/{moonbit-Dl4dhOZJ.js → moonbit-CdVUHoWl.js} +0 -0
- /package/dist/web/assets/{move-DTYKJmXy.js → move-Dq9iKZRY.js} +0 -0
- /package/dist/web/assets/{narrat-DnvXOS-o.js → narrat-7y5L5sGM.js} +0 -0
- /package/dist/web/assets/{nextflow-groovy-Di8QnEXg.js → nextflow-groovy-Cwcbkcrx.js} +0 -0
- /package/dist/web/assets/{night-owl-Czh0yq-H.js → night-owl-TBgLPzj4.js} +0 -0
- /package/dist/web/assets/{night-owl-light-D_OpZqOR.js → night-owl-light-Dehb9My2.js} +0 -0
- /package/dist/web/assets/{nix-2MvcjpK3.js → nix-BKj-gzoX.js} +0 -0
- /package/dist/web/assets/{nord-CG_r4cyk.js → nord-BF_r8PeX.js} +0 -0
- /package/dist/web/assets/{nushell-DINskMcU.js → nushell-CeAjk9_E.js} +0 -0
- /package/dist/web/assets/{objective-c-Dv7BIicR.js → objective-c-Xl1OMcDp.js} +0 -0
- /package/dist/web/assets/{objective-cpp-CpqsCxPb.js → objective-cpp-C4ZgzrRq.js} +0 -0
- /package/dist/web/assets/{ocaml-DwTsYSmW.js → ocaml-CGj8IYTq.js} +0 -0
- /package/dist/web/assets/{odin-G-4O4k4t.js → odin-C4veqvW2.js} +0 -0
- /package/dist/web/assets/{one-dark-pro-13Pv5SjI.js → one-dark-pro-gAcWejsV.js} +0 -0
- /package/dist/web/assets/{one-light-Bi2e86mS.js → one-light-B7E-UUXy.js} +0 -0
- /package/dist/web/assets/{openscad-D0WsOTij.js → openscad-C-wN9BEv.js} +0 -0
- /package/dist/web/assets/{pascal-DmDStuXr.js → pascal-C8WBtxMs.js} +0 -0
- /package/dist/web/assets/{pkl-Bl6Qjtuo.js → pkl-BBfF4G2A.js} +0 -0
- /package/dist/web/assets/{plastic-UeSVSjTI.js → plastic-DFOAb89P.js} +0 -0
- /package/dist/web/assets/{plsql-DreFC689.js → plsql-BS2CEMMV.js} +0 -0
- /package/dist/web/assets/{po-ZIjccxsX.js → po-BKJDtPmy.js} +0 -0
- /package/dist/web/assets/{poimandres-CvQHJPrI.js → poimandres-Cg3hL13e.js} +0 -0
- /package/dist/web/assets/{polar-BrMB0Kgh.js → polar-B9ebiXUU.js} +0 -0
- /package/dist/web/assets/{postcss-pgUsil1T.js → postcss-B5REwNY_.js} +0 -0
- /package/dist/web/assets/{powerquery-CTsZkCg_.js → powerquery-stc0Gzkf.js} +0 -0
- /package/dist/web/assets/{powershell-CcwVuBAp.js → powershell-jgd0ahJN.js} +0 -0
- /package/dist/web/assets/{prisma-spjnAI5W.js → prisma-CWuZjRhI.js} +0 -0
- /package/dist/web/assets/{prolog-ChCkZpDO.js → prolog-D5zNFE63.js} +0 -0
- /package/dist/web/assets/{proto-wVGqK4gB.js → proto-B-6RrU7n.js} +0 -0
- /package/dist/web/assets/{puppet-CED7iwPQ.js → puppet-DONP8TDR.js} +0 -0
- /package/dist/web/assets/{purescript-u9lGiQKV.js → purescript-DDJITf-A.js} +0 -0
- /package/dist/web/assets/{python-DeqTx6ef.js → python-bmWy9j1-.js} +0 -0
- /package/dist/web/assets/{qmldir-BH1uoPrX.js → qmldir-CKDwMt7X.js} +0 -0
- /package/dist/web/assets/{qss-CUVKA_13.js → qss-DptQQzBn.js} +0 -0
- /package/dist/web/assets/{r-BqdPzqYH.js → r-BorKpJ8r.js} +0 -0
- /package/dist/web/assets/{racket-C2eTgPN3.js → racket-BaHpYVsZ.js} +0 -0
- /package/dist/web/assets/{raku-uAay1sWx.js → raku-DFJIV4k_.js} +0 -0
- /package/dist/web/assets/{red-DTZP1ZfC.js → red-70oJGrkb.js} +0 -0
- /package/dist/web/assets/{reg-Cdk3YsxY.js → reg-C4g235Dv.js} +0 -0
- /package/dist/web/assets/{regexp-Bpa2aS7K.js → regexp-Cw1UVmti.js} +0 -0
- /package/dist/web/assets/{rel-bNsb1-3L.js → rel-DeLhIz5L.js} +0 -0
- /package/dist/web/assets/{resolve-theme-DQk_YcsT.js → resolve-theme-b_yGlUFQ.js} +0 -0
- /package/dist/web/assets/{riscv-DSaubByW.js → riscv-ChnTiBRK.js} +0 -0
- /package/dist/web/assets/{ron-DbQzYM6i.js → ron-C5IWeqDn.js} +0 -0
- /package/dist/web/assets/{rose-pine-C7RsprTu.js → rose-pine-DCR0ohYW.js} +0 -0
- /package/dist/web/assets/{rose-pine-dawn-VP976YzL.js → rose-pine-dawn-DvGZs1PR.js} +0 -0
- /package/dist/web/assets/{rose-pine-moon-XHZNhOqd.js → rose-pine-moon-BWACHjeS.js} +0 -0
- /package/dist/web/assets/{rosmsg-BVQlx0Lj.js → rosmsg-CQlIVazE.js} +0 -0
- /package/dist/web/assets/{run-in-terminal-bKRwuO2z.js → run-in-terminal-DHAvC1AG.js} +0 -0
- /package/dist/web/assets/{rust-VHaQ3rh3.js → rust-DGGVzWI8.js} +0 -0
- /package/dist/web/assets/{sass-CO-kMkwD.js → sass-bj1C0rFI.js} +0 -0
- /package/dist/web/assets/{scala-cY0GXkiz.js → scala-MU1tLKDi.js} +0 -0
- /package/dist/web/assets/{scheme-D4LNZE0X.js → scheme-CeGXtv7t.js} +0 -0
- /package/dist/web/assets/{sdbl-Bh2Fd2cn.js → sdbl-D0HLSGKp.js} +0 -0
- /package/dist/web/assets/{send-to-chat-S8LCNX7V.js → send-to-chat-BOyUWNKw.js} +0 -0
- /package/dist/web/assets/{separator-DqGg3f9c.js → separator-BzGoTlR7.js} +0 -0
- /package/dist/web/assets/{shellscript-KKclmCnt.js → shellscript-DkYiDvh1.js} +0 -0
- /package/dist/web/assets/{slack-dark-D6YQ-fqf.js → slack-dark-YqeHiGWH.js} +0 -0
- /package/dist/web/assets/{slack-ochin-CDf66CDj.js → slack-ochin-9Oe0DljJ.js} +0 -0
- /package/dist/web/assets/{smalltalk-D2OH_QIl.js → smalltalk-CaaxedR7.js} +0 -0
- /package/dist/web/assets/{snazzy-light-CQeF8G1K.js → snazzy-light-C8s2FHNC.js} +0 -0
- /package/dist/web/assets/{solarized-dark-LTPf1iLZ.js → solarized-dark-0ryY6oN3.js} +0 -0
- /package/dist/web/assets/{solarized-light-Ose1n88k.js → solarized-light-bltgZeNh.js} +0 -0
- /package/dist/web/assets/{solidity-lFuOMHki.js → solidity-DOf5HmLZ.js} +0 -0
- /package/dist/web/assets/{splunk-Bov-sB5S.js → splunk-D1u4WHDW.js} +0 -0
- /package/dist/web/assets/{sql-BKyZ6wmk.js → sql-G8uQZljX.js} +0 -0
- /package/dist/web/assets/{ssh-config-CqJoMGMb.js → ssh-config-rbXvly7Q.js} +0 -0
- /package/dist/web/assets/{stylus-Bf5pWRLI.js → stylus-Cii1iADy.js} +0 -0
- /package/dist/web/assets/{swift-D5d1hn_u.js → swift-DpIgonN4.js} +0 -0
- /package/dist/web/assets/{synthwave-84-B4c6YAgO.js → synthwave-84-DjGLzU2b.js} +0 -0
- /package/dist/web/assets/{system-verilog-D7fXyDsI.js → system-verilog-_Z0M0Hs1.js} +0 -0
- /package/dist/web/assets/{systemd-oNagzlBK.js → systemd-BhyDCh9P.js} +0 -0
- /package/dist/web/assets/{talonscript-C6Nqm9Dm.js → talonscript-CNchgCRD.js} +0 -0
- /package/dist/web/assets/{tasl-CaWy-cBX.js → tasl-m--W7Pyr.js} +0 -0
- /package/dist/web/assets/{tcl-C435P5Mq.js → tcl-gY-M_2BC.js} +0 -0
- /package/dist/web/assets/{terraform-CVDxqdPf.js → terraform-CB6CzMwo.js} +0 -0
- /package/dist/web/assets/{tokyo-night-Uhs17tQ3.js → tokyo-night-COh9oRYi.js} +0 -0
- /package/dist/web/assets/{toml-j6fPOJ6P.js → toml-Bg2bsY-v.js} +0 -0
- /package/dist/web/assets/{tsv-h78O6xrL.js → tsv-DceGDiJC.js} +0 -0
- /package/dist/web/assets/{tsx-Bol-vCrQ.js → tsx-EccDYa7i.js} +0 -0
- /package/dist/web/assets/{turtle-Dw8eFf04.js → turtle-C_l2JhvX.js} +0 -0
- /package/dist/web/assets/{typescript-Dtz7DPci.js → typescript-C1ytmMcr.js} +0 -0
- /package/dist/web/assets/{typespec-BIOQ7dMP.js → typespec-De2ztzG5.js} +0 -0
- /package/dist/web/assets/{typst-CoaGMjzu.js → typst-DNcS7gSr.js} +0 -0
- /package/dist/web/assets/{use-blob-url-Gfi69PtP.js → use-blob-url-De-ZtcpX.js} +0 -0
- /package/dist/web/assets/{use-open-team-member-CruUTqzD.js → use-open-team-member-DWhhWdmJ.js} +0 -0
- /package/dist/web/assets/{use-visual-viewport-rnvuooQZ.js → use-visual-viewport-D9O48HQt.js} +0 -0
- /package/dist/web/assets/{v-BoqFdpJ7.js → v-DSMUsdMO.js} +0 -0
- /package/dist/web/assets/{vala-COBpNnCC.js → vala-BEazLpkO.js} +0 -0
- /package/dist/web/assets/{vb-DxI86znh.js → vb-CV9pEJzW.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-BaMOj65g.js → vendor-xterm-cuGQmUjN.js} +0 -0
- /package/dist/web/assets/{verilog-DcTAamuQ.js → verilog-DhXkLVMk.js} +0 -0
- /package/dist/web/assets/{vesper-DO298JSv.js → vesper-n4IltYq-.js} +0 -0
- /package/dist/web/assets/{vhdl-Dq-bDVSN.js → vhdl-CePjFbvs.js} +0 -0
- /package/dist/web/assets/{viml-zHTRWuQh.js → viml-ChndFsm5.js} +0 -0
- /package/dist/web/assets/{vitesse-black-jlYMJCBf.js → vitesse-black-BytVdvhC.js} +0 -0
- /package/dist/web/assets/{vitesse-dark-DS0sUlSZ.js → vitesse-dark-83Wech0N.js} +0 -0
- /package/dist/web/assets/{vitesse-light-HSeZ2YhG.js → vitesse-light-Xg4wbeMO.js} +0 -0
- /package/dist/web/assets/{vyper-BQfKVO3M.js → vyper-eW1NC3FG.js} +0 -0
- /package/dist/web/assets/{wasm-B6mCuI8h.js → wasm-Bhucqu1z.js} +0 -0
- /package/dist/web/assets/{wasm-B1xp9bLp.js → wasm-BucxKwBZ.js} +0 -0
- /package/dist/web/assets/{wenyan-CfpS05sP.js → wenyan-BJFBuXuH.js} +0 -0
- /package/dist/web/assets/{wgsl-14GDsWRD.js → wgsl-6z4FUyMK.js} +0 -0
- /package/dist/web/assets/{wikitext-Ccbq5EVX.js → wikitext-BoDU6teJ.js} +0 -0
- /package/dist/web/assets/{window-pip-registry-BEN0QNSW.js → window-pip-registry-CSLhJfpL.js} +0 -0
- /package/dist/web/assets/{wit-C19hb3R5.js → wit-DerMPpgt.js} +0 -0
- /package/dist/web/assets/{wolfram-B-ZSwGwP.js → wolfram-D78v0Ap-.js} +0 -0
- /package/dist/web/assets/{ws-auth-Dawx17PM.js → ws-auth-ZSZkAT6p.js} +0 -0
- /package/dist/web/assets/{yaml-mw_JUeio.js → yaml-C4TIgIw4.js} +0 -0
- /package/dist/web/assets/{zenscript-WbzDRjvF.js → zenscript-BydW-dLC.js} +0 -0
- /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
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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
|
-
<
|
|
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
|
-
|
|
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) => ({
|
|
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
|
-
//
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
const
|
|
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
|
|
88
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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({
|
|
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
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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 });
|