@hienlh/ppm 0.19.6 → 0.19.8
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 +13 -0
- package/CLAUDE.md +15 -0
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/cli-reference.md +4 -4
- 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-BeoI2Jp8.js → ai-resource-editor-DmOGQ_1E.js} +1 -1
- package/dist/web/assets/{ai-settings-section-Bc91w0K4.js → ai-settings-section-DP53HaV9.js} +1 -1
- package/dist/web/assets/{ai-settings-section-edmjpNtG.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-CvX5XncT.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-Dwogm7g8.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-CcgWfErD.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-DXlx5CrZ.js → database-viewer-BwSf-V1L.js} +1 -1
- package/dist/web/assets/{diff-viewer-tYKO0wXX.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-BPnA8ztG.js → explorer-body-B2FmdPAx.js} +2 -2
- package/dist/web/assets/{explorer-window-content-BMPhgAnl.js → explorer-window-content-CtSMepys.js} +1 -1
- package/dist/web/assets/{extension-manager-section-Cepy9w0W.js → extension-manager-section-CBRXxG8W.js} +1 -1
- package/dist/web/assets/{extension-webview-83orjfAz.js → extension-webview-yfMof39w.js} +1 -1
- package/dist/web/assets/{files-settings-section-A_5QWv4b.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-D9iuuwL4.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-Ch5Ap1WP.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-LEL-8oU_.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-DznCP9IR.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-BUeQf1S6.js → keybindings-store-DAMW7K3e.js} +1 -1
- package/dist/web/assets/{keyboard-shortcuts-section-C-BeYTwO.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-B47WcMMs.js → markdown-renderer-BtrHvth9.js} +3 -3
- package/dist/web/assets/{markdown-renderer-Dcq0J7Yw.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-RG64iGIe.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-CmvMzpl2.js → notification-store-DIwuBHMP.js} +1 -1
- package/dist/web/assets/{notifications-settings-section--zzeoLfi.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-CGn99JWL.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-D-mPRQRC.js → postgres-viewer-qQtI_Qan.js} +3 -3
- package/dist/web/assets/{ppmbot-settings-section-Dy1CBG9d.js → ppmbot-settings-section-C_yNqYo1.js} +1 -1
- package/dist/web/assets/{process-table-DSLrAJC5.js → process-table-DH95ASxx.js} +1 -1
- package/dist/web/assets/{proxy-settings-section-COr2LOQV.js → proxy-settings-section-7OpR2hAD.js} +1 -1
- 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-CShd9Vo1.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-Dj3n_7MA.js → remote-desktop-mobile-view-CiKtuPVS.js} +1 -1
- package/dist/web/assets/{remote-desktop-readiness-gate-CR2jZ4pW.js → remote-desktop-readiness-gate-BSBIPU4d.js} +1 -1
- package/dist/web/assets/{remote-desktop-window-content-BhQizWi0.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-Gi8hYwKJ.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-BUHL5rX-.js → system-monitor-window-content-C5TkD158.js} +1 -1
- package/dist/web/assets/{tab-host-window-content-2gwUy-OA.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-BvqhkPjH.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-CbHDqCBe.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-DIoAqDka.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-B8ltBkBj.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--W-pnzPS.js → use-remote-desktop-display-choice-DOg4xZ-8.js} +1 -1
- package/dist/web/assets/{use-websocket-Dek_fwOD.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-DijwhDXk.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/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
- package/src/providers/registry.ts +18 -3
- package/src/server/routes/settings.ts +1 -0
- package/src/services/config.service.ts +28 -0
- package/src/services/db.service.ts +39 -2
- package/src/services/edge-forwarder.ts +191 -191
- package/src/services/prod-db-guard.ts +98 -0
- package/src/services/windows-process-tree.ts +351 -351
- package/src/types/config.ts +14 -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/general-settings-section.tsx +37 -3
- package/src/web/hooks/use-wake-lock.ts +148 -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-DGsB-ynw.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-Ca5IpdzP.js +0 -1
- package/dist/web/assets/chat-tab-BHO6ceZp.js +0 -15
- package/dist/web/assets/code-editor-1ZV6iSCc.js +0 -7
- package/dist/web/assets/general-settings-section-CFDRUc2E.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-BloZfB0Q.js +0 -1
- package/dist/web/assets/group-chat-tab-CfTivWze.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/radar-KQ55EAFF-DBIZEaIU.js +0 -1
- package/dist/web/assets/remote-desktop-mobile-sheet-yFKdq8Cb.js +0 -2
- package/dist/web/assets/schedules-settings-section-f6VP9Mde.js +0 -1
- package/dist/web/assets/settings-body-BRJapYD0.js +0 -2
- package/dist/web/assets/settings-store-Brjd0QnO.js +0 -2
- package/dist/web/assets/settings-tab-hHtSuYDb.js +0 -1
- package/dist/web/assets/settings-window-content-CUrGhhKI.js +0 -1
- package/dist/web/assets/sql-query-editor-DxS_r9dM.js +0 -1
- package/dist/web/assets/system-monitor-body-CdWv_LBB.js +0 -2
- package/dist/web/assets/system-monitor-tab-DBMjRETL.js +0 -1
- package/dist/web/assets/team-member-sheet-B-3ri_oc.js +0 -2
- package/dist/web/assets/treemap-KZPCXAKY-DFiG9UYW.js +0 -1
- package/dist/web/assets/use-monaco-theme-2YgX5HEz.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
|
@@ -1,191 +1,191 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Edge forwarder — owns the public port and pipes raw TCP to the server's
|
|
3
|
-
* current loopback port.
|
|
4
|
-
*
|
|
5
|
-
* ─── CRITICAL INVARIANT: THIS PROCESS MUST NEVER SPAWN A CHILD ───
|
|
6
|
-
*
|
|
7
|
-
* On Windows a child spawned with fd stdio inherits every inheritable handle,
|
|
8
|
-
* including a listening socket. When such a descendant is orphaned it keeps the
|
|
9
|
-
* socket open, so the port stays in LISTEN under a dead PID and can never be
|
|
10
|
-
* rebound — a "zombie port". The server hits this constantly because it spawns
|
|
11
|
-
* chat/tool/MCP subprocesses; those inherit its listener and wedge its port.
|
|
12
|
-
*
|
|
13
|
-
* The edge exists precisely because it spawns nothing, so its socket cannot be
|
|
14
|
-
* inherited and its port cannot zombie. cloudflared can therefore stay pinned
|
|
15
|
-
* to it forever and the public URL stops rotating. Adding any child-process
|
|
16
|
-
* call to this file reintroduces the exact bug the edge was built to remove.
|
|
17
|
-
*
|
|
18
|
-
* Raw TCP, never HTTP: WebSocket upgrades and SSE streams pass through
|
|
19
|
-
* untouched, and forwarded requests keep the headers cloudflared set.
|
|
20
|
-
*/
|
|
21
|
-
import net from "node:net";
|
|
22
|
-
import { resolveTargetPort, _resetTargetCache } from "./edge-target-resolver.ts";
|
|
23
|
-
|
|
24
|
-
/** Delay between attempts while waiting for the server to come back. */
|
|
25
|
-
const CONNECT_RETRY_MS = 250;
|
|
26
|
-
/**
|
|
27
|
-
* How long a client connection waits for a reachable server before giving up.
|
|
28
|
-
* During an upgrade the server is briefly absent; refusing instantly would
|
|
29
|
-
* surface as a broken page rather than a slow one.
|
|
30
|
-
*/
|
|
31
|
-
const CONNECT_WINDOW_MS = 5000;
|
|
32
|
-
|
|
33
|
-
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
|
|
34
|
-
|
|
35
|
-
/** Resolve once the socket is connected; reject on the first connect error. */
|
|
36
|
-
function connectUpstream(port: number): Promise<net.Socket> {
|
|
37
|
-
return new Promise((resolvePromise, reject) => {
|
|
38
|
-
const upstream = net.connect({
|
|
39
|
-
port,
|
|
40
|
-
host: "127.0.0.1", // never taken from status.json — loopback only
|
|
41
|
-
allowHalfOpen: true,
|
|
42
|
-
});
|
|
43
|
-
const onError = (err: Error) => {
|
|
44
|
-
upstream.destroy();
|
|
45
|
-
reject(err);
|
|
46
|
-
};
|
|
47
|
-
upstream.once("error", onError);
|
|
48
|
-
upstream.once("connect", () => {
|
|
49
|
-
upstream.removeListener("error", onError);
|
|
50
|
-
resolvePromise(upstream);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Largest amount of client data held while waiting for the server. Bounds the
|
|
57
|
-
* memory a slow upload can pin during an upgrade window.
|
|
58
|
-
*/
|
|
59
|
-
const MAX_PENDING_BYTES = 8 * 1024 * 1024;
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Pipe one client connection to the server.
|
|
63
|
-
*
|
|
64
|
-
* Resolving the upstream is async, so the first bytes usually arrive before
|
|
65
|
-
* there is anywhere to send them. They must be captured by a `data` listener
|
|
66
|
-
* attached synchronously on this very tick and replayed once the upstream
|
|
67
|
-
* exists.
|
|
68
|
-
*
|
|
69
|
-
* `socket.pause()` is NOT a substitute — verified against Bun 1.3.13: bytes
|
|
70
|
-
* that arrive while paused are lost, and a later `pipe()`/`resume()` does not
|
|
71
|
-
* bring them back. A socket with no `data` listener drops them outright too.
|
|
72
|
-
* Both variants silently swallowed the first request in testing.
|
|
73
|
-
*/
|
|
74
|
-
async function handleConnection(
|
|
75
|
-
client: net.Socket,
|
|
76
|
-
connectWindowMs: number,
|
|
77
|
-
): Promise<void> {
|
|
78
|
-
const pending: Buffer[] = [];
|
|
79
|
-
let pendingBytes = 0;
|
|
80
|
-
let clientEnded = false;
|
|
81
|
-
const onEarlyData = (chunk: Buffer) => {
|
|
82
|
-
pendingBytes += chunk.length;
|
|
83
|
-
if (pendingBytes > MAX_PENDING_BYTES) {
|
|
84
|
-
client.destroy();
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
pending.push(chunk);
|
|
88
|
-
};
|
|
89
|
-
client.on("data", onEarlyData);
|
|
90
|
-
client.once("end", () => { clientEnded = true; });
|
|
91
|
-
|
|
92
|
-
let upstream: net.Socket | null = null;
|
|
93
|
-
let clientGone = false;
|
|
94
|
-
|
|
95
|
-
// A socket error with no listener is an unhandled 'error' event, which would
|
|
96
|
-
// take the whole edge process — and the public port — down with it.
|
|
97
|
-
const teardown = () => {
|
|
98
|
-
upstream?.destroy();
|
|
99
|
-
client.destroy();
|
|
100
|
-
};
|
|
101
|
-
client.on("error", teardown);
|
|
102
|
-
client.once("close", () => { clientGone = true; });
|
|
103
|
-
|
|
104
|
-
const deadline = Date.now() + connectWindowMs;
|
|
105
|
-
while (!clientGone && Date.now() < deadline) {
|
|
106
|
-
const port = resolveTargetPort();
|
|
107
|
-
if (port !== null) {
|
|
108
|
-
try {
|
|
109
|
-
upstream = await connectUpstream(port);
|
|
110
|
-
break;
|
|
111
|
-
} catch {
|
|
112
|
-
// Server not up yet (or moved mid-restart) — re-resolve and retry.
|
|
113
|
-
_resetTargetCache();
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
await sleep(CONNECT_RETRY_MS);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (clientGone) return;
|
|
120
|
-
if (!upstream) {
|
|
121
|
-
client.destroy();
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
upstream.on("error", teardown);
|
|
126
|
-
|
|
127
|
-
// Replay what arrived during the connect, then hand both directions to the
|
|
128
|
-
// stream machinery. Removing the listener and piping happen in the same tick,
|
|
129
|
-
// so no chunk can slip through the gap.
|
|
130
|
-
client.off("data", onEarlyData);
|
|
131
|
-
for (const chunk of pending) upstream.write(chunk);
|
|
132
|
-
pending.length = 0;
|
|
133
|
-
|
|
134
|
-
client.pipe(upstream);
|
|
135
|
-
upstream.pipe(client);
|
|
136
|
-
|
|
137
|
-
// The client may have half-closed while we were still connecting.
|
|
138
|
-
if (clientEnded) upstream.end();
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export interface EdgeForwarderOptions {
|
|
142
|
-
publicPort: number;
|
|
143
|
-
host?: string;
|
|
144
|
-
/** How long a client waits for a reachable server. Defaults to 5s. */
|
|
145
|
-
connectWindowMs?: number;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Bind the public port and start forwarding. Resolves once listening so the
|
|
150
|
-
* caller can fail fast when the port is unavailable.
|
|
151
|
-
*/
|
|
152
|
-
export function startEdgeForwarder(
|
|
153
|
-
opts: EdgeForwarderOptions,
|
|
154
|
-
): Promise<net.Server> {
|
|
155
|
-
const host = opts.host ?? "0.0.0.0";
|
|
156
|
-
const connectWindowMs = opts.connectWindowMs ?? CONNECT_WINDOW_MS;
|
|
157
|
-
return new Promise((resolvePromise, reject) => {
|
|
158
|
-
// allowHalfOpen keeps the other direction alive when one side sends FIN —
|
|
159
|
-
// long-lived chat WS and SSE streams depend on it.
|
|
160
|
-
const server = net.createServer({ allowHalfOpen: true }, (client) => {
|
|
161
|
-
void handleConnection(client, connectWindowMs);
|
|
162
|
-
});
|
|
163
|
-
server.once("error", reject);
|
|
164
|
-
server.listen(opts.publicPort, host, () => {
|
|
165
|
-
server.removeListener("error", reject);
|
|
166
|
-
resolvePromise(server);
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// ─── Process entry ─────────────────────────────────────────────────────
|
|
172
|
-
// Mirrors the `__serve__` guard in src/server/index.ts: the supervisor
|
|
173
|
-
// re-invokes the binary as `<bin> __edge__ <publicPort> <host>`.
|
|
174
|
-
if (process.argv.includes("__edge__")) {
|
|
175
|
-
const idx = process.argv.indexOf("__edge__");
|
|
176
|
-
const publicPort = parseInt(process.argv[idx + 1] ?? "", 10);
|
|
177
|
-
const host = process.argv[idx + 2] ?? "0.0.0.0";
|
|
178
|
-
|
|
179
|
-
if (!Number.isInteger(publicPort) || publicPort <= 0 || publicPort > 65535) {
|
|
180
|
-
process.stderr.write(`[edge] Invalid public port: ${process.argv[idx + 1]}\n`);
|
|
181
|
-
process.exit(2);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
try {
|
|
185
|
-
await startEdgeForwarder({ publicPort, host });
|
|
186
|
-
process.stderr.write(`[edge] Listening on ${host}:${publicPort}\n`);
|
|
187
|
-
} catch (err) {
|
|
188
|
-
process.stderr.write(`[edge] Failed to bind ${host}:${publicPort}: ${err}\n`);
|
|
189
|
-
process.exit(1);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Edge forwarder — owns the public port and pipes raw TCP to the server's
|
|
3
|
+
* current loopback port.
|
|
4
|
+
*
|
|
5
|
+
* ─── CRITICAL INVARIANT: THIS PROCESS MUST NEVER SPAWN A CHILD ───
|
|
6
|
+
*
|
|
7
|
+
* On Windows a child spawned with fd stdio inherits every inheritable handle,
|
|
8
|
+
* including a listening socket. When such a descendant is orphaned it keeps the
|
|
9
|
+
* socket open, so the port stays in LISTEN under a dead PID and can never be
|
|
10
|
+
* rebound — a "zombie port". The server hits this constantly because it spawns
|
|
11
|
+
* chat/tool/MCP subprocesses; those inherit its listener and wedge its port.
|
|
12
|
+
*
|
|
13
|
+
* The edge exists precisely because it spawns nothing, so its socket cannot be
|
|
14
|
+
* inherited and its port cannot zombie. cloudflared can therefore stay pinned
|
|
15
|
+
* to it forever and the public URL stops rotating. Adding any child-process
|
|
16
|
+
* call to this file reintroduces the exact bug the edge was built to remove.
|
|
17
|
+
*
|
|
18
|
+
* Raw TCP, never HTTP: WebSocket upgrades and SSE streams pass through
|
|
19
|
+
* untouched, and forwarded requests keep the headers cloudflared set.
|
|
20
|
+
*/
|
|
21
|
+
import net from "node:net";
|
|
22
|
+
import { resolveTargetPort, _resetTargetCache } from "./edge-target-resolver.ts";
|
|
23
|
+
|
|
24
|
+
/** Delay between attempts while waiting for the server to come back. */
|
|
25
|
+
const CONNECT_RETRY_MS = 250;
|
|
26
|
+
/**
|
|
27
|
+
* How long a client connection waits for a reachable server before giving up.
|
|
28
|
+
* During an upgrade the server is briefly absent; refusing instantly would
|
|
29
|
+
* surface as a broken page rather than a slow one.
|
|
30
|
+
*/
|
|
31
|
+
const CONNECT_WINDOW_MS = 5000;
|
|
32
|
+
|
|
33
|
+
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
|
|
34
|
+
|
|
35
|
+
/** Resolve once the socket is connected; reject on the first connect error. */
|
|
36
|
+
function connectUpstream(port: number): Promise<net.Socket> {
|
|
37
|
+
return new Promise((resolvePromise, reject) => {
|
|
38
|
+
const upstream = net.connect({
|
|
39
|
+
port,
|
|
40
|
+
host: "127.0.0.1", // never taken from status.json — loopback only
|
|
41
|
+
allowHalfOpen: true,
|
|
42
|
+
});
|
|
43
|
+
const onError = (err: Error) => {
|
|
44
|
+
upstream.destroy();
|
|
45
|
+
reject(err);
|
|
46
|
+
};
|
|
47
|
+
upstream.once("error", onError);
|
|
48
|
+
upstream.once("connect", () => {
|
|
49
|
+
upstream.removeListener("error", onError);
|
|
50
|
+
resolvePromise(upstream);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Largest amount of client data held while waiting for the server. Bounds the
|
|
57
|
+
* memory a slow upload can pin during an upgrade window.
|
|
58
|
+
*/
|
|
59
|
+
const MAX_PENDING_BYTES = 8 * 1024 * 1024;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Pipe one client connection to the server.
|
|
63
|
+
*
|
|
64
|
+
* Resolving the upstream is async, so the first bytes usually arrive before
|
|
65
|
+
* there is anywhere to send them. They must be captured by a `data` listener
|
|
66
|
+
* attached synchronously on this very tick and replayed once the upstream
|
|
67
|
+
* exists.
|
|
68
|
+
*
|
|
69
|
+
* `socket.pause()` is NOT a substitute — verified against Bun 1.3.13: bytes
|
|
70
|
+
* that arrive while paused are lost, and a later `pipe()`/`resume()` does not
|
|
71
|
+
* bring them back. A socket with no `data` listener drops them outright too.
|
|
72
|
+
* Both variants silently swallowed the first request in testing.
|
|
73
|
+
*/
|
|
74
|
+
async function handleConnection(
|
|
75
|
+
client: net.Socket,
|
|
76
|
+
connectWindowMs: number,
|
|
77
|
+
): Promise<void> {
|
|
78
|
+
const pending: Buffer[] = [];
|
|
79
|
+
let pendingBytes = 0;
|
|
80
|
+
let clientEnded = false;
|
|
81
|
+
const onEarlyData = (chunk: Buffer) => {
|
|
82
|
+
pendingBytes += chunk.length;
|
|
83
|
+
if (pendingBytes > MAX_PENDING_BYTES) {
|
|
84
|
+
client.destroy();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
pending.push(chunk);
|
|
88
|
+
};
|
|
89
|
+
client.on("data", onEarlyData);
|
|
90
|
+
client.once("end", () => { clientEnded = true; });
|
|
91
|
+
|
|
92
|
+
let upstream: net.Socket | null = null;
|
|
93
|
+
let clientGone = false;
|
|
94
|
+
|
|
95
|
+
// A socket error with no listener is an unhandled 'error' event, which would
|
|
96
|
+
// take the whole edge process — and the public port — down with it.
|
|
97
|
+
const teardown = () => {
|
|
98
|
+
upstream?.destroy();
|
|
99
|
+
client.destroy();
|
|
100
|
+
};
|
|
101
|
+
client.on("error", teardown);
|
|
102
|
+
client.once("close", () => { clientGone = true; });
|
|
103
|
+
|
|
104
|
+
const deadline = Date.now() + connectWindowMs;
|
|
105
|
+
while (!clientGone && Date.now() < deadline) {
|
|
106
|
+
const port = resolveTargetPort();
|
|
107
|
+
if (port !== null) {
|
|
108
|
+
try {
|
|
109
|
+
upstream = await connectUpstream(port);
|
|
110
|
+
break;
|
|
111
|
+
} catch {
|
|
112
|
+
// Server not up yet (or moved mid-restart) — re-resolve and retry.
|
|
113
|
+
_resetTargetCache();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
await sleep(CONNECT_RETRY_MS);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (clientGone) return;
|
|
120
|
+
if (!upstream) {
|
|
121
|
+
client.destroy();
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
upstream.on("error", teardown);
|
|
126
|
+
|
|
127
|
+
// Replay what arrived during the connect, then hand both directions to the
|
|
128
|
+
// stream machinery. Removing the listener and piping happen in the same tick,
|
|
129
|
+
// so no chunk can slip through the gap.
|
|
130
|
+
client.off("data", onEarlyData);
|
|
131
|
+
for (const chunk of pending) upstream.write(chunk);
|
|
132
|
+
pending.length = 0;
|
|
133
|
+
|
|
134
|
+
client.pipe(upstream);
|
|
135
|
+
upstream.pipe(client);
|
|
136
|
+
|
|
137
|
+
// The client may have half-closed while we were still connecting.
|
|
138
|
+
if (clientEnded) upstream.end();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface EdgeForwarderOptions {
|
|
142
|
+
publicPort: number;
|
|
143
|
+
host?: string;
|
|
144
|
+
/** How long a client waits for a reachable server. Defaults to 5s. */
|
|
145
|
+
connectWindowMs?: number;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Bind the public port and start forwarding. Resolves once listening so the
|
|
150
|
+
* caller can fail fast when the port is unavailable.
|
|
151
|
+
*/
|
|
152
|
+
export function startEdgeForwarder(
|
|
153
|
+
opts: EdgeForwarderOptions,
|
|
154
|
+
): Promise<net.Server> {
|
|
155
|
+
const host = opts.host ?? "0.0.0.0";
|
|
156
|
+
const connectWindowMs = opts.connectWindowMs ?? CONNECT_WINDOW_MS;
|
|
157
|
+
return new Promise((resolvePromise, reject) => {
|
|
158
|
+
// allowHalfOpen keeps the other direction alive when one side sends FIN —
|
|
159
|
+
// long-lived chat WS and SSE streams depend on it.
|
|
160
|
+
const server = net.createServer({ allowHalfOpen: true }, (client) => {
|
|
161
|
+
void handleConnection(client, connectWindowMs);
|
|
162
|
+
});
|
|
163
|
+
server.once("error", reject);
|
|
164
|
+
server.listen(opts.publicPort, host, () => {
|
|
165
|
+
server.removeListener("error", reject);
|
|
166
|
+
resolvePromise(server);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ─── Process entry ─────────────────────────────────────────────────────
|
|
172
|
+
// Mirrors the `__serve__` guard in src/server/index.ts: the supervisor
|
|
173
|
+
// re-invokes the binary as `<bin> __edge__ <publicPort> <host>`.
|
|
174
|
+
if (process.argv.includes("__edge__")) {
|
|
175
|
+
const idx = process.argv.indexOf("__edge__");
|
|
176
|
+
const publicPort = parseInt(process.argv[idx + 1] ?? "", 10);
|
|
177
|
+
const host = process.argv[idx + 2] ?? "0.0.0.0";
|
|
178
|
+
|
|
179
|
+
if (!Number.isInteger(publicPort) || publicPort <= 0 || publicPort > 65535) {
|
|
180
|
+
process.stderr.write(`[edge] Invalid public port: ${process.argv[idx + 1]}\n`);
|
|
181
|
+
process.exit(2);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
await startEdgeForwarder({ publicPort, host });
|
|
186
|
+
process.stderr.write(`[edge] Listening on ${host}:${publicPort}\n`);
|
|
187
|
+
} catch (err) {
|
|
188
|
+
process.stderr.write(`[edge] Failed to bind ${host}:${publicPort}: ${err}\n`);
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gatekeeper for the real (non-isolated) PPM database.
|
|
3
|
+
*
|
|
4
|
+
* `getDb()` opens `~/.ppm/ppm.db` lazily for whoever asks first, which put every
|
|
5
|
+
* throwaway script, spike and agent worktree one import away from production
|
|
6
|
+
* state: a proxy probe that booted the provider registry without loading config
|
|
7
|
+
* once reset the whole `config` table and emptied `projects`, locking the user
|
|
8
|
+
* out of their own instance.
|
|
9
|
+
*
|
|
10
|
+
* The rule enforced here: only a genuine PPM entrypoint may touch the real
|
|
11
|
+
* database. Anything else must either point `PPM_HOME` at a scratch directory --
|
|
12
|
+
* the isolation contract the test suite already uses -- or opt in loudly through
|
|
13
|
+
* `PPM_ALLOW_PROD_DB=1`.
|
|
14
|
+
*/
|
|
15
|
+
import { sep } from "node:path";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Entry scripts cleared to open the real database, matched as path suffixes so
|
|
19
|
+
* they hold for a git checkout, a global npm install and a worktree alike.
|
|
20
|
+
*/
|
|
21
|
+
const ALLOWED_ENTRYPOINTS = [
|
|
22
|
+
"src/index.ts", // ppm CLI -- package.json "bin"
|
|
23
|
+
"src/server/index.ts", // HTTP server, and the __serve__ daemon child
|
|
24
|
+
"src/services/supervisor.ts", // __supervise__
|
|
25
|
+
"src/services/edge-forwarder.ts", // __edge__
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
/** Escape hatch for a deliberate one-off against production state. */
|
|
29
|
+
export const PROD_DB_OVERRIDE_ENV = "PPM_ALLOW_PROD_DB";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Everything the decision depends on, gathered in one place so the rule can be
|
|
33
|
+
* exercised without mutating process-wide state (tests that unset PPM_HOME leak
|
|
34
|
+
* the real ~/.ppm into whatever runs next).
|
|
35
|
+
*/
|
|
36
|
+
export interface ProdDbGuardContext {
|
|
37
|
+
ppmHome: string | undefined;
|
|
38
|
+
override: string | undefined;
|
|
39
|
+
execPath: string;
|
|
40
|
+
/** Raw process.argv[1], separators not yet normalised. */
|
|
41
|
+
entry: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Snapshot the live process into a guard context. */
|
|
45
|
+
export function currentProdDbGuardContext(): ProdDbGuardContext {
|
|
46
|
+
return {
|
|
47
|
+
ppmHome: process.env.PPM_HOME,
|
|
48
|
+
override: process.env[PROD_DB_OVERRIDE_ENV],
|
|
49
|
+
execPath: process.execPath,
|
|
50
|
+
entry: process.argv[1] ?? "",
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Entry path with separators normalised, so Windows paths match the suffixes. */
|
|
55
|
+
function normaliseEntry(entry: string): string {
|
|
56
|
+
return entry.split(sep).join("/");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Whether the described process may open the real database.
|
|
61
|
+
*
|
|
62
|
+
* A set `PPM_HOME` already redirects the whole PPM directory elsewhere, so the
|
|
63
|
+
* caller has isolated itself and there is nothing left to protect.
|
|
64
|
+
*/
|
|
65
|
+
export function isAllowedProdDbEntrypoint(
|
|
66
|
+
ctx: ProdDbGuardContext = currentProdDbGuardContext(),
|
|
67
|
+
): boolean {
|
|
68
|
+
if (ctx.ppmHome) return true;
|
|
69
|
+
if (ctx.override === "1") return true;
|
|
70
|
+
// A compiled binary carries its entry inside the executable, so argv[1] is not
|
|
71
|
+
// a source path there. Same signal autostart-generator uses.
|
|
72
|
+
if (!ctx.execPath.includes("bun")) return true;
|
|
73
|
+
const entry = normaliseEntry(ctx.entry);
|
|
74
|
+
// Anchored on a path boundary, so a stray ".../vendor-src/index.ts" cannot pose
|
|
75
|
+
// as the CLI just by ending in the same characters.
|
|
76
|
+
return ALLOWED_ENTRYPOINTS.some(
|
|
77
|
+
(suffix) => entry === suffix || entry.endsWith("/" + suffix),
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Throw unless the current process is allowed to open `dbPath`.
|
|
83
|
+
* The message is written for whoever -- or whatever -- is driving the script.
|
|
84
|
+
*/
|
|
85
|
+
export function assertProdDbAccessAllowed(dbPath: string): void {
|
|
86
|
+
const ctx = currentProdDbGuardContext();
|
|
87
|
+
if (isAllowedProdDbEntrypoint(ctx)) return;
|
|
88
|
+
const entry = normaliseEntry(ctx.entry) || "<unknown entry>";
|
|
89
|
+
throw new Error(
|
|
90
|
+
[
|
|
91
|
+
`Refusing to open the real PPM database at ${dbPath} from "${entry}".`,
|
|
92
|
+
"Only the ppm CLI, server, supervisor and edge forwarder may touch production state.",
|
|
93
|
+
"Run this against a scratch database instead -- set PPM_HOME to a temp directory",
|
|
94
|
+
`(the same isolation the test suite uses) -- or set ${PROD_DB_OVERRIDE_ENV}=1 if you`,
|
|
95
|
+
"genuinely intend to write to ~/.ppm.",
|
|
96
|
+
].join(" "),
|
|
97
|
+
);
|
|
98
|
+
}
|