@hienlh/ppm 0.18.12 → 0.18.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (532) hide show
  1. package/AGENTS.md +17 -5
  2. package/CHANGELOG.md +22 -0
  3. package/CLAUDE.md +3 -0
  4. package/README.md +6 -6
  5. package/assets/skills/ppm/SKILL.md +1 -1
  6. package/assets/skills/ppm/references/http-api.md +19 -1
  7. package/dist/web/assets/{adaptive-context-menu-DGCKKeTy.js → adaptive-context-menu-CbgPYQmj.js} +1 -1
  8. package/dist/web/assets/{ai-resource-editor-BOHHTTe7.js → ai-resource-editor-unM2HNmg.js} +1 -1
  9. package/dist/web/assets/{ai-settings-section-BigC_nZR.js → ai-settings-section-CdktdrwF.js} +1 -1
  10. package/dist/web/assets/{angular-html-BYPaydvh.js → angular-html-DcpbdcNG.js} +1 -1
  11. package/dist/web/assets/{angular-ts-Bb4AMKlk.js → angular-ts-Bv_WIk34.js} +1 -1
  12. package/dist/web/assets/api-client-BogqsFna.js +1 -0
  13. package/dist/web/assets/{api-settings-Bd3M4YpI.js → api-settings-BdCtex9i.js} +1 -1
  14. package/dist/web/assets/api-settings-DfXViPKz.js +1 -0
  15. package/dist/web/assets/{api-themes-Cpx419SL.js → api-themes-pRRoLvgD.js} +1 -1
  16. package/dist/web/assets/{apl-DB2VjFCS.js → apl-D5_lLszu.js} +1 -1
  17. package/dist/web/assets/architecture-PBZL5I3N-BzFm9ELu.js +1 -0
  18. package/dist/web/assets/{astro-BeoJdVpk.js → astro-CBHwddYL.js} +1 -1
  19. package/dist/web/assets/{audio-preview-BgFuTn-0.js → audio-preview-BD1iDovf.js} +1 -1
  20. package/dist/web/assets/{blade-Cf2q1sPf.js → blade-DGe1d2Pq.js} +1 -1
  21. package/dist/web/assets/{bsl-W1kOaNpu.js → bsl-2lyAzRJA.js} +1 -1
  22. package/dist/web/assets/{button-5zTrkEoN.js → button-2WCAS8dI.js} +1 -1
  23. package/dist/web/assets/{cairo-BoAZFcje.js → cairo-DjzZeJrq.js} +1 -1
  24. package/dist/web/assets/chat-tab-DzK8LGti.js +15 -0
  25. package/dist/web/assets/{cobol-B0Nm7RXj.js → cobol-cC3XIuAJ.js} +1 -1
  26. package/dist/web/assets/code-editor-CuMfPN9X.js +10 -0
  27. package/dist/web/assets/{coffee-BakMn3on.js → coffee-4eGboVoU.js} +1 -1
  28. package/dist/web/assets/{conflict-editor-BUs5k9q_.js → conflict-editor-DdJag4QK.js} +1 -1
  29. package/dist/web/assets/{context-menu-Bq92km4s.js → context-menu-BO1c9jKy.js} +1 -1
  30. package/dist/web/assets/{cpp-BRAJQHK2.js → cpp-DF9_G-OU.js} +1 -1
  31. package/dist/web/assets/{crystal-kqqO3zkK.js → crystal-OavZlzcm.js} +1 -1
  32. package/dist/web/assets/{csv-preview-ByoDgLAZ.js → csv-preview-DnXwouF3.js} +1 -1
  33. package/dist/web/assets/{data-grid-overlay-editor-Brkf9z41.js → data-grid-overlay-editor-B9Gpjm3l.js} +1 -1
  34. package/dist/web/assets/{database-viewer-Btc3h8Yu.js → database-viewer-Dk8oGyZx.js} +1 -1
  35. package/dist/web/assets/{dialog-DwtGlowE.js → dialog-B-l2ZxVm.js} +1 -1
  36. package/dist/web/assets/{diff-viewer-CZaDnR4w.js → diff-viewer-eaUBjLCH.js} +1 -1
  37. package/dist/web/assets/{docx-preview-DAD_vg59.js → docx-preview-DAdHPlhZ.js} +1 -1
  38. package/dist/web/assets/{edge-Cq1ZKZuE.js → edge-TzYh8OlN.js} +1 -1
  39. package/dist/web/assets/{edit-diff-preview-B_VE7ppQ.js → edit-diff-preview-DlwP3UIU.js} +1 -1
  40. package/dist/web/assets/{elixir-BM_JoJRk.js → elixir-Cy3RhKKH.js} +1 -1
  41. package/dist/web/assets/{elm-Dw7oO08Y.js → elm-BTBZdweK.js} +1 -1
  42. package/dist/web/assets/{erb-CfKOGAfk.js → erb-dv1mI0y4.js} +1 -1
  43. package/dist/web/assets/{erlang-DlDmGVeE.js → erlang-DjeiDrkl.js} +1 -1
  44. package/dist/web/assets/{esm-DGAP0GFh.js → esm-FRwvcesu.js} +1 -1
  45. package/dist/web/assets/explorer-body-DkCkSVrN.js +2 -0
  46. package/dist/web/assets/explorer-window-content-MsnTVngu.js +1 -0
  47. package/dist/web/assets/{extension-store-Cpfh2vMm.js → extension-store-DUaZINyC.js} +1 -1
  48. package/dist/web/assets/{extension-webview-B2OnjuCu.js → extension-webview-W0qRfaAU.js} +1 -1
  49. package/dist/web/assets/{file-store-aOERIEo-.js → file-store-yReVbR8q.js} +1 -1
  50. package/dist/web/assets/{fortran-fixed-form-XnAhQWxS.js → fortran-fixed-form-BCH9DAIJ.js} +1 -1
  51. package/dist/web/assets/{fsharp-CdNvy0PG.js → fsharp-C93NYKYD.js} +1 -1
  52. package/dist/web/assets/{gdresource-DxuG5i8i.js → gdresource-BcIEE2eX.js} +1 -1
  53. package/dist/web/assets/{git-commit-3lMonsur.js → git-commit-BVjlXEy8.js} +1 -1
  54. package/dist/web/assets/{git-log-panel-Co0PBPHC.js → git-log-panel-2_4HuP47.js} +1 -1
  55. package/dist/web/assets/{git-rebase-N8Z9kIMf.js → git-rebase-Bj_21B1V.js} +1 -1
  56. package/dist/web/assets/gitGraph-HDMCJU4V-B72vcb2r.js +1 -0
  57. package/dist/web/assets/glide-data-grid-B0IY6n_Q.js +138 -0
  58. package/dist/web/assets/{glimmer-js-Dp9OXiib.js → glimmer-js-C20yj4Zv.js} +1 -1
  59. package/dist/web/assets/{glimmer-ts-CDVKBcDj.js → glimmer-ts-ipbYC7kh.js} +1 -1
  60. package/dist/web/assets/{glsl-DPJxI4us.js → glsl-Dovazu3t.js} +1 -1
  61. package/dist/web/assets/{graphql-BrFhaQQl.js → graphql-DpMlM7hC.js} +1 -1
  62. package/dist/web/assets/{group-chat-tab-rOd8J8GC.js → group-chat-tab-DRLDHOp6.js} +1 -1
  63. package/dist/web/assets/{hack-BzXbDMlA.js → hack-gc7LCBuV.js} +1 -1
  64. package/dist/web/assets/{haml-CPpkX0s5.js → haml-vtlFm9gm.js} +1 -1
  65. package/dist/web/assets/{handlebars-BqrApy52.js → handlebars-DGKhpCji.js} +1 -1
  66. package/dist/web/assets/{html-DmjUl-OA.js → html-DvfhQbXb.js} +1 -1
  67. package/dist/web/assets/{html-derivative-Cnd6XFR5.js → html-derivative-C3oTSSCN.js} +1 -1
  68. package/dist/web/assets/{http-DMLWYun2.js → http-SG6zLTo7.js} +1 -1
  69. package/dist/web/assets/{hurl-CKkCVxbj.js → hurl-BWXsYlqW.js} +1 -1
  70. package/dist/web/assets/{hxml-CAx19TtQ.js → hxml-DUdMzaoh.js} +1 -1
  71. package/dist/web/assets/{image-preview-DHUoylQ1.js → image-preview-DxgFOV1T.js} +1 -1
  72. package/dist/web/assets/index-CBn4SOoT.js +52 -0
  73. package/dist/web/assets/index-DWpNR3nB.css +2 -0
  74. package/dist/web/assets/info-3K5VOQVL-3irPxRK_.js +1 -0
  75. package/dist/web/assets/{input-DcEk7mA3.js → input-DuAF-Stj.js} +1 -1
  76. package/dist/web/assets/{jinja-BmB9YN9l.js → jinja-955w9RKM.js} +1 -1
  77. package/dist/web/assets/{jison-BaVsKKpw.js → jison-WWfqPo50.js} +1 -1
  78. package/dist/web/assets/{julia-BgVBLveX.js → julia-BFrfnaNl.js} +1 -1
  79. package/dist/web/assets/{just-C2ENIbl9.js → just-BrZdyR_I.js} +1 -1
  80. package/dist/web/assets/{keybindings-store-BGIyqXHI.js → keybindings-store-0Wqfa7Qp.js} +1 -1
  81. package/dist/web/assets/keybindings-store-d54pv2NK.js +1 -0
  82. package/dist/web/assets/{latex-BiDIWxKL.js → latex-CwtPPASD.js} +1 -1
  83. package/dist/web/assets/{liquid-NxpapreE.js → liquid-CYZuvDDd.js} +1 -1
  84. package/dist/web/assets/{lua-DVepQvwH.js → lua-BV095ZyY.js} +1 -1
  85. package/dist/web/assets/markdown-renderer-BTS8ifdu.js +1 -0
  86. package/dist/web/assets/{markdown-renderer-DlcDhgrF.js → markdown-renderer-CnRcKK3d.js} +3 -3
  87. package/dist/web/assets/{marko-CJ2606Xl.js → marko-CNeljZ1C.js} +1 -1
  88. package/dist/web/assets/{mdc-D2bjqclE.js → mdc-JfGapShy.js} +1 -1
  89. package/dist/web/assets/{media-url-H17XJF-I.js → media-url-Bm4PsduE.js} +1 -1
  90. package/dist/web/assets/{mobile-bottom-sheet-g-r2hCFa.js → mobile-bottom-sheet-M5iZDX7y.js} +1 -1
  91. package/dist/web/assets/mobile-explorer-sheet-BqK2-WuN.js +1 -0
  92. package/dist/web/assets/{nextflow-BtJwUbfF.js → nextflow-DD5C8nqX.js} +1 -1
  93. package/dist/web/assets/{nginx-j4gyIhHE.js → nginx-Ca7B__x_.js} +1 -1
  94. package/dist/web/assets/{nim-ClH_gjP5.js → nim-B8FogsDw.js} +1 -1
  95. package/dist/web/assets/notification-store-Yvy1I8gd.js +1 -0
  96. package/dist/web/assets/{number-overlay-editor-C1EqJnWq.js → number-overlay-editor-DG9xJwEG.js} +1 -1
  97. package/dist/web/assets/{overview-panel-vTeeJYVZ.js → overview-panel-s53bnl0q.js} +1 -1
  98. package/dist/web/assets/packet-RMMSAZCW-Z5jWjFCV.js +1 -0
  99. package/dist/web/assets/{panel-store-BSnkjgHt.js → panel-store-B4rijFKN.js} +1 -1
  100. package/dist/web/assets/{pdf-preview-CqFGRY0Z.js → pdf-preview-DYt3aBzM.js} +1 -1
  101. package/dist/web/assets/{perl-C9H7X7CT.js → perl-BR78hS8R.js} +1 -1
  102. package/dist/web/assets/{php-Bx2U-cQ_.js → php-DXBOMC9z.js} +1 -1
  103. package/dist/web/assets/pie-UPGHQEXC-Bq7UMi8P.js +1 -0
  104. package/dist/web/assets/{postgres-viewer-DHwcQucn.js → postgres-viewer-BvoWSuoZ.js} +3 -3
  105. package/dist/web/assets/{process-table-BGRJNlpn.js → process-table-BYwKigiD.js} +1 -1
  106. package/dist/web/assets/{project-store--nvQiy75.js → project-store-BuY7rxn_.js} +1 -1
  107. package/dist/web/assets/{pug-Cw74sKsE.js → pug-CvTwVVKV.js} +1 -1
  108. package/dist/web/assets/{qml-BXD94Eqz.js → qml-CPSoZ1-B.js} +1 -1
  109. package/dist/web/assets/radar-KQ55EAFF-BLo4BOTD.js +1 -0
  110. package/dist/web/assets/{razor-DZ0-Ge0S.js → razor-BUA1YKtF.js} +1 -1
  111. package/dist/web/assets/{rst-Dtdh0QUj.js → rst-BJsq7ISz.js} +1 -1
  112. package/dist/web/assets/{ruby-BC51BW2Q.js → ruby-DSDMeYf5.js} +1 -1
  113. package/dist/web/assets/{run-in-terminal-Sd3KyjN4.js → run-in-terminal-C9xpskFn.js} +1 -1
  114. package/dist/web/assets/{sas-BN8i4qOU.js → sas-B1nJOjbN.js} +1 -1
  115. package/dist/web/assets/{scroll-area-0gljZ6lF.js → scroll-area-DBcG1fQo.js} +1 -1
  116. package/dist/web/assets/{scss-H-QtA7Rz.js → scss-BZFyRiQn.js} +1 -1
  117. package/dist/web/assets/{send-to-chat-u6m8l-rH.js → send-to-chat-BIg70MUZ.js} +1 -1
  118. package/dist/web/assets/{settings-store-CHY6Kzin.js → settings-store-GV5pkkke.js} +2 -2
  119. package/dist/web/assets/{settings-tab-IY6K1MiZ.js → settings-tab-BePvIcjd.js} +1 -1
  120. package/dist/web/assets/settings-tab-Br-lJSPa.js +1 -0
  121. package/dist/web/assets/{shaderlab-CalNsj_x.js → shaderlab-laINRXBo.js} +1 -1
  122. package/dist/web/assets/{shellsession-BFrcoR8x.js → shellsession-BpOOvWVR.js} +1 -1
  123. package/dist/web/assets/{soy-CNbku7vP.js → soy-BW4d91Sa.js} +1 -1
  124. package/dist/web/assets/{sparql-BN_orcVp.js → sparql-BsvvyoHn.js} +1 -1
  125. package/dist/web/assets/{sql-query-editor-C6pC3I8l.js → sql-query-editor-qQce5QJ6.js} +1 -1
  126. package/dist/web/assets/{sqlite-viewer-DTr5PzUb.js → sqlite-viewer-yhc0YNvu.js} +1 -1
  127. package/dist/web/assets/{stata-C6a5Ijzq.js → stata-K-dZInUt.js} +1 -1
  128. package/dist/web/assets/{surrealql-ClplI_HY.js → surrealql-CpNp2sgf.js} +1 -1
  129. package/dist/web/assets/{svelte-DNm-UNXB.js → svelte-BG6iBA8R.js} +1 -1
  130. package/dist/web/assets/{switch-DKvKya9y.js → switch-_NcrktLe.js} +1 -1
  131. package/dist/web/assets/system-monitor-body-D8Z5QXBB.js +2 -0
  132. package/dist/web/assets/system-monitor-tab-BclYXFTe.js +1 -0
  133. package/dist/web/assets/{system-monitor-window-content-BUqRsPK2.js → system-monitor-window-content-CaOhD0AU.js} +1 -1
  134. package/dist/web/assets/{tab-host-window-content-BnqGPu8a.js → tab-host-window-content-f_Rc5rJK.js} +1 -1
  135. package/dist/web/assets/{tab-store-CJuJRapl.js → tab-store-tFnyPmm4.js} +1 -1
  136. package/dist/web/assets/team-member-sheet-QDHoYCs0.js +2 -0
  137. package/dist/web/assets/{team-member-window-content-T4Q5JI-G.js → team-member-window-content-B1jkKkDi.js} +1 -1
  138. package/dist/web/assets/{templ-CSdqVobu.js → templ-gxNKXmt3.js} +1 -1
  139. package/dist/web/assets/{terminal-tab-Bb2rZegQ.js → terminal-tab-UvwM0sty.js} +3 -3
  140. package/dist/web/assets/{tex-DzSJ4kcZ.js → tex-C0ON27g5.js} +1 -1
  141. package/dist/web/assets/{tool-cards-lhqhrDTT.js → tool-cards-jB7GT-wj.js} +4 -4
  142. package/dist/web/assets/treemap-KZPCXAKY-dyrE6SW2.js +1 -0
  143. package/dist/web/assets/{ts-tags-C28w3bTg.js → ts-tags-BX_CTVgQ.js} +1 -1
  144. package/dist/web/assets/{twig-i5jY3QXB.js → twig-CwL7XnU0.js} +1 -1
  145. package/dist/web/assets/{use-blob-url-Dsq9OjTh.js → use-blob-url-DcRcjNTE.js} +1 -1
  146. package/dist/web/assets/use-coarse-long-press-BmI_GVW5.js +1 -0
  147. package/dist/web/assets/{use-monaco-theme-BZvlsoBv.js → use-monaco-theme--9tOOkDA.js} +1 -1
  148. package/dist/web/assets/{use-open-team-member-DkiEjFYE.js → use-open-team-member-1hRsHLKg.js} +1 -1
  149. package/dist/web/assets/{use-websocket-B8R50f7f.js → use-websocket-rxJLbFqy.js} +1 -1
  150. package/dist/web/assets/{vendor-mermaid-By4AVvJY.js → vendor-mermaid-CHTa6D69.js} +1 -1
  151. package/dist/web/assets/video-preview-DMhnf2Gi.js +1 -0
  152. package/dist/web/assets/{vue-Ceyet_lv.js → vue-Bykm6wSS.js} +1 -1
  153. package/dist/web/assets/{vue-html-GuU7g_hg.js → vue-html-CETdK_iV.js} +1 -1
  154. package/dist/web/assets/{vue-vine-CxXoaJr2.js → vue-vine-DiJb6fO5.js} +1 -1
  155. package/dist/web/assets/{window-store-CsEW6jiE.js → window-store-CQ1lghvv.js} +1 -1
  156. package/dist/web/assets/{xml-CbqOVhkP.js → xml-BNw8J5YW.js} +1 -1
  157. package/dist/web/assets/{xsl-KfAmCauy.js → xsl-CsG9L31b.js} +1 -1
  158. package/dist/web/index.html +46 -45
  159. package/dist/web/sw.js +1 -1
  160. package/docs/architecture/ai-chat-and-providers.md +309 -0
  161. package/docs/architecture/data-and-storage.md +356 -0
  162. package/docs/architecture/extensions.md +496 -0
  163. package/docs/architecture/integrations.md +214 -0
  164. package/docs/architecture/workspace-and-ui.md +391 -0
  165. package/docs/claude-agent-sdk-reference.md +1 -1
  166. package/docs/code-patterns.md +361 -0
  167. package/docs/code-standards.md +8 -358
  168. package/docs/codebase-subsystems.md +364 -0
  169. package/docs/codebase-summary.md +34 -379
  170. package/docs/deployment-guide.md +280 -490
  171. package/docs/design-guidelines.md +1 -1
  172. package/docs/lessons-learned.md +27 -10
  173. package/docs/project-changelog.md +18 -806
  174. package/docs/project-overview-pdr.md +117 -111
  175. package/docs/project-roadmap.md +89 -133
  176. package/docs/system-architecture.md +77 -1826
  177. package/package.json +2 -2
  178. package/src/cli/commands/autostart.ts +2 -2
  179. package/src/cli/commands/config-cmd.ts +12 -3
  180. package/src/cli/commands/status.ts +3 -2
  181. package/src/cli/commands/stop.ts +32 -4
  182. package/src/server/index.ts +17 -3
  183. package/src/server/routes/chat-unread.ts +36 -0
  184. package/src/server/routes/named-tunnel.ts +132 -0
  185. package/src/server/routes/tunnel.ts +13 -0
  186. package/src/server/ws/chat.ts +5 -2
  187. package/src/services/autostart-register.ts +47 -29
  188. package/src/services/cloud.service.ts +26 -1
  189. package/src/services/config-secret-keys.ts +48 -0
  190. package/src/services/config.service.ts +1 -1
  191. package/src/services/db.service.ts +62 -12
  192. package/src/services/extension-rpc-handlers.ts +9 -1
  193. package/src/services/file-watcher/watch-tree.ts +67 -33
  194. package/src/services/file-watcher.service.ts +28 -10
  195. package/src/services/fs-credential-path-guard.ts +103 -0
  196. package/src/services/fs-path-guard.service.ts +14 -66
  197. package/src/services/named-tunnel/cloudflare-dns-api.ts +40 -0
  198. package/src/services/named-tunnel/cloudflare-zone-api.ts +28 -0
  199. package/src/services/named-tunnel/cloudflared-cert.ts +95 -0
  200. package/src/services/named-tunnel/cloudflared-exec.ts +50 -0
  201. package/src/services/named-tunnel/cloudflared-login-helpers.ts +98 -0
  202. package/src/services/named-tunnel/cloudflared-login.service.ts +182 -0
  203. package/src/services/named-tunnel/hostname-rules.ts +58 -0
  204. package/src/services/named-tunnel/login-output-parser.ts +36 -0
  205. package/src/services/named-tunnel/named-tunnel-args.ts +110 -0
  206. package/src/services/named-tunnel/named-tunnel-config.ts +67 -0
  207. package/src/services/named-tunnel/named-tunnel-probe-state.ts +95 -0
  208. package/src/services/named-tunnel/named-tunnel-readiness.ts +59 -0
  209. package/src/services/named-tunnel/named-tunnel-runtime.ts +42 -0
  210. package/src/services/named-tunnel/named-tunnel-setup-confirm.ts +98 -0
  211. package/src/services/named-tunnel/named-tunnel-setup.service.ts +191 -0
  212. package/src/services/supervisor-state.ts +67 -2
  213. package/src/services/supervisor.ts +454 -157
  214. package/src/services/tunnel-registry-parse.ts +27 -0
  215. package/src/services/tunnel-registry.service.ts +2 -15
  216. package/src/services/tunnel.service.ts +12 -3
  217. package/src/types/config.ts +31 -0
  218. package/src/web/app.tsx +5 -0
  219. package/src/web/components/chat/chat-history-bar.tsx +95 -98
  220. package/src/web/components/chat/chat-toolbar-overflow-menu.tsx +57 -0
  221. package/src/web/components/chat/session-debug-dialog.tsx +35 -27
  222. package/src/web/components/layout/cloud-share-named-tunnel-row.tsx +111 -0
  223. package/src/web/components/layout/cloud-share-popover.tsx +56 -14
  224. package/src/web/components/shared/connection-lost-overlay.tsx +44 -5
  225. package/src/web/components/tunnels/named-tunnel/hostname-validation.ts +14 -0
  226. package/src/web/components/tunnels/named-tunnel/named-tunnel-copy.ts +96 -0
  227. package/src/web/components/tunnels/named-tunnel/named-tunnel-hostname-field.tsx +51 -0
  228. package/src/web/components/tunnels/named-tunnel/named-tunnel-login-step.tsx +105 -0
  229. package/src/web/components/tunnels/named-tunnel/named-tunnel-section.tsx +159 -0
  230. package/src/web/components/tunnels/named-tunnel/named-tunnel-setup-content.tsx +197 -0
  231. package/src/web/components/tunnels/named-tunnel/named-tunnel-setup-popup.tsx +57 -0
  232. package/src/web/components/tunnels/named-tunnel/named-tunnel-step-reducer.ts +191 -0
  233. package/src/web/components/tunnels/named-tunnel/use-named-tunnel-setup.ts +212 -0
  234. package/src/web/components/tunnels/tunnel-manager-tab.tsx +4 -0
  235. package/src/web/hooks/use-global-events.ts +3 -1
  236. package/src/web/lib/api-named-tunnel.ts +54 -0
  237. package/src/web/lib/last-known-local-url.ts +23 -0
  238. package/src/web/stores/notification-store.ts +20 -1
  239. package/dist/web/assets/api-client-DTZEgjBQ.js +0 -1
  240. package/dist/web/assets/api-settings-kd1j4iR8.js +0 -1
  241. package/dist/web/assets/architecture-PBZL5I3N-8dCMT9r7.js +0 -1
  242. package/dist/web/assets/chat-tab-E3bf_V8X.js +0 -15
  243. package/dist/web/assets/code-editor-BUlM2gXk.js +0 -10
  244. package/dist/web/assets/explorer-body-9aBmyVpZ.js +0 -2
  245. package/dist/web/assets/explorer-window-content-DRtqoSPA.js +0 -1
  246. package/dist/web/assets/gitGraph-HDMCJU4V-2e_8dfbs.js +0 -1
  247. package/dist/web/assets/glide-data-grid-C4_zIneN.js +0 -138
  248. package/dist/web/assets/index-BImUaigO.js +0 -52
  249. package/dist/web/assets/index-CSfi6DSU.css +0 -2
  250. package/dist/web/assets/info-3K5VOQVL-BZi1Gha1.js +0 -1
  251. package/dist/web/assets/keybindings-store-CzV2sPls.js +0 -1
  252. package/dist/web/assets/markdown-renderer-CcbR33VG.js +0 -1
  253. package/dist/web/assets/mobile-explorer-sheet-SIwQXlwA.js +0 -1
  254. package/dist/web/assets/notification-store-DV5QtUTg.js +0 -1
  255. package/dist/web/assets/packet-RMMSAZCW-o5htEcin.js +0 -1
  256. package/dist/web/assets/pie-UPGHQEXC-BXAIFSAD.js +0 -1
  257. package/dist/web/assets/radar-KQ55EAFF-Dbt2Aebl.js +0 -1
  258. package/dist/web/assets/settings-tab-Dic6TKkU.js +0 -1
  259. package/dist/web/assets/system-monitor-body-iwGiCns9.js +0 -2
  260. package/dist/web/assets/system-monitor-tab-DdXQhEel.js +0 -1
  261. package/dist/web/assets/team-member-sheet-LkAFSCvb.js +0 -2
  262. package/dist/web/assets/treemap-KZPCXAKY-DUbnl9dz.js +0 -1
  263. package/dist/web/assets/video-preview-m0-3p7QZ.js +0 -1
  264. /package/dist/web/assets/{abap-C6nB04tn.js → abap-DGlrX_8G.js} +0 -0
  265. /package/dist/web/assets/{actionscript-3-Vx4rw2sC.js → actionscript-3-CUqRtUJE.js} +0 -0
  266. /package/dist/web/assets/{ada-Ccd8vM20.js → ada-CY3Spa33.js} +0 -0
  267. /package/dist/web/assets/{andromeeda-DnBX5xMg.js → andromeeda-Lxs2TJn7.js} +0 -0
  268. /package/dist/web/assets/{apache-B-9_sx0g.js → apache-DfxgGdgM.js} +0 -0
  269. /package/dist/web/assets/{apex-_wPVBYoL.js → apex-QVDF1dnI.js} +0 -0
  270. /package/dist/web/assets/{api-client-aQb5hHE5.js → api-client-oY1tC3tM.js} +0 -0
  271. /package/dist/web/assets/{applescript-CcvD-qr0.js → applescript-pwJ8QXh-.js} +0 -0
  272. /package/dist/web/assets/{apply-theme-BeLRfsSu.js → apply-theme-B_bMVL6a.js} +0 -0
  273. /package/dist/web/assets/{ara-C40Ztoms.js → ara-mPjeX5YX.js} +0 -0
  274. /package/dist/web/assets/{asciidoc-CybYkJV4.js → asciidoc-Bf7LsDkI.js} +0 -0
  275. /package/dist/web/assets/{asm-9eOKwzR0.js → asm-rRKC1OUx.js} +0 -0
  276. /package/dist/web/assets/{aurora-x-B5ZH4t7t.js → aurora-x-DwQr0DkG.js} +0 -0
  277. /package/dist/web/assets/{awk-Dqilob-2.js → awk-Bpt768fN.js} +0 -0
  278. /package/dist/web/assets/{ayu-dark-CPgRhf5r.js → ayu-dark-D9lwQHMs.js} +0 -0
  279. /package/dist/web/assets/{ayu-light-Do06Q52f.js → ayu-light-B4-ptrU5.js} +0 -0
  280. /package/dist/web/assets/{ayu-mirage-_BhxcrxY.js → ayu-mirage-DAyRzH5Q.js} +0 -0
  281. /package/dist/web/assets/{ballerina-DDwK54QW.js → ballerina-Cgdpj1HC.js} +0 -0
  282. /package/dist/web/assets/{bat-BGyGlzGk.js → bat-4FrN36S2.js} +0 -0
  283. /package/dist/web/assets/{beancount-CRWBdapI.js → beancount-DkcxQER3.js} +0 -0
  284. /package/dist/web/assets/{berry-DbSFn2gO.js → berry-Dnuut-Ml.js} +0 -0
  285. /package/dist/web/assets/{bibtex-QpsV9gm9.js → bibtex-CCDwmbuA.js} +0 -0
  286. /package/dist/web/assets/{bicep-CxS8CUve.js → bicep-BC0ryoGM.js} +0 -0
  287. /package/dist/web/assets/{bird2-CuZhQzYR.js → bird2-C50V_A-0.js} +0 -0
  288. /package/dist/web/assets/{c-9bnDqE3g.js → c-Ddorhq0U.js} +0 -0
  289. /package/dist/web/assets/{c3-JMZTrOhA.js → c3-DdIf5r9E.js} +0 -0
  290. /package/dist/web/assets/{cadence-DsDNayJS.js → cadence-s9pd1Wng.js} +0 -0
  291. /package/dist/web/assets/{can-open-in-ppm-BJfpynya.js → can-open-in-ppm-C6hZV1OP.js} +0 -0
  292. /package/dist/web/assets/{catppuccin-frappe-DYIKXXBe.js → catppuccin-frappe-CzJNTyu-.js} +0 -0
  293. /package/dist/web/assets/{catppuccin-latte-IYYOnUJ8.js → catppuccin-latte-BNpt-m7s.js} +0 -0
  294. /package/dist/web/assets/{catppuccin-macchiato-BrJ_7mfS.js → catppuccin-macchiato-FYGkfsJ5.js} +0 -0
  295. /package/dist/web/assets/{catppuccin-mocha-gzSu7v7-.js → catppuccin-mocha-it2g5D1q.js} +0 -0
  296. /package/dist/web/assets/{clarity-DLzsC0Hb.js → clarity-BVFBTjMe.js} +0 -0
  297. /package/dist/web/assets/{clipboard-7fw0Shic.js → clipboard-BWznymz7.js} +0 -0
  298. /package/dist/web/assets/{clojure-DS1BvoTt.js → clojure-BSYvXMI8.js} +0 -0
  299. /package/dist/web/assets/{cmake-CDvsJwYp.js → cmake-DGEqH-Np.js} +0 -0
  300. /package/dist/web/assets/{codeowners-BjsYiflJ.js → codeowners-D8FCOxWg.js} +0 -0
  301. /package/dist/web/assets/{codeql-CG-7ARat.js → codeql-COV0eluG.js} +0 -0
  302. /package/dist/web/assets/{common-lisp-DSO1Lbh9.js → common-lisp-xHnZUlgt.js} +0 -0
  303. /package/dist/web/assets/{coq-DYdh3oP_.js → coq-Cs_2i3Xg.js} +0 -0
  304. /package/dist/web/assets/{csharp-DxEBz5s0.js → csharp-B1ONB4PT.js} +0 -0
  305. /package/dist/web/assets/{css-dal3Q-8C.js → css-BgGQbvrZ.js} +0 -0
  306. /package/dist/web/assets/{csv-CpqjMGiA.js → csv-CNHmQBzs.js} +0 -0
  307. /package/dist/web/assets/{csv-parser-3umBA4NY.js → csv-parser-DWR24J17.js} +0 -0
  308. /package/dist/web/assets/{cue-DinoJ_5k.js → cue-ZXAKzwIy.js} +0 -0
  309. /package/dist/web/assets/{cypher-DzxqmkUW.js → cypher-4PL5bmT5.js} +0 -0
  310. /package/dist/web/assets/{d-BxNwJuEC.js → d-CEsV3RT2.js} +0 -0
  311. /package/dist/web/assets/{dark-plus-Clmv3V-0.js → dark-plus-NtFnYSDz.js} +0 -0
  312. /package/dist/web/assets/{dart-BWVtXD35.js → dart-CKHn4mDf.js} +0 -0
  313. /package/dist/web/assets/{data-grid-types-B4n51Fck.js → data-grid-types-CxU8oo-j.js} +0 -0
  314. /package/dist/web/assets/{dax-DsImuWgJ.js → dax-Cmkj1I_M.js} +0 -0
  315. /package/dist/web/assets/{desktop-B0jJuG2r.js → desktop-DJLalvPQ.js} +0 -0
  316. /package/dist/web/assets/{diff-CWqAAxoE.js → diff-BnS2wpj6.js} +0 -0
  317. /package/dist/web/assets/{dist-C0eNNfbt.js → dist-CuIdRyUB.js} +0 -0
  318. /package/dist/web/assets/{dist-B-EXdSYE.js → dist-uYjs3Wv6.js} +0 -0
  319. /package/dist/web/assets/{docker-CYFCJdIL.js → docker-CovNy7ml.js} +0 -0
  320. /package/dist/web/assets/{dotenv-CKDUjURg.js → dotenv-Gh4w3I6B.js} +0 -0
  321. /package/dist/web/assets/{dracula-CSoPspHE.js → dracula-NF0tAHXl.js} +0 -0
  322. /package/dist/web/assets/{dracula-soft-BuFjw5L1.js → dracula-soft-Cj_qBurK.js} +0 -0
  323. /package/dist/web/assets/{dream-maker-B6PdDRZu.js → dream-maker-CRuZPcl7.js} +0 -0
  324. /package/dist/web/assets/{emacs-lisp-CMcXvD0G.js → emacs-lisp-BACmC9qj.js} +0 -0
  325. /package/dist/web/assets/{everforest-dark-cU8-wYzi.js → everforest-dark-Dd9av4QG.js} +0 -0
  326. /package/dist/web/assets/{everforest-light-KhorllqK.js → everforest-light-C-jsss-B.js} +0 -0
  327. /package/dist/web/assets/{external-link-B8BynhvY.js → external-link-B6Hl0U4X.js} +0 -0
  328. /package/dist/web/assets/{fennel-BCELZK87.js → fennel-BJA9XnL8.js} +0 -0
  329. /package/dist/web/assets/{file-exclamation-point-CZ4DiR75.js → file-exclamation-point-JzhTU2TX.js} +0 -0
  330. /package/dist/web/assets/{fish-BQc0y_jy.js → fish-CKlhNSc2.js} +0 -0
  331. /package/dist/web/assets/{fluent-BTINnwF6.js → fluent-wfglRk5D.js} +0 -0
  332. /package/dist/web/assets/{folder-symlink-B8XrtvQK.js → folder-symlink-Dx1hOk8X.js} +0 -0
  333. /package/dist/web/assets/{format-bytes-WVcFxJuT.js → format-bytes-utwHMTry.js} +0 -0
  334. /package/dist/web/assets/{fortran-free-form-BQim9wDz.js → fortran-free-form-BlXCdid3.js} +0 -0
  335. /package/dist/web/assets/{gdscript-03w5u8un.js → gdscript-BwAVG6Et.js} +0 -0
  336. /package/dist/web/assets/{gdshader-Dp2daNzU.js → gdshader-DPc_T7ib.js} +0 -0
  337. /package/dist/web/assets/{genie-CoNcjPiD.js → genie-B-zZSLCX.js} +0 -0
  338. /package/dist/web/assets/{gherkin-NrPOSPQL.js → gherkin-CJ0ajpGs.js} +0 -0
  339. /package/dist/web/assets/{github-dark-z4RE9ZqA.js → github-dark-Dz8ZkzSP.js} +0 -0
  340. /package/dist/web/assets/{github-dark-default-DOKw-1cI.js → github-dark-default-CNUYo_kp.js} +0 -0
  341. /package/dist/web/assets/{github-dark-dimmed-DJRNMkEA.js → github-dark-dimmed-241z_Ycx.js} +0 -0
  342. /package/dist/web/assets/{github-dark-high-contrast-Bj7jJ_Gs.js → github-dark-high-contrast-7r6yZZYH.js} +0 -0
  343. /package/dist/web/assets/{github-light-B4k_yMFu.js → github-light-C8gmZn-D.js} +0 -0
  344. /package/dist/web/assets/{github-light-default-BHc-Uzhs.js → github-light-default-GAEgq1eA.js} +0 -0
  345. /package/dist/web/assets/{github-light-high-contrast-CHisIywL.js → github-light-high-contrast-3z91352E.js} +0 -0
  346. /package/dist/web/assets/{gleam-CfbypZ4q.js → gleam-C7vxW5zd.js} +0 -0
  347. /package/dist/web/assets/{gn-YoAjyhJa.js → gn-CyJIXwHP.js} +0 -0
  348. /package/dist/web/assets/{gnuplot-xVkc1f1c.js → gnuplot-CqLbGgPd.js} +0 -0
  349. /package/dist/web/assets/{go-GPCwP3Gu.js → go-DdDcK9aX.js} +0 -0
  350. /package/dist/web/assets/{groovy-Crh4Yww9.js → groovy-UYHggEqH.js} +0 -0
  351. /package/dist/web/assets/{gruvbox-dark-hard-BluUFuDS.js → gruvbox-dark-hard-B4ierkJn.js} +0 -0
  352. /package/dist/web/assets/{gruvbox-dark-medium-Cxk1FWQp.js → gruvbox-dark-medium-DYwkDSZ6.js} +0 -0
  353. /package/dist/web/assets/{gruvbox-dark-soft-CHXMiFmj.js → gruvbox-dark-soft-CVL4P-Lz.js} +0 -0
  354. /package/dist/web/assets/{gruvbox-light-hard-B6eKPjAD.js → gruvbox-light-hard-BJ0LewUZ.js} +0 -0
  355. /package/dist/web/assets/{gruvbox-light-medium-pDwMm1ut.js → gruvbox-light-medium-CaqqjeGJ.js} +0 -0
  356. /package/dist/web/assets/{gruvbox-light-soft-Cxu6kHqK.js → gruvbox-light-soft-ByKMoVNr.js} +0 -0
  357. /package/dist/web/assets/{haskell-C6JKHjbK.js → haskell-BilYRVPp.js} +0 -0
  358. /package/dist/web/assets/{haxe-BuBNdF0a.js → haxe-Brs9Bj1s.js} +0 -0
  359. /package/dist/web/assets/{hcl-DZpDdGj2.js → hcl-ClrZpol-.js} +0 -0
  360. /package/dist/web/assets/{hjson-CBkhYRuo.js → hjson-9PvHnYMX.js} +0 -0
  361. /package/dist/web/assets/{hlsl-C5nMxnp9.js → hlsl-BbBk4vqV.js} +0 -0
  362. /package/dist/web/assets/{horizon-VAFvA6R6.js → horizon-E5Py0cny.js} +0 -0
  363. /package/dist/web/assets/{horizon-bright-BC0xn7T3.js → horizon-bright-DVCsNGEk.js} +0 -0
  364. /package/dist/web/assets/{houston-BxrUivmz.js → houston-JdFEax9Y.js} +0 -0
  365. /package/dist/web/assets/{hy-DLtOXoaH.js → hy-W_W3tLKT.js} +0 -0
  366. /package/dist/web/assets/{image-gallery-Gnf7TdCR.js → image-gallery-5IURd6db.js} +0 -0
  367. /package/dist/web/assets/{imba-BdpFXM2W.js → imba-CfAqJz7T.js} +0 -0
  368. /package/dist/web/assets/{ini-BInJO_T0.js → ini-C_3gvKWs.js} +0 -0
  369. /package/dist/web/assets/{java-Dxuddnkb.js → java-CKqtXZ-j.js} +0 -0
  370. /package/dist/web/assets/{javascript-CVamJfLY.js → javascript-C7gSEfae.js} +0 -0
  371. /package/dist/web/assets/{json-BLZ0ozYk.js → json-BoN6e11T.js} +0 -0
  372. /package/dist/web/assets/{json5-BnXzmMKs.js → json5-CgE7C8HW.js} +0 -0
  373. /package/dist/web/assets/{jsonc-CSgkSga7.js → jsonc-DjyoattY.js} +0 -0
  374. /package/dist/web/assets/{jsonl-CY5W2nF2.js → jsonl-lI82wGSw.js} +0 -0
  375. /package/dist/web/assets/{jsonnet-CEJYH3sF.js → jsonnet-CszEI8va.js} +0 -0
  376. /package/dist/web/assets/{jssm-CsJc7Uhk.js → jssm-CZXDlszb.js} +0 -0
  377. /package/dist/web/assets/{jsx-jCiRaHU7.js → jsx-BeRz0eEz.js} +0 -0
  378. /package/dist/web/assets/{kanagawa-dragon-DfoA_GxX.js → kanagawa-dragon-BOmnUiyd.js} +0 -0
  379. /package/dist/web/assets/{kanagawa-lotus-BOLYJpWd.js → kanagawa-lotus-ffU_P5w-.js} +0 -0
  380. /package/dist/web/assets/{kanagawa-wave-DfKlbT1G.js → kanagawa-wave-DKTJZrMu.js} +0 -0
  381. /package/dist/web/assets/{kdl-CmssIFTi.js → kdl-BWECJveH.js} +0 -0
  382. /package/dist/web/assets/{kotlin-BRsNgp6x.js → kotlin-DpVwBCSt.js} +0 -0
  383. /package/dist/web/assets/{kusto-T8X9jUab.js → kusto-BgVqjUZA.js} +0 -0
  384. /package/dist/web/assets/{laserwave-DkJMVJ8Z.js → laserwave-CEVCi8em.js} +0 -0
  385. /package/dist/web/assets/{lean-C65KGVPq.js → lean-CGyfRhLJ.js} +0 -0
  386. /package/dist/web/assets/{less-exIPdDlf.js → less-B0_H10Ku.js} +0 -0
  387. /package/dist/web/assets/{lib-mC1NZfuw.js → lib-hrC3bruJ.js} +0 -0
  388. /package/dist/web/assets/{libesm-DSutUtl1.js → libesm-DVpFmwJu.js} +0 -0
  389. /package/dist/web/assets/{light-plus-DiHUXAZt.js → light-plus-DqzMqPID.js} +0 -0
  390. /package/dist/web/assets/{llvm-CJBnEzFM.js → llvm-9ucnfNiF.js} +0 -0
  391. /package/dist/web/assets/{loader-circle-gSPVxfvH.js → loader-circle-Dpqcv0eS.js} +0 -0
  392. /package/dist/web/assets/{lock-Did-87UV.js → lock-DldbT31x.js} +0 -0
  393. /package/dist/web/assets/{log-DxMyUMuP.js → log-m6A2dOSj.js} +0 -0
  394. /package/dist/web/assets/{logo-CC9NKzca.js → logo-ByPcsC9P.js} +0 -0
  395. /package/dist/web/assets/{luau-Bw10I6zf.js → luau-DFCo8nBn.js} +0 -0
  396. /package/dist/web/assets/{make-C_6M90m6.js → make-C90w3MeA.js} +0 -0
  397. /package/dist/web/assets/{markdown-bR9_R-LF.js → markdown-DT0uywZG.js} +0 -0
  398. /package/dist/web/assets/{material-theme-BUx2Qujn.js → material-theme-BVUO93tJ.js} +0 -0
  399. /package/dist/web/assets/{material-theme-darker-CRJrPgKm.js → material-theme-darker-xXgGDwnF.js} +0 -0
  400. /package/dist/web/assets/{material-theme-lighter-CUAYppPa.js → material-theme-lighter-BjStPzWB.js} +0 -0
  401. /package/dist/web/assets/{material-theme-ocean-DuINF1fg.js → material-theme-ocean-wFmSiKjy.js} +0 -0
  402. /package/dist/web/assets/{material-theme-palenight-W6_icGCj.js → material-theme-palenight-e-0CtRoe.js} +0 -0
  403. /package/dist/web/assets/{matlab-rfqn_b3z.js → matlab-BNaNQAUH.js} +0 -0
  404. /package/dist/web/assets/{mdx-Bh1B_YOJ.js → mdx-DfpVWAqO.js} +0 -0
  405. /package/dist/web/assets/{mermaid-Dxf6Ya2k.js → mermaid-Bpq7wFCP.js} +0 -0
  406. /package/dist/web/assets/{min-dark-CivZ2L0h.js → min-dark-CL2Y0WH6.js} +0 -0
  407. /package/dist/web/assets/{min-light-B1Ykqtma.js → min-light-DOgr_IdP.js} +0 -0
  408. /package/dist/web/assets/{mipsasm-DynHaM0d.js → mipsasm-C9ie2zlB.js} +0 -0
  409. /package/dist/web/assets/{mojo-Clw5PbGH.js → mojo-Md2A2sJy.js} +0 -0
  410. /package/dist/web/assets/{monitor-Dv8vn_6O.js → monitor-4vWfqzuN.js} +0 -0
  411. /package/dist/web/assets/{monokai-DFIooFZT.js → monokai-nbXIEySB.js} +0 -0
  412. /package/dist/web/assets/{moonbit-DnBSZWGM.js → moonbit-CJ-T-s4A.js} +0 -0
  413. /package/dist/web/assets/{move-CCcL2PfL.js → move-DwEehLIK.js} +0 -0
  414. /package/dist/web/assets/{narrat-BDarg5Lk.js → narrat-CuF4sIKr.js} +0 -0
  415. /package/dist/web/assets/{nextflow-groovy-DrZOeCNW.js → nextflow-groovy-1dYhfPfq.js} +0 -0
  416. /package/dist/web/assets/{night-owl-BnZZCK7v.js → night-owl-gZS5mfzY.js} +0 -0
  417. /package/dist/web/assets/{night-owl-light-CEwBsVHS.js → night-owl-light-DDAster5.js} +0 -0
  418. /package/dist/web/assets/{nix-amCzOPMR.js → nix-BlbEYs2c.js} +0 -0
  419. /package/dist/web/assets/{nord-BIs2BC6q.js → nord-BRiPb8Vy.js} +0 -0
  420. /package/dist/web/assets/{nushell-Y02fo4yw.js → nushell-DgWicB1i.js} +0 -0
  421. /package/dist/web/assets/{objective-c-7xOZtWW1.js → objective-c-D8mPZ42Y.js} +0 -0
  422. /package/dist/web/assets/{objective-cpp-eVtjUvVB.js → objective-cpp-B0pNXzuj.js} +0 -0
  423. /package/dist/web/assets/{ocaml-Bi6ZwqG4.js → ocaml-lQd7aK5d.js} +0 -0
  424. /package/dist/web/assets/{odin-8xf1Y0S9.js → odin-CxtIOBjm.js} +0 -0
  425. /package/dist/web/assets/{one-dark-pro-hVv-_y_b.js → one-dark-pro-T_UFnWfe.js} +0 -0
  426. /package/dist/web/assets/{one-light-CJJ3MtHt.js → one-light-LBVqwyV-.js} +0 -0
  427. /package/dist/web/assets/{openscad-B2HcywLk.js → openscad-C5dnS6J7.js} +0 -0
  428. /package/dist/web/assets/{pascal-C7fllV_7.js → pascal-CmWCWQML.js} +0 -0
  429. /package/dist/web/assets/{pkl-qvLC1IWP.js → pkl-BWWOtDQk.js} +0 -0
  430. /package/dist/web/assets/{plastic-BT1wHZv2.js → plastic-ekhupckF.js} +0 -0
  431. /package/dist/web/assets/{play-4MZi1Axp.js → play-CpCAoQRZ.js} +0 -0
  432. /package/dist/web/assets/{plsql-1MsmdmJD.js → plsql-BPsDHXx4.js} +0 -0
  433. /package/dist/web/assets/{plus-BhMZqFsN.js → plus-BR0qewJI.js} +0 -0
  434. /package/dist/web/assets/{po-BigskytD.js → po-BX2FiuW2.js} +0 -0
  435. /package/dist/web/assets/{poimandres-DuklniF7.js → poimandres-DzXOdZcN.js} +0 -0
  436. /package/dist/web/assets/{polar-e2pjN_sp.js → polar-DDRXgJzG.js} +0 -0
  437. /package/dist/web/assets/{portal-container-context-Cm5HipFr.js → portal-container-context-a399Hd9F.js} +0 -0
  438. /package/dist/web/assets/{postcss-DtAeYjWw.js → postcss-BHW6XBhx.js} +0 -0
  439. /package/dist/web/assets/{powerquery-Cr2PtehI.js → powerquery-B89c2NBb.js} +0 -0
  440. /package/dist/web/assets/{powershell-BxFTGLJ4.js → powershell-Dvxrd3Tu.js} +0 -0
  441. /package/dist/web/assets/{prisma-COWJiwdZ.js → prisma-lMK8EFLU.js} +0 -0
  442. /package/dist/web/assets/{prolog-DFvGKRx6.js → prolog-D0YrtMG4.js} +0 -0
  443. /package/dist/web/assets/{proto-CcK80lFt.js → proto-J0mM25aw.js} +0 -0
  444. /package/dist/web/assets/{puppet-BF60bZ4F.js → puppet-CUT0xkhh.js} +0 -0
  445. /package/dist/web/assets/{purescript-zL_69MzU.js → purescript-CoJWSGRp.js} +0 -0
  446. /package/dist/web/assets/{python-CIwKhfb_.js → python-BBrmuz6P.js} +0 -0
  447. /package/dist/web/assets/{qmldir-CXNe04Lo.js → qmldir-CUtzs4Q7.js} +0 -0
  448. /package/dist/web/assets/{qss-C8lAWe6G.js → qss-Dm1RZ8aL.js} +0 -0
  449. /package/dist/web/assets/{r-CL5ZVL3_.js → r-BGP7qZTe.js} +0 -0
  450. /package/dist/web/assets/{racket-BBfh0uh0.js → racket-K_6U1lqJ.js} +0 -0
  451. /package/dist/web/assets/{raku-o6E8R5Q3.js → raku-bNSiZeW_.js} +0 -0
  452. /package/dist/web/assets/{react-CBTnT4sY.js → react-X4jUntEf.js} +0 -0
  453. /package/dist/web/assets/{red-GomRF2Xp.js → red-uVeIEF0f.js} +0 -0
  454. /package/dist/web/assets/{refresh-cw-B06yaBrW.js → refresh-cw-B9iv7csb.js} +0 -0
  455. /package/dist/web/assets/{reg-_ffDIvx9.js → reg-DSm9GWjh.js} +0 -0
  456. /package/dist/web/assets/{regexp-Bl5sF65W.js → regexp-CljRm_j_.js} +0 -0
  457. /package/dist/web/assets/{rel-DgMdqDuj.js → rel-d3JcopZg.js} +0 -0
  458. /package/dist/web/assets/{resolve-theme-CRt_7wpd.js → resolve-theme-DLKmm-lE.js} +0 -0
  459. /package/dist/web/assets/{riscv-8b3-Ye4X.js → riscv-CJmaELjT.js} +0 -0
  460. /package/dist/web/assets/{ron-DrmU1KHP.js → ron-D0g9B1rW.js} +0 -0
  461. /package/dist/web/assets/{rose-pine-C_-E2tF1.js → rose-pine-DOrD2BSH.js} +0 -0
  462. /package/dist/web/assets/{rose-pine-dawn-DEfhNlFH.js → rose-pine-dawn-CzZQ-LCF.js} +0 -0
  463. /package/dist/web/assets/{rose-pine-moon-BdvX3gdn.js → rose-pine-moon-CdmsYp7C.js} +0 -0
  464. /package/dist/web/assets/{rosmsg-B6GhGpd5.js → rosmsg-CmDth6pO.js} +0 -0
  465. /package/dist/web/assets/{rotate-ccw-COXu_9oj.js → rotate-ccw-DnuPzJRE.js} +0 -0
  466. /package/dist/web/assets/{rust-DmC97M1-.js → rust-DGdP6jiR.js} +0 -0
  467. /package/dist/web/assets/{sass-B0tJOHLM.js → sass-Dkgt2FKZ.js} +0 -0
  468. /package/dist/web/assets/{save-CtIGOjmx.js → save-DxonD4y1.js} +0 -0
  469. /package/dist/web/assets/{scala-n8zaFOXv.js → scala-BQLTON6C.js} +0 -0
  470. /package/dist/web/assets/{scheme-BKD9ztBU.js → scheme-DKlxUGCi.js} +0 -0
  471. /package/dist/web/assets/{sdbl-D8gB5-rS.js → sdbl-C3iZJQeZ.js} +0 -0
  472. /package/dist/web/assets/{send-BlyNJAzy.js → send-B-t5Mz26.js} +0 -0
  473. /package/dist/web/assets/{shallow-DYo6goJ4.js → shallow-jwPzEunk.js} +0 -0
  474. /package/dist/web/assets/{shellscript-BfXlf_Ao.js → shellscript-BRu-ZQAx.js} +0 -0
  475. /package/dist/web/assets/{shield-check-B0iGUiOK.js → shield-check-CdTiK1j2.js} +0 -0
  476. /package/dist/web/assets/{shield-off-BNLWBhcq.js → shield-off-DuetkXKM.js} +0 -0
  477. /package/dist/web/assets/{slack-dark-CylEddse.js → slack-dark-qkm_u2zz.js} +0 -0
  478. /package/dist/web/assets/{slack-ochin-w8wg8vuC.js → slack-ochin-BP8_8e4m.js} +0 -0
  479. /package/dist/web/assets/{smalltalk-hiAXA64u.js → smalltalk-Bnz4gt07.js} +0 -0
  480. /package/dist/web/assets/{snazzy-light-BwlV3Xty.js → snazzy-light-fbPZg5io.js} +0 -0
  481. /package/dist/web/assets/{solarized-dark-vmNGdykz.js → solarized-dark-CM0vTRoi.js} +0 -0
  482. /package/dist/web/assets/{solarized-light-DGv_0JXq.js → solarized-light-C4_W9mvs.js} +0 -0
  483. /package/dist/web/assets/{solidity-Y7QSH0B1.js → solidity-Bz6v1PoD.js} +0 -0
  484. /package/dist/web/assets/{splunk-BtgpLjHi.js → splunk-DyNxu-0i.js} +0 -0
  485. /package/dist/web/assets/{sql-CRHYhOia.js → sql-DXRL1gw1.js} +0 -0
  486. /package/dist/web/assets/{ssh-config-DOqSs3au.js → ssh-config-2z1QHuOG.js} +0 -0
  487. /package/dist/web/assets/{stylus-crCAEaBT.js → stylus-D4I-VaeY.js} +0 -0
  488. /package/dist/web/assets/{swift-eE3rT7TC.js → swift-C_2G-tIc.js} +0 -0
  489. /package/dist/web/assets/{synthwave-84-BWy14LBX.js → synthwave-84-osBjChRP.js} +0 -0
  490. /package/dist/web/assets/{system-verilog-DC0-DZM4.js → system-verilog-zQP2qPNU.js} +0 -0
  491. /package/dist/web/assets/{systemd-to5p6N8I.js → systemd-UGfjRSBM.js} +0 -0
  492. /package/dist/web/assets/{table-Bbc783ko.js → table-FLU8ei8b.js} +0 -0
  493. /package/dist/web/assets/{talonscript-DoTcU8wm.js → talonscript-C1XrFPwo.js} +0 -0
  494. /package/dist/web/assets/{tasl-cNZvUs95.js → tasl-B5raVn43.js} +0 -0
  495. /package/dist/web/assets/{tcl-mZE8sZH8.js → tcl-3-vbeMIc.js} +0 -0
  496. /package/dist/web/assets/{terraform-CqHPpIfu.js → terraform-a8VXZDm9.js} +0 -0
  497. /package/dist/web/assets/{text-wrap-CBT4Gxtg.js → text-wrap-B05VGRa-.js} +0 -0
  498. /package/dist/web/assets/{tokyo-night-Tp2rTIZd.js → tokyo-night-4SRhf-Hz.js} +0 -0
  499. /package/dist/web/assets/{toml-CU_vscgn.js → toml-B4N0i8wT.js} +0 -0
  500. /package/dist/web/assets/{trash-2-Bk4yYlck.js → trash-2-CTXlTflF.js} +0 -0
  501. /package/dist/web/assets/{triangle-alert-B8EYecpe.js → triangle-alert-BRq0VAfd.js} +0 -0
  502. /package/dist/web/assets/{tsv-ik7iFB9D.js → tsv-DA5k9Lvw.js} +0 -0
  503. /package/dist/web/assets/{tsx-BMvvMKiv.js → tsx-D9SZ8owC.js} +0 -0
  504. /package/dist/web/assets/{turtle-DBqKCq9o.js → turtle-BTHTvyY_.js} +0 -0
  505. /package/dist/web/assets/{typescript-DXJDmMZZ.js → typescript-DYzV9p5L.js} +0 -0
  506. /package/dist/web/assets/{typespec-CBseCMtZ.js → typespec-BC15eh7F.js} +0 -0
  507. /package/dist/web/assets/{typst-4oY25U9y.js → typst-BJUqzA6D.js} +0 -0
  508. /package/dist/web/assets/{use-is-mobile-D1weanbj.js → use-is-mobile-DFWViA4S.js} +0 -0
  509. /package/dist/web/assets/{utils-BNRH507E.js → utils-C9OjCrou.js} +0 -0
  510. /package/dist/web/assets/{v-BXaZ_1oy.js → v-50Lps6oA.js} +0 -0
  511. /package/dist/web/assets/{vala-BImWJE7z.js → vala-8wiUvvrD.js} +0 -0
  512. /package/dist/web/assets/{vb-CLfj2_sy.js → vb-BlgPLt6B.js} +0 -0
  513. /package/dist/web/assets/{vendor-xterm-_yyu5n32.js → vendor-xterm-BZOrwF_F.js} +0 -0
  514. /package/dist/web/assets/{verilog-BWa8Ed2b.js → verilog-CD9pVW5p.js} +0 -0
  515. /package/dist/web/assets/{vesper-BGj1cg6m.js → vesper-BrivW4PT.js} +0 -0
  516. /package/dist/web/assets/{vhdl-mByK7mlx.js → vhdl-Bunxfa7N.js} +0 -0
  517. /package/dist/web/assets/{viml-CugmlW5g.js → viml-DndUb2qM.js} +0 -0
  518. /package/dist/web/assets/{vitesse-black-vPdpy9TL.js → vitesse-black-BurZSkxW.js} +0 -0
  519. /package/dist/web/assets/{vitesse-dark-BuQK3dUh.js → vitesse-dark-8UShspzC.js} +0 -0
  520. /package/dist/web/assets/{vitesse-light-B3nz1XL9.js → vitesse-light-DghCAZ90.js} +0 -0
  521. /package/dist/web/assets/{vyper-DH_GTIHG.js → vyper-b-Clr-8u.js} +0 -0
  522. /package/dist/web/assets/{wasm-DfVbVJlW.js → wasm-C5v2T06Y.js} +0 -0
  523. /package/dist/web/assets/{wasm-C-LF9GjX.js → wasm-CpcKStkw.js} +0 -0
  524. /package/dist/web/assets/{wenyan-CzQkHyHx.js → wenyan-Dz2srLZR.js} +0 -0
  525. /package/dist/web/assets/{wgsl-Du_M1DW9.js → wgsl-CeD1-dRb.js} +0 -0
  526. /package/dist/web/assets/{wikitext-BWN_w5S7.js → wikitext-CyeS-9FH.js} +0 -0
  527. /package/dist/web/assets/{wit-BR13v5HD.js → wit-Kr-q-qBQ.js} +0 -0
  528. /package/dist/web/assets/{wolfram-BoXxp_Xl.js → wolfram-BKm8bmln.js} +0 -0
  529. /package/dist/web/assets/{x-nhriOX9o.js → x-YDu4m2Iq.js} +0 -0
  530. /package/dist/web/assets/{yaml-DpR_EF-d.js → yaml-2XSxomjM.js} +0 -0
  531. /package/dist/web/assets/{zenscript-C-EdUtUd.js → zenscript-CKIS34vf.js} +0 -0
  532. /package/dist/web/assets/{zig-BD4eA5nU.js → zig-DdHGNllX.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
+ }