@hienlh/ppm 0.18.12 → 0.18.14
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/AGENTS.md +17 -5
- package/CHANGELOG.md +27 -0
- package/CLAUDE.md +3 -0
- package/README.md +6 -6
- 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 +19 -1
- package/dist/web/assets/{adaptive-context-menu-DGCKKeTy.js → adaptive-context-menu-DCZtgOL7.js} +1 -1
- package/dist/web/assets/{ai-resource-editor-BOHHTTe7.js → ai-resource-editor-D5CPBg06.js} +1 -1
- package/dist/web/assets/{ai-settings-section-BigC_nZR.js → ai-settings-section-DY-t1bK8.js} +1 -1
- package/dist/web/assets/{angular-html-BYPaydvh.js → angular-html-CTvM4ulF.js} +1 -1
- package/dist/web/assets/{angular-ts-Bb4AMKlk.js → angular-ts-B_vSkjco.js} +1 -1
- package/dist/web/assets/api-client-BogqsFna.js +1 -0
- package/dist/web/assets/{api-settings-Bd3M4YpI.js → api-settings-B2iNXQ0c.js} +1 -1
- package/dist/web/assets/api-settings-DRF9oYkn.js +1 -0
- package/dist/web/assets/{api-themes-Cpx419SL.js → api-themes-DrWnJbhs.js} +1 -1
- package/dist/web/assets/{apl-DB2VjFCS.js → apl-DywzTry0.js} +1 -1
- package/dist/web/assets/architecture-PBZL5I3N-nw5-j_I_.js +1 -0
- package/dist/web/assets/{astro-BeoJdVpk.js → astro-1JaRgaSb.js} +1 -1
- package/dist/web/assets/{audio-preview-BgFuTn-0.js → audio-preview-DAuGvOiK.js} +1 -1
- package/dist/web/assets/{blade-Cf2q1sPf.js → blade-CDeeJWBb.js} +1 -1
- package/dist/web/assets/{bsl-W1kOaNpu.js → bsl-BfgoPVYR.js} +1 -1
- package/dist/web/assets/{button-5zTrkEoN.js → button-tNy0ba3y.js} +1 -1
- package/dist/web/assets/{cairo-BoAZFcje.js → cairo-C26gNwWW.js} +1 -1
- package/dist/web/assets/chat-tab-IcnU3nqQ.js +15 -0
- package/dist/web/assets/{cobol-B0Nm7RXj.js → cobol-D92nBnON.js} +1 -1
- package/dist/web/assets/code-editor-Dno5Srkm.js +10 -0
- package/dist/web/assets/{coffee-BakMn3on.js → coffee-CIWH40R1.js} +1 -1
- package/dist/web/assets/{conflict-editor-BUs5k9q_.js → conflict-editor-CDp0I3mD.js} +1 -1
- package/dist/web/assets/{context-menu-Bq92km4s.js → context-menu-BO1c9jKy.js} +1 -1
- package/dist/web/assets/{cpp-BRAJQHK2.js → cpp-DOrBqXCn.js} +1 -1
- package/dist/web/assets/{crystal-kqqO3zkK.js → crystal-BNKqmHux.js} +1 -1
- package/dist/web/assets/{csv-preview-ByoDgLAZ.js → csv-preview-D4svNDAq.js} +1 -1
- package/dist/web/assets/{data-grid-overlay-editor-Brkf9z41.js → data-grid-overlay-editor-BqV0AxZg.js} +1 -1
- package/dist/web/assets/{database-viewer-Btc3h8Yu.js → database-viewer-BCvv_Bwf.js} +1 -1
- package/dist/web/assets/{dialog-DwtGlowE.js → dialog-DcLGDwaX.js} +1 -1
- package/dist/web/assets/diff-viewer-D41fCFAi.js +4 -0
- package/dist/web/assets/{docx-preview-DAD_vg59.js → docx-preview-DfaQn9v7.js} +1 -1
- package/dist/web/assets/{edge-Cq1ZKZuE.js → edge-Dbjp42Pt.js} +1 -1
- package/dist/web/assets/{edit-diff-preview-B_VE7ppQ.js → edit-diff-preview-BqcUuFCc.js} +1 -1
- package/dist/web/assets/{elixir-BM_JoJRk.js → elixir-na3b1pYy.js} +1 -1
- package/dist/web/assets/{elm-Dw7oO08Y.js → elm-_Nalil1R.js} +1 -1
- package/dist/web/assets/{erb-CfKOGAfk.js → erb-CW_7dubf.js} +1 -1
- package/dist/web/assets/{erlang-DlDmGVeE.js → erlang-DmZ7Zzb0.js} +1 -1
- package/dist/web/assets/{esm-DGAP0GFh.js → esm-CwyBetO1.js} +1 -1
- package/dist/web/assets/explorer-body-DB1L30pa.js +2 -0
- package/dist/web/assets/explorer-window-content-Cwlt3C3I.js +1 -0
- package/dist/web/assets/{extension-store-Cpfh2vMm.js → extension-store-DUaZINyC.js} +1 -1
- package/dist/web/assets/{extension-webview-B2OnjuCu.js → extension-webview-BW_mccb3.js} +1 -1
- package/dist/web/assets/{file-store-aOERIEo-.js → file-store-yReVbR8q.js} +1 -1
- package/dist/web/assets/{fortran-fixed-form-XnAhQWxS.js → fortran-fixed-form-DB2A8L4-.js} +1 -1
- package/dist/web/assets/{fsharp-CdNvy0PG.js → fsharp-BYHrti7z.js} +1 -1
- package/dist/web/assets/{gdresource-DxuG5i8i.js → gdresource-D5GBin40.js} +1 -1
- package/dist/web/assets/{git-commit-3lMonsur.js → git-commit-CUiOBoIL.js} +1 -1
- package/dist/web/assets/{git-log-panel-Co0PBPHC.js → git-log-panel-C1QDkmgl.js} +1 -1
- package/dist/web/assets/{git-rebase-N8Z9kIMf.js → git-rebase-DOxGnpdw.js} +1 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-C1xf87gN.js +1 -0
- package/dist/web/assets/glide-data-grid-Dz8lx6n2.js +138 -0
- package/dist/web/assets/{glimmer-js-Dp9OXiib.js → glimmer-js-Begy4UT7.js} +1 -1
- package/dist/web/assets/{glimmer-ts-CDVKBcDj.js → glimmer-ts-rPApRY8N.js} +1 -1
- package/dist/web/assets/{glsl-DPJxI4us.js → glsl-wrbPvrBL.js} +1 -1
- package/dist/web/assets/{graphql-BrFhaQQl.js → graphql-Cu4-NR__.js} +1 -1
- package/dist/web/assets/group-chat-tab-DFwr-pig.js +1 -0
- package/dist/web/assets/{hack-BzXbDMlA.js → hack-Ddo93XKD.js} +1 -1
- package/dist/web/assets/{haml-CPpkX0s5.js → haml-BFX_1i8j.js} +1 -1
- package/dist/web/assets/{handlebars-BqrApy52.js → handlebars-5gFKA4H5.js} +1 -1
- package/dist/web/assets/{html-DmjUl-OA.js → html-C06I-zeO.js} +1 -1
- package/dist/web/assets/{html-derivative-Cnd6XFR5.js → html-derivative-e5JLAFZF.js} +1 -1
- package/dist/web/assets/{http-DMLWYun2.js → http-CrAAhSU7.js} +1 -1
- package/dist/web/assets/{hurl-CKkCVxbj.js → hurl-T1V3SX9T.js} +1 -1
- package/dist/web/assets/{hxml-CAx19TtQ.js → hxml-B056LLKN.js} +1 -1
- package/dist/web/assets/{image-preview-DHUoylQ1.js → image-preview-DWyuCYT3.js} +1 -1
- package/dist/web/assets/index-DWpNR3nB.css +2 -0
- package/dist/web/assets/index-oUKV5nIA.js +52 -0
- package/dist/web/assets/info-3K5VOQVL-C2z7FTDe.js +1 -0
- package/dist/web/assets/{input-DcEk7mA3.js → input-DouJ9Zvt.js} +1 -1
- package/dist/web/assets/{jinja-BmB9YN9l.js → jinja-DGdtRh43.js} +1 -1
- package/dist/web/assets/{jison-BaVsKKpw.js → jison-Ah6QobPS.js} +1 -1
- package/dist/web/assets/{julia-BgVBLveX.js → julia-BJeGOK0K.js} +1 -1
- package/dist/web/assets/{just-C2ENIbl9.js → just-iw9oRs7j.js} +1 -1
- package/dist/web/assets/{keybindings-store-BGIyqXHI.js → keybindings-store-0Wqfa7Qp.js} +1 -1
- package/dist/web/assets/keybindings-store-d54pv2NK.js +1 -0
- package/dist/web/assets/{latex-BiDIWxKL.js → latex-DHjj5hyN.js} +1 -1
- package/dist/web/assets/{liquid-NxpapreE.js → liquid-B-FFecDc.js} +1 -1
- package/dist/web/assets/{lua-DVepQvwH.js → lua-DDianJp_.js} +1 -1
- package/dist/web/assets/{markdown-renderer-DlcDhgrF.js → markdown-renderer-BHiUhQN8.js} +3 -3
- package/dist/web/assets/markdown-renderer-CnE36_gd.js +1 -0
- package/dist/web/assets/{marko-CJ2606Xl.js → marko-BW5SBVng.js} +1 -1
- package/dist/web/assets/{mdc-D2bjqclE.js → mdc-B9gL9bjl.js} +1 -1
- package/dist/web/assets/{media-url-H17XJF-I.js → media-url-DUK-k0bB.js} +1 -1
- package/dist/web/assets/{mobile-bottom-sheet-g-r2hCFa.js → mobile-bottom-sheet-CJ7ApOkI.js} +1 -1
- package/dist/web/assets/mobile-explorer-sheet-BzjlS1Xn.js +1 -0
- package/dist/web/assets/{nextflow-BtJwUbfF.js → nextflow-dTluY6qy.js} +1 -1
- package/dist/web/assets/{nginx-j4gyIhHE.js → nginx-DlwghGI-.js} +1 -1
- package/dist/web/assets/{nim-ClH_gjP5.js → nim-N9jddb5D.js} +1 -1
- package/dist/web/assets/notification-store-C7UBqxYP.js +1 -0
- package/dist/web/assets/{number-overlay-editor-C1EqJnWq.js → number-overlay-editor-BVXM7aAs.js} +1 -1
- package/dist/web/assets/{overview-panel-vTeeJYVZ.js → overview-panel-DCCDmtCQ.js} +1 -1
- package/dist/web/assets/packet-RMMSAZCW-DQUxN0wU.js +1 -0
- package/dist/web/assets/{panel-store-BSnkjgHt.js → panel-store-B4rijFKN.js} +1 -1
- package/dist/web/assets/{pdf-preview-CqFGRY0Z.js → pdf-preview-D7yLmAZW.js} +1 -1
- package/dist/web/assets/{perl-C9H7X7CT.js → perl-CkmpYKa_.js} +1 -1
- package/dist/web/assets/{php-Bx2U-cQ_.js → php-BwZ3KDPo.js} +1 -1
- package/dist/web/assets/pie-UPGHQEXC-BOr9ek4Q.js +1 -0
- package/dist/web/assets/{postgres-viewer-DHwcQucn.js → postgres-viewer--CRN1fvO.js} +3 -3
- package/dist/web/assets/{process-table-BGRJNlpn.js → process-table-CXC10GSy.js} +1 -1
- package/dist/web/assets/{project-store--nvQiy75.js → project-store-BuY7rxn_.js} +1 -1
- package/dist/web/assets/{pug-Cw74sKsE.js → pug-B3rBPqQo.js} +1 -1
- package/dist/web/assets/{qml-BXD94Eqz.js → qml-BfDbWFmg.js} +1 -1
- package/dist/web/assets/radar-KQ55EAFF-DSErxZFb.js +1 -0
- package/dist/web/assets/{razor-DZ0-Ge0S.js → razor-B1ww1r38.js} +1 -1
- package/dist/web/assets/{rst-Dtdh0QUj.js → rst-C0MSq6m-.js} +1 -1
- package/dist/web/assets/{ruby-BC51BW2Q.js → ruby-ClIZ1wb3.js} +1 -1
- package/dist/web/assets/{run-in-terminal-Sd3KyjN4.js → run-in-terminal-4efbW2Xv.js} +1 -1
- package/dist/web/assets/{sas-BN8i4qOU.js → sas-DR0j3o4_.js} +1 -1
- package/dist/web/assets/{scroll-area-0gljZ6lF.js → scroll-area-ZP8wcwTI.js} +1 -1
- package/dist/web/assets/{scss-H-QtA7Rz.js → scss-Vh3JLayR.js} +1 -1
- package/dist/web/assets/{send-to-chat-u6m8l-rH.js → send-to-chat-BNrEpAyC.js} +1 -1
- package/dist/web/assets/{settings-store-CHY6Kzin.js → settings-store-OLJE7dPH.js} +2 -2
- package/dist/web/assets/{settings-tab-IY6K1MiZ.js → settings-tab-B1rvHFc6.js} +1 -1
- package/dist/web/assets/settings-tab-BUlmPJ2w.js +1 -0
- package/dist/web/assets/{shaderlab-CalNsj_x.js → shaderlab-0rHRnQ18.js} +1 -1
- package/dist/web/assets/{shellsession-BFrcoR8x.js → shellsession-Dxdw6D8c.js} +1 -1
- package/dist/web/assets/{soy-CNbku7vP.js → soy-BHlSNj1y.js} +1 -1
- package/dist/web/assets/{sparql-BN_orcVp.js → sparql-B2QaPpni.js} +1 -1
- package/dist/web/assets/{sql-query-editor-C6pC3I8l.js → sql-query-editor-R_iKjPP9.js} +1 -1
- package/dist/web/assets/{sqlite-viewer-DTr5PzUb.js → sqlite-viewer-b2onA0SP.js} +1 -1
- package/dist/web/assets/{stata-C6a5Ijzq.js → stata-CwIxjsEJ.js} +1 -1
- package/dist/web/assets/{surrealql-ClplI_HY.js → surrealql-C6vo-rp-.js} +1 -1
- package/dist/web/assets/{svelte-DNm-UNXB.js → svelte-LLdJ6rlH.js} +1 -1
- package/dist/web/assets/{switch-DKvKya9y.js → switch-DV-BDjyk.js} +1 -1
- package/dist/web/assets/system-monitor-body-DPYQlBEt.js +2 -0
- package/dist/web/assets/system-monitor-tab-CPQdWv27.js +1 -0
- package/dist/web/assets/{system-monitor-window-content-BUqRsPK2.js → system-monitor-window-content-BPif0azo.js} +1 -1
- package/dist/web/assets/tab-host-window-content-BnAN6m4K.js +1 -0
- package/dist/web/assets/{tab-store-CJuJRapl.js → tab-store-tFnyPmm4.js} +1 -1
- package/dist/web/assets/team-member-sheet-Bu2wG1sm.js +2 -0
- package/dist/web/assets/{team-member-window-content-T4Q5JI-G.js → team-member-window-content-BSyU-5Uc.js} +1 -1
- package/dist/web/assets/{templ-CSdqVobu.js → templ-CJGvhEP5.js} +1 -1
- package/dist/web/assets/{terminal-tab-Bb2rZegQ.js → terminal-tab-Ncor0Rfu.js} +3 -3
- package/dist/web/assets/{tex-DzSJ4kcZ.js → tex-psXWhc4t.js} +1 -1
- package/dist/web/assets/{tool-cards-lhqhrDTT.js → tool-cards-DdVP1wrD.js} +4 -4
- package/dist/web/assets/treemap-KZPCXAKY-C17p0LQw.js +1 -0
- package/dist/web/assets/{ts-tags-C28w3bTg.js → ts-tags-D5Ar_ZCO.js} +1 -1
- package/dist/web/assets/{twig-i5jY3QXB.js → twig-vJgGC-qY.js} +1 -1
- package/dist/web/assets/{use-blob-url-Dsq9OjTh.js → use-blob-url-BOVGWg9F.js} +1 -1
- package/dist/web/assets/use-coarse-long-press-BmI_GVW5.js +1 -0
- package/dist/web/assets/use-monaco-theme-BshnLXoY.js +1 -0
- package/dist/web/assets/{use-open-team-member-DkiEjFYE.js → use-open-team-member-CY3wOdWL.js} +1 -1
- package/dist/web/assets/{use-websocket-B8R50f7f.js → use-websocket-B7xjNsyD.js} +1 -1
- package/dist/web/assets/{vendor-mermaid-By4AVvJY.js → vendor-mermaid-999ksD45.js} +1 -1
- package/dist/web/assets/video-preview-7F72sRwf.js +1 -0
- package/dist/web/assets/{vue-Ceyet_lv.js → vue-BWngFyav.js} +1 -1
- package/dist/web/assets/{vue-html-GuU7g_hg.js → vue-html-BN5ZLu-H.js} +1 -1
- package/dist/web/assets/{vue-vine-CxXoaJr2.js → vue-vine-BZHnO8yV.js} +1 -1
- package/dist/web/assets/window-pip-registry-BnYU83LE.js +1 -0
- package/dist/web/assets/{window-store-CsEW6jiE.js → window-store-CQ1lghvv.js} +1 -1
- package/dist/web/assets/{xml-CbqOVhkP.js → xml-DS2beZHp.js} +1 -1
- package/dist/web/assets/{xsl-KfAmCauy.js → xsl-Ciiku1Bq.js} +1 -1
- package/dist/web/index.html +47 -45
- package/dist/web/sw.js +1 -1
- package/docs/architecture/ai-chat-and-providers.md +309 -0
- package/docs/architecture/data-and-storage.md +356 -0
- package/docs/architecture/extensions.md +496 -0
- package/docs/architecture/integrations.md +214 -0
- package/docs/architecture/workspace-and-ui.md +399 -0
- package/docs/claude-agent-sdk-reference.md +1 -1
- package/docs/code-patterns.md +361 -0
- package/docs/code-standards.md +8 -358
- package/docs/codebase-subsystems.md +364 -0
- package/docs/codebase-summary.md +34 -379
- package/docs/deployment-guide.md +280 -490
- package/docs/design-guidelines.md +4 -3
- package/docs/lessons-learned.md +27 -10
- package/docs/project-changelog.md +18 -806
- package/docs/project-overview-pdr.md +117 -111
- package/docs/project-roadmap.md +89 -133
- package/docs/system-architecture.md +77 -1826
- package/package.json +2 -2
- package/src/cli/commands/autostart.ts +2 -2
- package/src/cli/commands/config-cmd.ts +12 -3
- package/src/cli/commands/status.ts +3 -2
- package/src/cli/commands/stop.ts +32 -4
- package/src/server/index.ts +17 -3
- package/src/server/routes/chat-unread.ts +36 -0
- package/src/server/routes/named-tunnel.ts +132 -0
- package/src/server/routes/tunnel.ts +13 -0
- package/src/server/ws/chat.ts +5 -2
- package/src/services/autostart-register.ts +47 -29
- package/src/services/cloud.service.ts +26 -1
- package/src/services/config-secret-keys.ts +48 -0
- package/src/services/config.service.ts +1 -1
- package/src/services/db.service.ts +62 -12
- package/src/services/edge-forwarder.ts +191 -191
- package/src/services/extension-rpc-handlers.ts +9 -1
- package/src/services/file-watcher/watch-tree.ts +67 -33
- package/src/services/file-watcher.service.ts +28 -10
- package/src/services/fs-credential-path-guard.ts +103 -0
- package/src/services/fs-path-guard.service.ts +14 -66
- package/src/services/named-tunnel/cloudflare-dns-api.ts +40 -0
- package/src/services/named-tunnel/cloudflare-zone-api.ts +28 -0
- package/src/services/named-tunnel/cloudflared-cert.ts +95 -0
- package/src/services/named-tunnel/cloudflared-exec.ts +50 -0
- package/src/services/named-tunnel/cloudflared-login-helpers.ts +98 -0
- package/src/services/named-tunnel/cloudflared-login.service.ts +182 -0
- package/src/services/named-tunnel/hostname-rules.ts +58 -0
- package/src/services/named-tunnel/login-output-parser.ts +36 -0
- package/src/services/named-tunnel/named-tunnel-args.ts +110 -0
- package/src/services/named-tunnel/named-tunnel-config.ts +67 -0
- package/src/services/named-tunnel/named-tunnel-probe-state.ts +95 -0
- package/src/services/named-tunnel/named-tunnel-readiness.ts +59 -0
- package/src/services/named-tunnel/named-tunnel-runtime.ts +42 -0
- package/src/services/named-tunnel/named-tunnel-setup-confirm.ts +98 -0
- package/src/services/named-tunnel/named-tunnel-setup.service.ts +191 -0
- package/src/services/supervisor-state.ts +67 -2
- package/src/services/supervisor.ts +454 -157
- package/src/services/tunnel-registry-parse.ts +27 -0
- package/src/services/tunnel-registry.service.ts +2 -15
- package/src/services/tunnel.service.ts +12 -3
- package/src/services/windows-process-tree.ts +351 -351
- package/src/types/config.ts +31 -0
- package/src/web/app.tsx +5 -0
- package/src/web/components/chat/chat-history-bar.tsx +95 -98
- package/src/web/components/chat/chat-toolbar-overflow-menu.tsx +57 -0
- package/src/web/components/chat/session-debug-dialog.tsx +35 -27
- package/src/web/components/floating-window/floating-window.tsx +8 -1
- package/src/web/components/floating-window/open-tab-in-pip.ts +78 -0
- package/src/web/components/floating-window/window-pip-registry.ts +46 -0
- package/src/web/components/layout/cloud-share-named-tunnel-row.tsx +111 -0
- package/src/web/components/layout/cloud-share-popover.tsx +56 -14
- package/src/web/components/layout/tab-pop-out-menu-item.tsx +25 -2
- package/src/web/components/shared/connection-lost-overlay.tsx +44 -5
- package/src/web/components/tunnels/named-tunnel/hostname-validation.ts +14 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-copy.ts +96 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-hostname-field.tsx +51 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-login-step.tsx +105 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-section.tsx +159 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-setup-content.tsx +197 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-setup-popup.tsx +57 -0
- package/src/web/components/tunnels/named-tunnel/named-tunnel-step-reducer.ts +191 -0
- package/src/web/components/tunnels/named-tunnel/use-named-tunnel-setup.ts +212 -0
- package/src/web/components/tunnels/tunnel-manager-tab.tsx +4 -0
- package/src/web/hooks/use-global-events.ts +3 -1
- package/src/web/lib/api-named-tunnel.ts +54 -0
- package/src/web/lib/last-known-local-url.ts +23 -0
- package/src/web/stores/notification-store.ts +20 -1
- package/dist/web/assets/api-client-DTZEgjBQ.js +0 -1
- package/dist/web/assets/api-settings-kd1j4iR8.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-8dCMT9r7.js +0 -1
- package/dist/web/assets/chat-tab-E3bf_V8X.js +0 -15
- package/dist/web/assets/code-editor-BUlM2gXk.js +0 -10
- package/dist/web/assets/diff-viewer-CZaDnR4w.js +0 -4
- package/dist/web/assets/explorer-body-9aBmyVpZ.js +0 -2
- package/dist/web/assets/explorer-window-content-DRtqoSPA.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-2e_8dfbs.js +0 -1
- package/dist/web/assets/glide-data-grid-C4_zIneN.js +0 -138
- package/dist/web/assets/group-chat-tab-rOd8J8GC.js +0 -1
- package/dist/web/assets/index-BImUaigO.js +0 -52
- package/dist/web/assets/index-CSfi6DSU.css +0 -2
- package/dist/web/assets/info-3K5VOQVL-BZi1Gha1.js +0 -1
- package/dist/web/assets/keybindings-store-CzV2sPls.js +0 -1
- package/dist/web/assets/markdown-renderer-CcbR33VG.js +0 -1
- package/dist/web/assets/mobile-explorer-sheet-SIwQXlwA.js +0 -1
- package/dist/web/assets/notification-store-DV5QtUTg.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-o5htEcin.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-BXAIFSAD.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-Dbt2Aebl.js +0 -1
- package/dist/web/assets/settings-tab-Dic6TKkU.js +0 -1
- package/dist/web/assets/system-monitor-body-iwGiCns9.js +0 -2
- package/dist/web/assets/system-monitor-tab-DdXQhEel.js +0 -1
- package/dist/web/assets/tab-host-window-content-BnqGPu8a.js +0 -1
- package/dist/web/assets/team-member-sheet-LkAFSCvb.js +0 -2
- package/dist/web/assets/treemap-KZPCXAKY-DUbnl9dz.js +0 -1
- package/dist/web/assets/use-monaco-theme-BZvlsoBv.js +0 -1
- package/dist/web/assets/video-preview-m0-3p7QZ.js +0 -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/dist/web/assets/{abap-C6nB04tn.js → abap-CjzrhAS2.js} +0 -0
- /package/dist/web/assets/{actionscript-3-Vx4rw2sC.js → actionscript-3-B59Kbl-9.js} +0 -0
- /package/dist/web/assets/{ada-Ccd8vM20.js → ada-B7gItKAE.js} +0 -0
- /package/dist/web/assets/{andromeeda-DnBX5xMg.js → andromeeda-Dy5zcy0Q.js} +0 -0
- /package/dist/web/assets/{apache-B-9_sx0g.js → apache-B6T9jrc0.js} +0 -0
- /package/dist/web/assets/{apex-_wPVBYoL.js → apex-CTsIxDQw.js} +0 -0
- /package/dist/web/assets/{api-client-aQb5hHE5.js → api-client-oY1tC3tM.js} +0 -0
- /package/dist/web/assets/{applescript-CcvD-qr0.js → applescript-DuycKmmb.js} +0 -0
- /package/dist/web/assets/{apply-theme-BeLRfsSu.js → apply-theme-r8tKDrCR.js} +0 -0
- /package/dist/web/assets/{ara-C40Ztoms.js → ara-CISL3599.js} +0 -0
- /package/dist/web/assets/{asciidoc-CybYkJV4.js → asciidoc-BXyE2Lpr.js} +0 -0
- /package/dist/web/assets/{asm-9eOKwzR0.js → asm-y258phtP.js} +0 -0
- /package/dist/web/assets/{aurora-x-B5ZH4t7t.js → aurora-x-Dq3Jc78M.js} +0 -0
- /package/dist/web/assets/{awk-Dqilob-2.js → awk-DxL6XSJv.js} +0 -0
- /package/dist/web/assets/{ayu-dark-CPgRhf5r.js → ayu-dark-DjoK6Evo.js} +0 -0
- /package/dist/web/assets/{ayu-light-Do06Q52f.js → ayu-light-CKKXBLMI.js} +0 -0
- /package/dist/web/assets/{ayu-mirage-_BhxcrxY.js → ayu-mirage-DGXSrrXB.js} +0 -0
- /package/dist/web/assets/{ballerina-DDwK54QW.js → ballerina-DZSXFmUf.js} +0 -0
- /package/dist/web/assets/{bat-BGyGlzGk.js → bat-BNsZk6nY.js} +0 -0
- /package/dist/web/assets/{beancount-CRWBdapI.js → beancount-cPl4gJct.js} +0 -0
- /package/dist/web/assets/{berry-DbSFn2gO.js → berry-DGAodERk.js} +0 -0
- /package/dist/web/assets/{bibtex-QpsV9gm9.js → bibtex-DftVoRif.js} +0 -0
- /package/dist/web/assets/{bicep-CxS8CUve.js → bicep-Suioyyzh.js} +0 -0
- /package/dist/web/assets/{bird2-CuZhQzYR.js → bird2-DjU24I2P.js} +0 -0
- /package/dist/web/assets/{c-9bnDqE3g.js → c-DFi8Y_nN.js} +0 -0
- /package/dist/web/assets/{c3-JMZTrOhA.js → c3-1eSHnH5V.js} +0 -0
- /package/dist/web/assets/{cadence-DsDNayJS.js → cadence-DLLsFwQP.js} +0 -0
- /package/dist/web/assets/{can-open-in-ppm-BJfpynya.js → can-open-in-ppm-in727eFQ.js} +0 -0
- /package/dist/web/assets/{catppuccin-frappe-DYIKXXBe.js → catppuccin-frappe-DDj0JEiY.js} +0 -0
- /package/dist/web/assets/{catppuccin-latte-IYYOnUJ8.js → catppuccin-latte-DPyANHyR.js} +0 -0
- /package/dist/web/assets/{catppuccin-macchiato-BrJ_7mfS.js → catppuccin-macchiato-CO-h8VTT.js} +0 -0
- /package/dist/web/assets/{catppuccin-mocha-gzSu7v7-.js → catppuccin-mocha-BCmbN2IZ.js} +0 -0
- /package/dist/web/assets/{clarity-DLzsC0Hb.js → clarity-C0pYsZjs.js} +0 -0
- /package/dist/web/assets/{clipboard-7fw0Shic.js → clipboard-DBLGKMrH.js} +0 -0
- /package/dist/web/assets/{clojure-DS1BvoTt.js → clojure-JFr6s8iZ.js} +0 -0
- /package/dist/web/assets/{cmake-CDvsJwYp.js → cmake-EEcLEgVy.js} +0 -0
- /package/dist/web/assets/{codeowners-BjsYiflJ.js → codeowners-Deh3Lx0u.js} +0 -0
- /package/dist/web/assets/{codeql-CG-7ARat.js → codeql-C317igT5.js} +0 -0
- /package/dist/web/assets/{common-lisp-DSO1Lbh9.js → common-lisp-DepbATZs.js} +0 -0
- /package/dist/web/assets/{coq-DYdh3oP_.js → coq-MxgxU5ya.js} +0 -0
- /package/dist/web/assets/{csharp-DxEBz5s0.js → csharp-eEFXdsAq.js} +0 -0
- /package/dist/web/assets/{css-dal3Q-8C.js → css-Db-syWW9.js} +0 -0
- /package/dist/web/assets/{csv-CpqjMGiA.js → csv-DHeYcbaq.js} +0 -0
- /package/dist/web/assets/{csv-parser-3umBA4NY.js → csv-parser-_JWMLGl3.js} +0 -0
- /package/dist/web/assets/{cue-DinoJ_5k.js → cue-BmUNowrt.js} +0 -0
- /package/dist/web/assets/{cypher-DzxqmkUW.js → cypher-XjXHgCNS.js} +0 -0
- /package/dist/web/assets/{d-BxNwJuEC.js → d-BWJnZtig.js} +0 -0
- /package/dist/web/assets/{dark-plus-Clmv3V-0.js → dark-plus-Db7umas1.js} +0 -0
- /package/dist/web/assets/{dart-BWVtXD35.js → dart-DSI4HYh1.js} +0 -0
- /package/dist/web/assets/{data-grid-types-B4n51Fck.js → data-grid-types-CfVHh9gv.js} +0 -0
- /package/dist/web/assets/{dax-DsImuWgJ.js → dax-yw1JsAni.js} +0 -0
- /package/dist/web/assets/{desktop-B0jJuG2r.js → desktop-C2QO4RvD.js} +0 -0
- /package/dist/web/assets/{diff-CWqAAxoE.js → diff-Drt8aEyp.js} +0 -0
- /package/dist/web/assets/{dist-B-EXdSYE.js → dist-DNRvhVdz.js} +0 -0
- /package/dist/web/assets/{dist-C0eNNfbt.js → dist-VBxOHLmN.js} +0 -0
- /package/dist/web/assets/{docker-CYFCJdIL.js → docker-ByDKbmLl.js} +0 -0
- /package/dist/web/assets/{dotenv-CKDUjURg.js → dotenv-BkfOLytR.js} +0 -0
- /package/dist/web/assets/{dracula-CSoPspHE.js → dracula-DAmrm-Un.js} +0 -0
- /package/dist/web/assets/{dracula-soft-BuFjw5L1.js → dracula-soft-BUOEnKqR.js} +0 -0
- /package/dist/web/assets/{dream-maker-B6PdDRZu.js → dream-maker-DQBIfSiO.js} +0 -0
- /package/dist/web/assets/{emacs-lisp-CMcXvD0G.js → emacs-lisp-Blh5kBD3.js} +0 -0
- /package/dist/web/assets/{everforest-dark-cU8-wYzi.js → everforest-dark-CEzhDxHq.js} +0 -0
- /package/dist/web/assets/{everforest-light-KhorllqK.js → everforest-light-CPk_5Khm.js} +0 -0
- /package/dist/web/assets/{external-link-B8BynhvY.js → external-link-B6Hl0U4X.js} +0 -0
- /package/dist/web/assets/{fennel-BCELZK87.js → fennel-B1MT_EBZ.js} +0 -0
- /package/dist/web/assets/{file-exclamation-point-CZ4DiR75.js → file-exclamation-point-JzhTU2TX.js} +0 -0
- /package/dist/web/assets/{fish-BQc0y_jy.js → fish-C_HGcewt.js} +0 -0
- /package/dist/web/assets/{fluent-BTINnwF6.js → fluent-Dp1Iclmx.js} +0 -0
- /package/dist/web/assets/{folder-symlink-B8XrtvQK.js → folder-symlink-Dx1hOk8X.js} +0 -0
- /package/dist/web/assets/{format-bytes-WVcFxJuT.js → format-bytes-53WBtyi2.js} +0 -0
- /package/dist/web/assets/{fortran-free-form-BQim9wDz.js → fortran-free-form-B_-UA4XC.js} +0 -0
- /package/dist/web/assets/{gdscript-03w5u8un.js → gdscript-Bm_JpjS_.js} +0 -0
- /package/dist/web/assets/{gdshader-Dp2daNzU.js → gdshader-C_PNmfYU.js} +0 -0
- /package/dist/web/assets/{genie-CoNcjPiD.js → genie-B5rmR2TF.js} +0 -0
- /package/dist/web/assets/{gherkin-NrPOSPQL.js → gherkin-BTJ34TJ9.js} +0 -0
- /package/dist/web/assets/{github-dark-z4RE9ZqA.js → github-dark-DOkNVj9H.js} +0 -0
- /package/dist/web/assets/{github-dark-default-DOKw-1cI.js → github-dark-default-DTsmiyVo.js} +0 -0
- /package/dist/web/assets/{github-dark-dimmed-DJRNMkEA.js → github-dark-dimmed-CjbxAe9s.js} +0 -0
- /package/dist/web/assets/{github-dark-high-contrast-Bj7jJ_Gs.js → github-dark-high-contrast-r_M8F_k7.js} +0 -0
- /package/dist/web/assets/{github-light-B4k_yMFu.js → github-light-BzfxyMyb.js} +0 -0
- /package/dist/web/assets/{github-light-default-BHc-Uzhs.js → github-light-default-BOqiBIy5.js} +0 -0
- /package/dist/web/assets/{github-light-high-contrast-CHisIywL.js → github-light-high-contrast-DQzBrDM4.js} +0 -0
- /package/dist/web/assets/{gleam-CfbypZ4q.js → gleam-BWmuAtD8.js} +0 -0
- /package/dist/web/assets/{gn-YoAjyhJa.js → gn-CNQPjiZW.js} +0 -0
- /package/dist/web/assets/{gnuplot-xVkc1f1c.js → gnuplot-BlHjcPMe.js} +0 -0
- /package/dist/web/assets/{go-GPCwP3Gu.js → go-Bn8Ba9uz.js} +0 -0
- /package/dist/web/assets/{groovy-Crh4Yww9.js → groovy-C1Y1_F4V.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-hard-BluUFuDS.js → gruvbox-dark-hard-DueOsHav.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-medium-Cxk1FWQp.js → gruvbox-dark-medium-DaQjD538.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-soft-CHXMiFmj.js → gruvbox-dark-soft-CbbX2WOm.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-hard-B6eKPjAD.js → gruvbox-light-hard-E2M70ljZ.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-medium-pDwMm1ut.js → gruvbox-light-medium-B_DDLY6h.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-soft-Cxu6kHqK.js → gruvbox-light-soft-2SZmyC1F.js} +0 -0
- /package/dist/web/assets/{haskell-C6JKHjbK.js → haskell-D8DeoXtG.js} +0 -0
- /package/dist/web/assets/{haxe-BuBNdF0a.js → haxe-BmZm7B0W.js} +0 -0
- /package/dist/web/assets/{hcl-DZpDdGj2.js → hcl-CKnBM3ng.js} +0 -0
- /package/dist/web/assets/{hjson-CBkhYRuo.js → hjson-Ct9t4-ci.js} +0 -0
- /package/dist/web/assets/{hlsl-C5nMxnp9.js → hlsl-BZSASBqS.js} +0 -0
- /package/dist/web/assets/{horizon-VAFvA6R6.js → horizon-CzX1AZ08.js} +0 -0
- /package/dist/web/assets/{horizon-bright-BC0xn7T3.js → horizon-bright-CCVNeRIP.js} +0 -0
- /package/dist/web/assets/{houston-BxrUivmz.js → houston-DBlJN7xc.js} +0 -0
- /package/dist/web/assets/{hy-DLtOXoaH.js → hy-Dyc6h6Xb.js} +0 -0
- /package/dist/web/assets/{image-gallery-Gnf7TdCR.js → image-gallery-DujlrjOC.js} +0 -0
- /package/dist/web/assets/{imba-BdpFXM2W.js → imba-Bauru7s2.js} +0 -0
- /package/dist/web/assets/{ini-BInJO_T0.js → ini-SjdwtaTp.js} +0 -0
- /package/dist/web/assets/{java-Dxuddnkb.js → java-D2r0ocpf.js} +0 -0
- /package/dist/web/assets/{javascript-CVamJfLY.js → javascript-y-lof7iP.js} +0 -0
- /package/dist/web/assets/{json-BLZ0ozYk.js → json-DO4LSx5A.js} +0 -0
- /package/dist/web/assets/{json5-BnXzmMKs.js → json5-BEwWf-W3.js} +0 -0
- /package/dist/web/assets/{jsonc-CSgkSga7.js → jsonc-OBEFv7gP.js} +0 -0
- /package/dist/web/assets/{jsonl-CY5W2nF2.js → jsonl-DOyW4Mg3.js} +0 -0
- /package/dist/web/assets/{jsonnet-CEJYH3sF.js → jsonnet-BL5R2CpP.js} +0 -0
- /package/dist/web/assets/{jssm-CsJc7Uhk.js → jssm-ksPusAyg.js} +0 -0
- /package/dist/web/assets/{jsx-jCiRaHU7.js → jsx-B6XEu6O-.js} +0 -0
- /package/dist/web/assets/{kanagawa-dragon-DfoA_GxX.js → kanagawa-dragon-JBVe_ji_.js} +0 -0
- /package/dist/web/assets/{kanagawa-lotus-BOLYJpWd.js → kanagawa-lotus-ChprO68_.js} +0 -0
- /package/dist/web/assets/{kanagawa-wave-DfKlbT1G.js → kanagawa-wave-D_uB_R0Q.js} +0 -0
- /package/dist/web/assets/{kdl-CmssIFTi.js → kdl-pf5B8N_m.js} +0 -0
- /package/dist/web/assets/{kotlin-BRsNgp6x.js → kotlin-BdF0METC.js} +0 -0
- /package/dist/web/assets/{kusto-T8X9jUab.js → kusto-BneVP-OU.js} +0 -0
- /package/dist/web/assets/{laserwave-DkJMVJ8Z.js → laserwave-C4-UPIyG.js} +0 -0
- /package/dist/web/assets/{lean-C65KGVPq.js → lean-BN6Jdymq.js} +0 -0
- /package/dist/web/assets/{less-exIPdDlf.js → less-Cx-fdlDC.js} +0 -0
- /package/dist/web/assets/{lib-mC1NZfuw.js → lib-CMuBa85c.js} +0 -0
- /package/dist/web/assets/{libesm-DSutUtl1.js → libesm-BB74PRsH.js} +0 -0
- /package/dist/web/assets/{light-plus-DiHUXAZt.js → light-plus-DFnnn_iL.js} +0 -0
- /package/dist/web/assets/{llvm-CJBnEzFM.js → llvm-BGxtW0Nw.js} +0 -0
- /package/dist/web/assets/{loader-circle-gSPVxfvH.js → loader-circle-Dpqcv0eS.js} +0 -0
- /package/dist/web/assets/{lock-Did-87UV.js → lock-DldbT31x.js} +0 -0
- /package/dist/web/assets/{log-DxMyUMuP.js → log-kQb4eJnj.js} +0 -0
- /package/dist/web/assets/{logo-CC9NKzca.js → logo-DqAzaq7s.js} +0 -0
- /package/dist/web/assets/{luau-Bw10I6zf.js → luau-Dc2cp-zS.js} +0 -0
- /package/dist/web/assets/{make-C_6M90m6.js → make-DYg9dwaJ.js} +0 -0
- /package/dist/web/assets/{markdown-bR9_R-LF.js → markdown-O4EPpS3K.js} +0 -0
- /package/dist/web/assets/{material-theme-BUx2Qujn.js → material-theme-ClP8yfQ2.js} +0 -0
- /package/dist/web/assets/{material-theme-darker-CRJrPgKm.js → material-theme-darker-LOK55hGu.js} +0 -0
- /package/dist/web/assets/{material-theme-lighter-CUAYppPa.js → material-theme-lighter-j72tzZqi.js} +0 -0
- /package/dist/web/assets/{material-theme-ocean-DuINF1fg.js → material-theme-ocean-C19LKClA.js} +0 -0
- /package/dist/web/assets/{material-theme-palenight-W6_icGCj.js → material-theme-palenight-DJ5tN2ax.js} +0 -0
- /package/dist/web/assets/{matlab-rfqn_b3z.js → matlab-DQNZ_NU8.js} +0 -0
- /package/dist/web/assets/{mdx-Bh1B_YOJ.js → mdx-CJayB7XK.js} +0 -0
- /package/dist/web/assets/{mermaid-Dxf6Ya2k.js → mermaid-Cb0TRX92.js} +0 -0
- /package/dist/web/assets/{min-dark-CivZ2L0h.js → min-dark-CWM8Bo-m.js} +0 -0
- /package/dist/web/assets/{min-light-B1Ykqtma.js → min-light-BBR1sjS2.js} +0 -0
- /package/dist/web/assets/{mipsasm-DynHaM0d.js → mipsasm-Jc7u7YSS.js} +0 -0
- /package/dist/web/assets/{mojo-Clw5PbGH.js → mojo-CTB0cutd.js} +0 -0
- /package/dist/web/assets/{monitor-Dv8vn_6O.js → monitor-4vWfqzuN.js} +0 -0
- /package/dist/web/assets/{monokai-DFIooFZT.js → monokai-CvM_YNKx.js} +0 -0
- /package/dist/web/assets/{moonbit-DnBSZWGM.js → moonbit-CbFEfYYM.js} +0 -0
- /package/dist/web/assets/{move-CCcL2PfL.js → move-BT38p0kT.js} +0 -0
- /package/dist/web/assets/{narrat-BDarg5Lk.js → narrat-55QZ_kOG.js} +0 -0
- /package/dist/web/assets/{nextflow-groovy-DrZOeCNW.js → nextflow-groovy-Bg8peyqg.js} +0 -0
- /package/dist/web/assets/{night-owl-BnZZCK7v.js → night-owl-DzS77iPK.js} +0 -0
- /package/dist/web/assets/{night-owl-light-CEwBsVHS.js → night-owl-light-DER7fGnx.js} +0 -0
- /package/dist/web/assets/{nix-amCzOPMR.js → nix-BSI8YesN.js} +0 -0
- /package/dist/web/assets/{nord-BIs2BC6q.js → nord-9bn7iNWo.js} +0 -0
- /package/dist/web/assets/{nushell-Y02fo4yw.js → nushell-qDVZn_lw.js} +0 -0
- /package/dist/web/assets/{objective-c-7xOZtWW1.js → objective-c-Blf-ATos.js} +0 -0
- /package/dist/web/assets/{objective-cpp-eVtjUvVB.js → objective-cpp-Bz8bAq47.js} +0 -0
- /package/dist/web/assets/{ocaml-Bi6ZwqG4.js → ocaml-B9heAsc3.js} +0 -0
- /package/dist/web/assets/{odin-8xf1Y0S9.js → odin-BaFYnOwO.js} +0 -0
- /package/dist/web/assets/{one-dark-pro-hVv-_y_b.js → one-dark-pro-D6B_hSe-.js} +0 -0
- /package/dist/web/assets/{one-light-CJJ3MtHt.js → one-light-Ba-f0wyk.js} +0 -0
- /package/dist/web/assets/{openscad-B2HcywLk.js → openscad-UvYyL2MK.js} +0 -0
- /package/dist/web/assets/{pascal-C7fllV_7.js → pascal-B4-qvEoG.js} +0 -0
- /package/dist/web/assets/{pkl-qvLC1IWP.js → pkl-B146nqGx.js} +0 -0
- /package/dist/web/assets/{plastic-BT1wHZv2.js → plastic-L38t-Id3.js} +0 -0
- /package/dist/web/assets/{play-4MZi1Axp.js → play-CpCAoQRZ.js} +0 -0
- /package/dist/web/assets/{plsql-1MsmdmJD.js → plsql-ItOG5Cca.js} +0 -0
- /package/dist/web/assets/{plus-BhMZqFsN.js → plus-BR0qewJI.js} +0 -0
- /package/dist/web/assets/{po-BigskytD.js → po-imiCTaNX.js} +0 -0
- /package/dist/web/assets/{poimandres-DuklniF7.js → poimandres-Bu6sIba9.js} +0 -0
- /package/dist/web/assets/{polar-e2pjN_sp.js → polar-CTeGoFxV.js} +0 -0
- /package/dist/web/assets/{portal-container-context-Cm5HipFr.js → portal-container-context-a399Hd9F.js} +0 -0
- /package/dist/web/assets/{postcss-DtAeYjWw.js → postcss-jvFe6GNE.js} +0 -0
- /package/dist/web/assets/{powerquery-Cr2PtehI.js → powerquery-D9Dw1hJp.js} +0 -0
- /package/dist/web/assets/{powershell-BxFTGLJ4.js → powershell-CZqvYQtg.js} +0 -0
- /package/dist/web/assets/{prisma-COWJiwdZ.js → prisma-B4D2nO_7.js} +0 -0
- /package/dist/web/assets/{prolog-DFvGKRx6.js → prolog-CQbyUcCF.js} +0 -0
- /package/dist/web/assets/{proto-CcK80lFt.js → proto-Cwpo0cW1.js} +0 -0
- /package/dist/web/assets/{puppet-BF60bZ4F.js → puppet-CKxCwBod.js} +0 -0
- /package/dist/web/assets/{purescript-zL_69MzU.js → purescript-B-MyXMMp.js} +0 -0
- /package/dist/web/assets/{python-CIwKhfb_.js → python-D6QbSR2S.js} +0 -0
- /package/dist/web/assets/{qmldir-CXNe04Lo.js → qmldir-BpTSVcw_.js} +0 -0
- /package/dist/web/assets/{qss-C8lAWe6G.js → qss-DBc4gbpe.js} +0 -0
- /package/dist/web/assets/{r-CL5ZVL3_.js → r-i9jMMi0s.js} +0 -0
- /package/dist/web/assets/{racket-BBfh0uh0.js → racket-BWNaxU7C.js} +0 -0
- /package/dist/web/assets/{raku-o6E8R5Q3.js → raku-fqTZLn7L.js} +0 -0
- /package/dist/web/assets/{react-CBTnT4sY.js → react-X4jUntEf.js} +0 -0
- /package/dist/web/assets/{red-GomRF2Xp.js → red-D-JEcuzA.js} +0 -0
- /package/dist/web/assets/{refresh-cw-B06yaBrW.js → refresh-cw-B9iv7csb.js} +0 -0
- /package/dist/web/assets/{reg-_ffDIvx9.js → reg-BbirlU1S.js} +0 -0
- /package/dist/web/assets/{regexp-Bl5sF65W.js → regexp-D8VTFrtg.js} +0 -0
- /package/dist/web/assets/{rel-DgMdqDuj.js → rel-ByQGKiNM.js} +0 -0
- /package/dist/web/assets/{resolve-theme-CRt_7wpd.js → resolve-theme-Cqb9zWYc.js} +0 -0
- /package/dist/web/assets/{riscv-8b3-Ye4X.js → riscv-B5nqCfLE.js} +0 -0
- /package/dist/web/assets/{ron-DrmU1KHP.js → ron-DOVh_iZR.js} +0 -0
- /package/dist/web/assets/{rose-pine-dawn-DEfhNlFH.js → rose-pine-dawn-B7hkmmWy.js} +0 -0
- /package/dist/web/assets/{rose-pine-C_-E2tF1.js → rose-pine-jp51ZUzi.js} +0 -0
- /package/dist/web/assets/{rose-pine-moon-BdvX3gdn.js → rose-pine-moon-Ff063yLj.js} +0 -0
- /package/dist/web/assets/{rosmsg-B6GhGpd5.js → rosmsg-Cyk7Il8z.js} +0 -0
- /package/dist/web/assets/{rotate-ccw-COXu_9oj.js → rotate-ccw-DnuPzJRE.js} +0 -0
- /package/dist/web/assets/{rust-DmC97M1-.js → rust-DRNM5epF.js} +0 -0
- /package/dist/web/assets/{sass-B0tJOHLM.js → sass-D_cB0-M1.js} +0 -0
- /package/dist/web/assets/{save-CtIGOjmx.js → save-DxonD4y1.js} +0 -0
- /package/dist/web/assets/{scala-n8zaFOXv.js → scala-Crl-1kKS.js} +0 -0
- /package/dist/web/assets/{scheme-BKD9ztBU.js → scheme-DCaWyEJ0.js} +0 -0
- /package/dist/web/assets/{sdbl-D8gB5-rS.js → sdbl-BbXNqwtX.js} +0 -0
- /package/dist/web/assets/{send-BlyNJAzy.js → send-B-t5Mz26.js} +0 -0
- /package/dist/web/assets/{shallow-DYo6goJ4.js → shallow-4zAfs2KW.js} +0 -0
- /package/dist/web/assets/{shellscript-BfXlf_Ao.js → shellscript-BAgksBhW.js} +0 -0
- /package/dist/web/assets/{shield-check-B0iGUiOK.js → shield-check-CdTiK1j2.js} +0 -0
- /package/dist/web/assets/{shield-off-BNLWBhcq.js → shield-off-DuetkXKM.js} +0 -0
- /package/dist/web/assets/{slack-dark-CylEddse.js → slack-dark-GB-ElUW_.js} +0 -0
- /package/dist/web/assets/{slack-ochin-w8wg8vuC.js → slack-ochin-tU6CFD3S.js} +0 -0
- /package/dist/web/assets/{smalltalk-hiAXA64u.js → smalltalk-DSVGUbtL.js} +0 -0
- /package/dist/web/assets/{snazzy-light-BwlV3Xty.js → snazzy-light-DZhi3PoS.js} +0 -0
- /package/dist/web/assets/{solarized-dark-vmNGdykz.js → solarized-dark-D6AMCco7.js} +0 -0
- /package/dist/web/assets/{solarized-light-DGv_0JXq.js → solarized-light-DepuTWSE.js} +0 -0
- /package/dist/web/assets/{solidity-Y7QSH0B1.js → solidity-CsxN618l.js} +0 -0
- /package/dist/web/assets/{splunk-BtgpLjHi.js → splunk-CF1m0Kkv.js} +0 -0
- /package/dist/web/assets/{sql-CRHYhOia.js → sql-DvyMDgrB.js} +0 -0
- /package/dist/web/assets/{ssh-config-DOqSs3au.js → ssh-config-a8sDo-Q8.js} +0 -0
- /package/dist/web/assets/{stylus-crCAEaBT.js → stylus-DCJ-6AjT.js} +0 -0
- /package/dist/web/assets/{swift-eE3rT7TC.js → swift-c-ZFxyPP.js} +0 -0
- /package/dist/web/assets/{synthwave-84-BWy14LBX.js → synthwave-84-9NPgBcuv.js} +0 -0
- /package/dist/web/assets/{system-verilog-DC0-DZM4.js → system-verilog-DPD02IOo.js} +0 -0
- /package/dist/web/assets/{systemd-to5p6N8I.js → systemd-BUr5HRtU.js} +0 -0
- /package/dist/web/assets/{table-Bbc783ko.js → table-FLU8ei8b.js} +0 -0
- /package/dist/web/assets/{talonscript-DoTcU8wm.js → talonscript-BNBQV5YJ.js} +0 -0
- /package/dist/web/assets/{tasl-cNZvUs95.js → tasl-BETjpSyu.js} +0 -0
- /package/dist/web/assets/{tcl-mZE8sZH8.js → tcl-Clp_AZiC.js} +0 -0
- /package/dist/web/assets/{terraform-CqHPpIfu.js → terraform-B0kZ0lim.js} +0 -0
- /package/dist/web/assets/{text-wrap-CBT4Gxtg.js → text-wrap-B05VGRa-.js} +0 -0
- /package/dist/web/assets/{tokyo-night-Tp2rTIZd.js → tokyo-night-oOJ0a7Dk.js} +0 -0
- /package/dist/web/assets/{toml-CU_vscgn.js → toml-DOPCSumy.js} +0 -0
- /package/dist/web/assets/{trash-2-Bk4yYlck.js → trash-2-CTXlTflF.js} +0 -0
- /package/dist/web/assets/{triangle-alert-B8EYecpe.js → triangle-alert-BRq0VAfd.js} +0 -0
- /package/dist/web/assets/{tsv-ik7iFB9D.js → tsv-D6qUGf84.js} +0 -0
- /package/dist/web/assets/{tsx-BMvvMKiv.js → tsx-B6qYhT6O.js} +0 -0
- /package/dist/web/assets/{turtle-DBqKCq9o.js → turtle-C0Rjzw73.js} +0 -0
- /package/dist/web/assets/{typescript-DXJDmMZZ.js → typescript-BiydShEu.js} +0 -0
- /package/dist/web/assets/{typespec-CBseCMtZ.js → typespec-DjmF6Aww.js} +0 -0
- /package/dist/web/assets/{typst-4oY25U9y.js → typst-CPuscfcL.js} +0 -0
- /package/dist/web/assets/{use-is-mobile-D1weanbj.js → use-is-mobile-b94q8RvF.js} +0 -0
- /package/dist/web/assets/{utils-BNRH507E.js → utils-C9OjCrou.js} +0 -0
- /package/dist/web/assets/{v-BXaZ_1oy.js → v-DE4vpLLQ.js} +0 -0
- /package/dist/web/assets/{vala-BImWJE7z.js → vala-CmUF2pS5.js} +0 -0
- /package/dist/web/assets/{vb-CLfj2_sy.js → vb-BvcRoX4b.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-_yyu5n32.js → vendor-xterm-K8kpLxdb.js} +0 -0
- /package/dist/web/assets/{verilog-BWa8Ed2b.js → verilog-BGIzyH3R.js} +0 -0
- /package/dist/web/assets/{vesper-BGj1cg6m.js → vesper-CG7IrHQQ.js} +0 -0
- /package/dist/web/assets/{vhdl-mByK7mlx.js → vhdl-DMSumomw.js} +0 -0
- /package/dist/web/assets/{viml-CugmlW5g.js → viml-Drt7AEmU.js} +0 -0
- /package/dist/web/assets/{vitesse-black-vPdpy9TL.js → vitesse-black-DmsjfN0b.js} +0 -0
- /package/dist/web/assets/{vitesse-dark-BuQK3dUh.js → vitesse-dark-Dl55_WeJ.js} +0 -0
- /package/dist/web/assets/{vitesse-light-B3nz1XL9.js → vitesse-light-Crbv9aGg.js} +0 -0
- /package/dist/web/assets/{vyper-DH_GTIHG.js → vyper-CB7psEJj.js} +0 -0
- /package/dist/web/assets/{wasm-DfVbVJlW.js → wasm-BY1tuM5m.js} +0 -0
- /package/dist/web/assets/{wasm-C-LF9GjX.js → wasm-Dck8KPgP.js} +0 -0
- /package/dist/web/assets/{wenyan-CzQkHyHx.js → wenyan-DhewQ68b.js} +0 -0
- /package/dist/web/assets/{wgsl-Du_M1DW9.js → wgsl-DlmiP456.js} +0 -0
- /package/dist/web/assets/{wikitext-BWN_w5S7.js → wikitext-cQCnqNgE.js} +0 -0
- /package/dist/web/assets/{wit-BR13v5HD.js → wit-S5MaCngB.js} +0 -0
- /package/dist/web/assets/{wolfram-BoXxp_Xl.js → wolfram-Bh8n_9zr.js} +0 -0
- /package/dist/web/assets/{x-nhriOX9o.js → x-YDu4m2Iq.js} +0 -0
- /package/dist/web/assets/{yaml-DpR_EF-d.js → yaml-BoK_17l9.js} +0 -0
- /package/dist/web/assets/{zenscript-C-EdUtUd.js → zenscript-DB3ZFwNJ.js} +0 -0
- /package/dist/web/assets/{zig-BD4eA5nU.js → zig-Bv1BWmfT.js} +0 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permanent Tunnel Manager entry point for the named tunnel: status display
|
|
3
|
+
* plus the actions that survive after the first-run popup is gone or was
|
|
4
|
+
* closed early. Uses its own `useNamedTunnelSetup()` instance — see that
|
|
5
|
+
* hook's docstring for why two instances stay in sync without a shared store.
|
|
6
|
+
*/
|
|
7
|
+
import { useState } from "react";
|
|
8
|
+
import { ExternalLink, Copy, Check, ShieldAlert, AlertTriangle } from "lucide-react";
|
|
9
|
+
import { toast } from "sonner";
|
|
10
|
+
import { namedTunnelApi } from "@/lib/api-named-tunnel";
|
|
11
|
+
import { copyToClipboard } from "@/lib/clipboard";
|
|
12
|
+
import { useNamedTunnelSetup } from "./use-named-tunnel-setup";
|
|
13
|
+
import { NamedTunnelSetupContent } from "./named-tunnel-setup-content";
|
|
14
|
+
import { namedTunnelCopy } from "./named-tunnel-copy";
|
|
15
|
+
|
|
16
|
+
export function NamedTunnelSection() {
|
|
17
|
+
const t = useNamedTunnelSetup();
|
|
18
|
+
const [confirmDisable, setConfirmDisable] = useState(false);
|
|
19
|
+
const [disabling, setDisabling] = useState(false);
|
|
20
|
+
const [copied, setCopied] = useState(false);
|
|
21
|
+
const c = namedTunnelCopy.section;
|
|
22
|
+
const status = t.status;
|
|
23
|
+
|
|
24
|
+
if (!status) return null; // still loading — avoid flashing empty controls
|
|
25
|
+
|
|
26
|
+
// Disabling the domain kills the connector that is serving this page, so the
|
|
27
|
+
// temporary URL that replaces it can never reach whoever pressed the button.
|
|
28
|
+
const servedByOwnHostname =
|
|
29
|
+
!!status.hostname && typeof window !== "undefined" && window.location.hostname === status.hostname;
|
|
30
|
+
|
|
31
|
+
// "ask-domain" is the popup's own opening question; the section skips it and
|
|
32
|
+
// shows a plain "Set up" button instead, since clicking that button already
|
|
33
|
+
// means "yes".
|
|
34
|
+
const inFlow = t.step.k !== "hidden" && t.step.k !== "ask-domain";
|
|
35
|
+
// Optional until the server route lands it — default to "on" so this never
|
|
36
|
+
// hides real functionality on a build that predates the field, but never
|
|
37
|
+
// reopens it for a genuine `false`.
|
|
38
|
+
const authEnabled = status.authEnabled ?? true;
|
|
39
|
+
// What is actually serving traffic, not just what was asked for — a failed
|
|
40
|
+
// named spawn falls back to quick while `mode` (the persisted request)
|
|
41
|
+
// still says "named".
|
|
42
|
+
const displayMode = status.liveMode ?? status.mode;
|
|
43
|
+
const certNeedsRelogin = status.certState === "invalid" || status.certState === "mismatch";
|
|
44
|
+
|
|
45
|
+
async function handleDisable() {
|
|
46
|
+
if (!confirmDisable) {
|
|
47
|
+
setConfirmDisable(true);
|
|
48
|
+
setTimeout(() => setConfirmDisable(false), 4000);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
setConfirmDisable(false);
|
|
52
|
+
setDisabling(true);
|
|
53
|
+
try {
|
|
54
|
+
await namedTunnelApi.disable();
|
|
55
|
+
toast.success("Đã chuyển về quick tunnel");
|
|
56
|
+
await t.refreshStatus();
|
|
57
|
+
} catch (e) {
|
|
58
|
+
toast.error(e instanceof Error ? e.message : "Không chuyển được về quick tunnel");
|
|
59
|
+
} finally {
|
|
60
|
+
setDisabling(false);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function copyHostname(hostname: string) {
|
|
65
|
+
const ok = await copyToClipboard(`https://${hostname}`);
|
|
66
|
+
if (!ok) { toast.error("Failed to copy URL"); return; }
|
|
67
|
+
setCopied(true);
|
|
68
|
+
setTimeout(() => setCopied(false), 2000);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div className="p-3 border-b border-border bg-surface space-y-3">
|
|
73
|
+
<div className="flex items-center gap-2">
|
|
74
|
+
<span className="text-sm font-medium text-text-primary">{c.title}</span>
|
|
75
|
+
<span className={`px-1.5 py-0.5 rounded text-[10px] font-medium uppercase tracking-wide ${
|
|
76
|
+
displayMode === "named" ? "bg-success/10 text-success" : "bg-surface-elevated text-text-secondary"
|
|
77
|
+
}`}>
|
|
78
|
+
{displayMode === "named" ? c.modeNamed : c.modeQuick}
|
|
79
|
+
</span>
|
|
80
|
+
{status.mode !== displayMode && (
|
|
81
|
+
<span className="text-[10px] text-text-subtle">({c.configuredAs(status.mode)})</span>
|
|
82
|
+
)}
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
{status.mode === "named" && status.hostname && (
|
|
86
|
+
<div className="flex items-center gap-1 text-xs">
|
|
87
|
+
<a href={`https://${status.hostname}`} target="_blank" rel="noopener noreferrer" className="flex-1 min-w-0 truncate text-primary hover:underline">
|
|
88
|
+
{status.hostname}
|
|
89
|
+
</a>
|
|
90
|
+
<button
|
|
91
|
+
onClick={() => copyHostname(status.hostname!)}
|
|
92
|
+
aria-label="Copy URL"
|
|
93
|
+
className="shrink-0 size-11 flex items-center justify-center rounded-md hover:bg-surface-elevated transition-colors"
|
|
94
|
+
>
|
|
95
|
+
{copied ? <Check className="size-3.5 text-success" /> : <Copy className="size-3.5 text-text-secondary" />}
|
|
96
|
+
</button>
|
|
97
|
+
<a
|
|
98
|
+
href={`https://${status.hostname}`} target="_blank" rel="noopener noreferrer"
|
|
99
|
+
className="shrink-0 size-11 flex items-center justify-center rounded-md hover:bg-surface-elevated transition-colors"
|
|
100
|
+
>
|
|
101
|
+
<ExternalLink className="size-3.5 text-text-secondary" />
|
|
102
|
+
</a>
|
|
103
|
+
</div>
|
|
104
|
+
)}
|
|
105
|
+
|
|
106
|
+
{status.tokenMasked && (
|
|
107
|
+
<p className="text-[10px] font-mono text-text-subtle">{c.tokenLabel}: {status.tokenMasked}</p>
|
|
108
|
+
)}
|
|
109
|
+
|
|
110
|
+
{status.tunnelWarning && (
|
|
111
|
+
<div className="flex items-center gap-2 rounded-md border border-warning/30 bg-warning/10 px-2.5 py-2 text-xs text-foreground">
|
|
112
|
+
<AlertTriangle className="size-3.5 text-warning shrink-0" />
|
|
113
|
+
{status.tunnelWarning}
|
|
114
|
+
</div>
|
|
115
|
+
)}
|
|
116
|
+
|
|
117
|
+
{certNeedsRelogin && !inFlow && (
|
|
118
|
+
<div className="flex items-center gap-2 rounded-md border border-warning/30 bg-warning/10 px-2.5 py-2 text-xs text-foreground">
|
|
119
|
+
<ShieldAlert className="size-3.5 text-warning shrink-0" />
|
|
120
|
+
{status.certState === "mismatch" ? c.certMismatch : c.certInvalid}
|
|
121
|
+
</div>
|
|
122
|
+
)}
|
|
123
|
+
|
|
124
|
+
{inFlow ? (
|
|
125
|
+
<NamedTunnelSetupContent step={t.step} t={t} />
|
|
126
|
+
) : !authEnabled ? (
|
|
127
|
+
<p className="text-xs text-text-secondary">{c.authDisabled}</p>
|
|
128
|
+
) : (
|
|
129
|
+
<div className="flex flex-wrap gap-2">
|
|
130
|
+
{status.mode === "quick" && (
|
|
131
|
+
<button
|
|
132
|
+
onClick={t.answerYes}
|
|
133
|
+
className="min-h-11 px-3 py-2 rounded-md bg-primary text-primary-foreground text-xs font-medium hover:bg-primary/90 transition-colors"
|
|
134
|
+
>
|
|
135
|
+
{c.setup}
|
|
136
|
+
</button>
|
|
137
|
+
)}
|
|
138
|
+
{status.mode === "named" && (
|
|
139
|
+
<button
|
|
140
|
+
onClick={handleDisable}
|
|
141
|
+
disabled={disabling || servedByOwnHostname}
|
|
142
|
+
title={servedByOwnHostname ? c.disableSelfCut : undefined}
|
|
143
|
+
className={`min-h-11 px-3 py-2 rounded-md text-xs transition-colors disabled:opacity-50 ${
|
|
144
|
+
confirmDisable ? "bg-destructive/15 text-destructive" : "border border-border text-text-secondary hover:bg-surface-elevated"
|
|
145
|
+
}`}
|
|
146
|
+
>
|
|
147
|
+
{confirmDisable ? c.disableConfirm : c.disable}
|
|
148
|
+
</button>
|
|
149
|
+
)}
|
|
150
|
+
</div>
|
|
151
|
+
)}
|
|
152
|
+
{/* Turning the domain off kills the connector serving this very page, so
|
|
153
|
+
the replacement link would never reach the user who pressed it. */}
|
|
154
|
+
{status.mode === "named" && servedByOwnHostname && (
|
|
155
|
+
<p className="text-[11px] text-text-secondary leading-relaxed">{c.disableSelfCut}</p>
|
|
156
|
+
)}
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Step content switch — one card per step. Both the popup shell and the
|
|
3
|
+
* Tunnel Manager section render this, so it never assumes it is inside a
|
|
4
|
+
* dialog or a sheet (no close button of its own; the shell owns dismissal).
|
|
5
|
+
*/
|
|
6
|
+
import { Loader2, AlertCircle } from "lucide-react";
|
|
7
|
+
import type { Step } from "./named-tunnel-step-reducer";
|
|
8
|
+
import type { UseNamedTunnelSetup } from "./use-named-tunnel-setup";
|
|
9
|
+
import { namedTunnelCopy } from "./named-tunnel-copy";
|
|
10
|
+
import { NamedTunnelLoginStep } from "./named-tunnel-login-step";
|
|
11
|
+
import { NamedTunnelHostnameField } from "./named-tunnel-hostname-field";
|
|
12
|
+
|
|
13
|
+
const primaryBtn = "w-full min-h-11 py-3 rounded-lg bg-primary text-primary-foreground text-sm font-medium hover:bg-primary/90 transition-colors disabled:opacity-50 disabled:pointer-events-none";
|
|
14
|
+
const secondaryBtn = "w-full min-h-11 py-3 rounded-lg border border-border text-sm text-text-secondary hover:bg-surface-elevated transition-colors";
|
|
15
|
+
|
|
16
|
+
interface Props {
|
|
17
|
+
step: Step;
|
|
18
|
+
t: UseNamedTunnelSetup;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function NamedTunnelSetupContent({ step, t }: Props) {
|
|
22
|
+
switch (step.k) {
|
|
23
|
+
case "hidden":
|
|
24
|
+
return null;
|
|
25
|
+
|
|
26
|
+
case "ask-domain": {
|
|
27
|
+
const c = namedTunnelCopy.askDomain;
|
|
28
|
+
return (
|
|
29
|
+
<div className="space-y-4">
|
|
30
|
+
<div>
|
|
31
|
+
<h2 className="text-base font-semibold text-foreground">{c.title}</h2>
|
|
32
|
+
<p className="mt-1 text-sm text-text-secondary leading-relaxed">{c.body}</p>
|
|
33
|
+
</div>
|
|
34
|
+
<div className="flex gap-2">
|
|
35
|
+
<button type="button" onClick={t.answerNo} className={secondaryBtn}>{c.no}</button>
|
|
36
|
+
<button type="button" onClick={t.answerYes} className={primaryBtn}>{c.yes}</button>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
case "no-domain": {
|
|
43
|
+
const c = namedTunnelCopy.noDomain;
|
|
44
|
+
return (
|
|
45
|
+
<div className="space-y-4">
|
|
46
|
+
<div>
|
|
47
|
+
<h2 className="text-base font-semibold text-foreground">{c.title}</h2>
|
|
48
|
+
<p className="mt-1 text-sm text-text-secondary leading-relaxed">{c.body}</p>
|
|
49
|
+
</div>
|
|
50
|
+
<button type="button" onClick={t.close} className={primaryBtn}>{c.close}</button>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
case "login-wait":
|
|
56
|
+
return <NamedTunnelLoginStep url={step.url} slow={step.slow} onCancel={t.cancelLogin} />;
|
|
57
|
+
|
|
58
|
+
case "login-timeout": {
|
|
59
|
+
const c = namedTunnelCopy.timeout;
|
|
60
|
+
return (
|
|
61
|
+
<div className="space-y-4">
|
|
62
|
+
<div>
|
|
63
|
+
<h2 className="text-base font-semibold text-foreground">{c.title}</h2>
|
|
64
|
+
<p className="mt-1 text-sm text-text-secondary leading-relaxed">{c.body}</p>
|
|
65
|
+
</div>
|
|
66
|
+
<button type="button" onClick={t.retryLogin} className={primaryBtn}>{c.retry}</button>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
case "login-cancelled": {
|
|
72
|
+
const c = namedTunnelCopy.cancelled;
|
|
73
|
+
return (
|
|
74
|
+
<div className="space-y-4">
|
|
75
|
+
<div>
|
|
76
|
+
<h2 className="text-base font-semibold text-foreground">{c.title}</h2>
|
|
77
|
+
<p className="mt-1 text-sm text-text-secondary leading-relaxed">{c.body}</p>
|
|
78
|
+
</div>
|
|
79
|
+
<button type="button" onClick={t.retryLogin} className={primaryBtn}>{c.retry}</button>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
case "confirm-zone": {
|
|
85
|
+
const c = namedTunnelCopy.confirmZone;
|
|
86
|
+
return (
|
|
87
|
+
<div className="space-y-4">
|
|
88
|
+
<div>
|
|
89
|
+
<h2 className="text-base font-semibold text-foreground">{c.title}</h2>
|
|
90
|
+
<p className="mt-1 text-sm text-text-secondary leading-relaxed">{c.body(step.zone)}</p>
|
|
91
|
+
</div>
|
|
92
|
+
<div className="flex gap-2">
|
|
93
|
+
<button type="button" onClick={t.startOver} className={secondaryBtn}>{c.startOver}</button>
|
|
94
|
+
<button type="button" onClick={t.confirmZone} className={primaryBtn}>{c.confirm}</button>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
case "needs-relogin": {
|
|
101
|
+
const c = namedTunnelCopy.needsRelogin;
|
|
102
|
+
return (
|
|
103
|
+
<div className="space-y-4">
|
|
104
|
+
<div>
|
|
105
|
+
<h2 className="text-base font-semibold text-foreground">{c.title}</h2>
|
|
106
|
+
<p className="mt-1 text-sm text-text-secondary leading-relaxed">{step.message}</p>
|
|
107
|
+
</div>
|
|
108
|
+
<button type="button" onClick={t.requestRelogin} className={primaryBtn}>{c.action}</button>
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
case "choose-hostname": {
|
|
114
|
+
const c = namedTunnelCopy.hostname;
|
|
115
|
+
return (
|
|
116
|
+
<div className="space-y-4">
|
|
117
|
+
<h2 className="text-base font-semibold text-foreground">{c.title}</h2>
|
|
118
|
+
<NamedTunnelHostnameField
|
|
119
|
+
zone={step.zone}
|
|
120
|
+
prefix={step.prefix}
|
|
121
|
+
error={step.error}
|
|
122
|
+
onChange={t.setHostnamePrefix}
|
|
123
|
+
/>
|
|
124
|
+
<button
|
|
125
|
+
type="button"
|
|
126
|
+
onClick={t.submitHostname}
|
|
127
|
+
disabled={!step.prefix || !!step.error}
|
|
128
|
+
className={primaryBtn}
|
|
129
|
+
>
|
|
130
|
+
{c.submit}
|
|
131
|
+
</button>
|
|
132
|
+
</div>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
case "applying":
|
|
137
|
+
return (
|
|
138
|
+
<div className="space-y-4 py-4">
|
|
139
|
+
<div className="flex items-center gap-2 text-sm text-foreground">
|
|
140
|
+
<Loader2 className="size-4 animate-spin text-primary" />
|
|
141
|
+
{step.message}
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
case "done": {
|
|
147
|
+
const c = namedTunnelCopy.done;
|
|
148
|
+
return (
|
|
149
|
+
<div className="space-y-4">
|
|
150
|
+
<div>
|
|
151
|
+
<h2 className="text-base font-semibold text-foreground">{c.title}</h2>
|
|
152
|
+
<p className="mt-1 text-sm text-text-secondary break-all">{c.body(step.hostname)}</p>
|
|
153
|
+
</div>
|
|
154
|
+
<button type="button" onClick={t.close} className={primaryBtn}>{c.close}</button>
|
|
155
|
+
</div>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
case "pending": {
|
|
160
|
+
const c = namedTunnelCopy.pending;
|
|
161
|
+
return (
|
|
162
|
+
<div className="space-y-4">
|
|
163
|
+
<div>
|
|
164
|
+
<h2 className="text-base font-semibold text-foreground">{c.title}</h2>
|
|
165
|
+
<p className="mt-1 text-sm text-text-secondary leading-relaxed">{step.message}</p>
|
|
166
|
+
<p className="mt-2 text-xs font-mono text-text-subtle bg-surface-elevated rounded px-2 py-1.5 inline-block">
|
|
167
|
+
ppm restart
|
|
168
|
+
</p>
|
|
169
|
+
</div>
|
|
170
|
+
<button type="button" onClick={t.close} className={primaryBtn}>{c.close}</button>
|
|
171
|
+
</div>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
case "error": {
|
|
176
|
+
const c = namedTunnelCopy.error;
|
|
177
|
+
return (
|
|
178
|
+
<div className="space-y-4">
|
|
179
|
+
<div className="flex items-start gap-2">
|
|
180
|
+
<AlertCircle className="size-4 text-destructive shrink-0 mt-0.5" />
|
|
181
|
+
<div>
|
|
182
|
+
<h2 className="text-base font-semibold text-foreground">{c.title}</h2>
|
|
183
|
+
<p className="mt-1 text-sm text-text-secondary leading-relaxed">{step.message}</p>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
<div className="flex gap-2">
|
|
187
|
+
<button type="button" onClick={t.close} className={secondaryBtn}>{c.close}</button>
|
|
188
|
+
<button type="button" onClick={t.retryLogin} className={primaryBtn}>{c.retry}</button>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
default:
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mount point for the first-run named-tunnel flow: a centred dialog on
|
|
3
|
+
* desktop, a bottom sheet on mobile (`docs/design-guidelines.md` — dialogs
|
|
4
|
+
* must never be desktop-only). Closing (backdrop, swipe, X) only hides this
|
|
5
|
+
* popup instance — it does not call `dismiss()` and does not cancel an
|
|
6
|
+
* in-progress login; the Tunnel Manager section is the permanent re-entry
|
|
7
|
+
* point, so nothing is lost.
|
|
8
|
+
*/
|
|
9
|
+
import { useState } from "react";
|
|
10
|
+
import { X } from "lucide-react";
|
|
11
|
+
import { useIsMobile } from "@/hooks/use-is-mobile";
|
|
12
|
+
import { BottomSheet } from "@/components/ui/mobile-bottom-sheet";
|
|
13
|
+
import { useNamedTunnelSetup } from "./use-named-tunnel-setup";
|
|
14
|
+
import { NamedTunnelSetupContent } from "./named-tunnel-setup-content";
|
|
15
|
+
|
|
16
|
+
export function NamedTunnelSetupPopup() {
|
|
17
|
+
const t = useNamedTunnelSetup();
|
|
18
|
+
const isMobile = useIsMobile();
|
|
19
|
+
const [closedByUser, setClosedByUser] = useState(false);
|
|
20
|
+
|
|
21
|
+
const visible = t.step.k !== "hidden" && !closedByUser;
|
|
22
|
+
if (!visible) return null;
|
|
23
|
+
|
|
24
|
+
const handleClose = () => setClosedByUser(true);
|
|
25
|
+
|
|
26
|
+
if (isMobile) {
|
|
27
|
+
return (
|
|
28
|
+
<BottomSheet open={visible} onClose={handleClose} zIndex={45}>
|
|
29
|
+
<div className="px-4 pb-4">
|
|
30
|
+
<NamedTunnelSetupContent step={t.step} t={t} />
|
|
31
|
+
</div>
|
|
32
|
+
</BottomSheet>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<>
|
|
38
|
+
<div className="fixed inset-0 z-[45] bg-black/40" onClick={handleClose} />
|
|
39
|
+
<div
|
|
40
|
+
className="fixed z-[45] top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-full max-w-md max-h-[85vh] overflow-y-auto rounded-xl bg-popover text-popover-foreground border border-border shadow-2xl p-5"
|
|
41
|
+
onClick={(e) => e.stopPropagation()}
|
|
42
|
+
>
|
|
43
|
+
<button
|
|
44
|
+
type="button"
|
|
45
|
+
onClick={handleClose}
|
|
46
|
+
aria-label="Close"
|
|
47
|
+
className="absolute right-3 top-3 size-11 flex items-center justify-center rounded-md hover:bg-surface-elevated transition-colors"
|
|
48
|
+
>
|
|
49
|
+
<X className="size-4" />
|
|
50
|
+
</button>
|
|
51
|
+
<div className="pr-8">
|
|
52
|
+
<NamedTunnelSetupContent step={t.step} t={t} />
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure step machine for the named-tunnel first-run flow. No side effects here
|
|
3
|
+
* (no fetch, no window events) — `use-named-tunnel-setup.ts` owns those and
|
|
4
|
+
* dispatches actions into `reduceStep`. Kept side-effect-free so the whole
|
|
5
|
+
* transition table is unit-testable without mocking the network or WS.
|
|
6
|
+
*/
|
|
7
|
+
import type { LoginState, NamedTunnelStatus } from "@/lib/api-named-tunnel";
|
|
8
|
+
import { namedTunnelCopy } from "./named-tunnel-copy";
|
|
9
|
+
import { DEFAULT_HOSTNAME_PREFIX } from "./hostname-validation";
|
|
10
|
+
|
|
11
|
+
export type Step =
|
|
12
|
+
| { k: "hidden" }
|
|
13
|
+
| { k: "ask-domain" }
|
|
14
|
+
| { k: "no-domain" }
|
|
15
|
+
| { k: "login-wait"; url: string | null; slow: boolean }
|
|
16
|
+
| { k: "login-timeout" }
|
|
17
|
+
| { k: "login-cancelled" }
|
|
18
|
+
| { k: "confirm-zone"; zone: string }
|
|
19
|
+
| { k: "needs-relogin"; message: string }
|
|
20
|
+
| { k: "choose-hostname"; zone: string; prefix: string; error?: string }
|
|
21
|
+
| { k: "applying"; zone: string; prefix: string; message: string }
|
|
22
|
+
| { k: "done"; hostname: string }
|
|
23
|
+
| { k: "pending"; hostname: string; message: string }
|
|
24
|
+
| { k: "error"; message: string };
|
|
25
|
+
|
|
26
|
+
export type Action =
|
|
27
|
+
| { type: "status"; status: NamedTunnelStatus }
|
|
28
|
+
| { type: "answer-yes" }
|
|
29
|
+
| { type: "answer-no" }
|
|
30
|
+
| { type: "login-url"; url: string }
|
|
31
|
+
| { type: "login-state"; state: LoginState; message?: string | null }
|
|
32
|
+
| { type: "cancel" }
|
|
33
|
+
| { type: "retry" }
|
|
34
|
+
| { type: "zone-loaded"; zone: string }
|
|
35
|
+
| { type: "zone-error"; message: string }
|
|
36
|
+
| { type: "confirm-zone" }
|
|
37
|
+
| { type: "start-over" }
|
|
38
|
+
| { type: "hostname-prefix"; prefix: string; error?: string }
|
|
39
|
+
| { type: "submit" }
|
|
40
|
+
| { type: "setup-step"; message: string }
|
|
41
|
+
| { type: "setup-done"; hostname: string }
|
|
42
|
+
| { type: "setup-pending"; hostname: string; message: string }
|
|
43
|
+
| { type: "setup-error"; message: string }
|
|
44
|
+
| { type: "needs-relogin"; message: string }
|
|
45
|
+
| { type: "close" };
|
|
46
|
+
|
|
47
|
+
/** First step to render once `/status` has been read on mount. */
|
|
48
|
+
export function initialStepFromStatus(status: NamedTunnelStatus): Step {
|
|
49
|
+
// `authEnabled` is optional until the server route lands it — a missing
|
|
50
|
+
// value must not silently reopen the popup on an auth-disabled install, so
|
|
51
|
+
// default to "on" only for backward compatibility, never to hide a real
|
|
52
|
+
// `false`.
|
|
53
|
+
const authEnabled = status.authEnabled ?? true;
|
|
54
|
+
if (!authEnabled) {
|
|
55
|
+
return { k: "hidden" };
|
|
56
|
+
}
|
|
57
|
+
if (status.certState === "invalid" || status.certState === "mismatch") {
|
|
58
|
+
return {
|
|
59
|
+
k: "needs-relogin",
|
|
60
|
+
message: status.certState === "mismatch"
|
|
61
|
+
? namedTunnelCopy.needsRelogin.certMismatch
|
|
62
|
+
: namedTunnelCopy.needsRelogin.certInvalid,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (status.mode !== "quick" || status.dismissed) {
|
|
66
|
+
return { k: "hidden" };
|
|
67
|
+
}
|
|
68
|
+
return stepFromLoginState(status.login.state, status.login.url, status.login.message);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Steps a later `/status` refresh is allowed to recompute. Once the user has
|
|
73
|
+
* committed past login (confirm-zone, choose-hostname, applying) or reached a
|
|
74
|
+
* terminal card (done, pending, no-domain), a stale or lagging status
|
|
75
|
+
* snapshot must not silently reset that progress — only these "not yet
|
|
76
|
+
* committed" steps re-derive from a fresh fetch.
|
|
77
|
+
*/
|
|
78
|
+
const STATUS_RESETTABLE: ReadonlySet<Step["k"]> = new Set([
|
|
79
|
+
"hidden", "ask-domain", "login-wait", "login-timeout", "login-cancelled", "needs-relogin", "error",
|
|
80
|
+
]);
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Steps that are actually waiting on a zone lookup. A login session's
|
|
84
|
+
* `state` stays "success" long after the moment it fired — it is not reset
|
|
85
|
+
* to "idle" — so a later, unrelated `/status` refresh (after setup-done, or
|
|
86
|
+
* on mount of an already-configured install) can still read "success" and
|
|
87
|
+
* ask for the zone again. Without this gate that stray `zone-loaded` would
|
|
88
|
+
* silently replace a "done" card with "confirm-zone", or reopen the hidden
|
|
89
|
+
* popup of a finished install straight into it. Exported so the hook can
|
|
90
|
+
* skip the redundant `/zone` call at the source instead of only discarding
|
|
91
|
+
* its result here.
|
|
92
|
+
*/
|
|
93
|
+
export const ZONE_EXPECTING_STEPS: ReadonlySet<Step["k"]> = new Set(["login-wait", "needs-relogin"]);
|
|
94
|
+
|
|
95
|
+
function stepFromLoginState(state: LoginState, url: string | null, message: string | null): Step {
|
|
96
|
+
switch (state) {
|
|
97
|
+
case "waiting":
|
|
98
|
+
return { k: "login-wait", url, slow: false };
|
|
99
|
+
case "slow":
|
|
100
|
+
return { k: "login-wait", url, slow: true };
|
|
101
|
+
case "timeout":
|
|
102
|
+
return { k: "login-timeout" };
|
|
103
|
+
case "cancelled":
|
|
104
|
+
return { k: "login-cancelled" };
|
|
105
|
+
case "error":
|
|
106
|
+
return { k: "error", message: message ?? namedTunnelCopy.error.title };
|
|
107
|
+
case "success":
|
|
108
|
+
// Zone lookup is a hook-level side effect triggered right after this;
|
|
109
|
+
// the spinner stays on the login step until `zone-loaded` arrives.
|
|
110
|
+
return { k: "login-wait", url, slow: false };
|
|
111
|
+
case "idle":
|
|
112
|
+
default:
|
|
113
|
+
return { k: "ask-domain" };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function reduceStep(step: Step, action: Action): Step {
|
|
118
|
+
switch (action.type) {
|
|
119
|
+
case "status":
|
|
120
|
+
return STATUS_RESETTABLE.has(step.k) ? initialStepFromStatus(action.status) : step;
|
|
121
|
+
|
|
122
|
+
case "answer-yes":
|
|
123
|
+
return { k: "login-wait", url: null, slow: false };
|
|
124
|
+
|
|
125
|
+
case "answer-no":
|
|
126
|
+
return { k: "no-domain" };
|
|
127
|
+
|
|
128
|
+
case "login-url":
|
|
129
|
+
return step.k === "login-wait"
|
|
130
|
+
? { ...step, url: action.url }
|
|
131
|
+
: { k: "login-wait", url: action.url, slow: false };
|
|
132
|
+
|
|
133
|
+
case "login-state":
|
|
134
|
+
return stepFromLoginState(action.state, step.k === "login-wait" ? step.url : null, action.message ?? null);
|
|
135
|
+
|
|
136
|
+
case "cancel":
|
|
137
|
+
return { k: "login-cancelled" };
|
|
138
|
+
|
|
139
|
+
case "retry":
|
|
140
|
+
return { k: "login-wait", url: null, slow: false };
|
|
141
|
+
|
|
142
|
+
case "zone-loaded":
|
|
143
|
+
return ZONE_EXPECTING_STEPS.has(step.k) ? { k: "confirm-zone", zone: action.zone } : step;
|
|
144
|
+
|
|
145
|
+
case "zone-error":
|
|
146
|
+
return ZONE_EXPECTING_STEPS.has(step.k) ? { k: "error", message: action.message } : step;
|
|
147
|
+
|
|
148
|
+
case "confirm-zone":
|
|
149
|
+
return step.k === "confirm-zone"
|
|
150
|
+
? { k: "choose-hostname", zone: step.zone, prefix: DEFAULT_HOSTNAME_PREFIX }
|
|
151
|
+
: step;
|
|
152
|
+
|
|
153
|
+
case "start-over":
|
|
154
|
+
return { k: "ask-domain" };
|
|
155
|
+
|
|
156
|
+
case "hostname-prefix":
|
|
157
|
+
return step.k === "choose-hostname"
|
|
158
|
+
? { ...step, prefix: action.prefix, error: action.error }
|
|
159
|
+
: step;
|
|
160
|
+
|
|
161
|
+
case "submit":
|
|
162
|
+
return step.k === "choose-hostname"
|
|
163
|
+
? { k: "applying", zone: step.zone, prefix: step.prefix, message: namedTunnelCopy.applying.title }
|
|
164
|
+
: step;
|
|
165
|
+
|
|
166
|
+
case "setup-step":
|
|
167
|
+
return step.k === "applying" ? { ...step, message: action.message } : step;
|
|
168
|
+
|
|
169
|
+
case "setup-done":
|
|
170
|
+
return { k: "done", hostname: action.hostname };
|
|
171
|
+
|
|
172
|
+
case "setup-pending":
|
|
173
|
+
return { k: "pending", hostname: action.hostname, message: action.message };
|
|
174
|
+
|
|
175
|
+
case "setup-error":
|
|
176
|
+
// Route back to the hostname field with the reason inline — losing the
|
|
177
|
+
// typed prefix here would make the user re-type it for a typo-sized fix.
|
|
178
|
+
return step.k === "applying"
|
|
179
|
+
? { k: "choose-hostname", zone: step.zone, prefix: step.prefix, error: action.message }
|
|
180
|
+
: { k: "error", message: action.message };
|
|
181
|
+
|
|
182
|
+
case "needs-relogin":
|
|
183
|
+
return { k: "needs-relogin", message: action.message };
|
|
184
|
+
|
|
185
|
+
case "close":
|
|
186
|
+
return { k: "hidden" };
|
|
187
|
+
|
|
188
|
+
default:
|
|
189
|
+
return step;
|
|
190
|
+
}
|
|
191
|
+
}
|