@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
@@ -125,6 +125,33 @@ const SOURCE_RANK: Record<TunnelSource, number> = { external: 0, ppm: 1, app: 2
125
125
  * source/protected flag, while url/port/identity are filled from whichever
126
126
  * entry has them (higher precedence preferred).
127
127
  */
128
+ /** Identity of the supervisor-managed app tunnel, read from status.json + config. */
129
+ export interface AppShare {
130
+ shareUrl: string | null;
131
+ tunnelPid: number | null;
132
+ serverPort: number | null;
133
+ }
134
+
135
+ /**
136
+ * Does this cloudflared entry belong to the app/supervisor tunnel? Such a
137
+ * tunnel is display-only: stopping it from the panel would take the whole app
138
+ * offline, and the supervisor would just respawn it.
139
+ *
140
+ * Matching is protect-by-default (PID, public URL, then the PPM port as a
141
+ * fallback for a stale `tunnelPid`) with one deliberate exception: a tunnel
142
+ * this server spawned itself. Running a second, temporary tunnel onto the same
143
+ * public port is a supported thing to do — sharing a one-off link without
144
+ * handing out the permanent hostname — and it must stay stoppable from the UI
145
+ * that created it.
146
+ */
147
+ export function isAppTunnel(entry: TunnelEntry, app: AppShare): boolean {
148
+ if (app.tunnelPid != null && entry.pid === app.tunnelPid) return true;
149
+ if (app.shareUrl && entry.url && entry.url === app.shareUrl) return true;
150
+ if (entry.source === "ppm") return false;
151
+ if (app.serverPort != null && entry.port === app.serverPort) return true;
152
+ return false;
153
+ }
154
+
128
155
  export function mergeTunnelSources(sources: {
129
156
  external: TunnelEntry[];
130
157
  ppm: TunnelEntry[];
@@ -21,6 +21,8 @@ import {
21
21
  extractMetricsPort,
22
22
  parseQuickTunnelResponse,
23
23
  mergeTunnelSources,
24
+ isAppTunnel,
25
+ type AppShare,
24
26
  type TunnelEntry,
25
27
  } from "./tunnel-registry-parse.ts";
26
28
 
@@ -159,12 +161,6 @@ async function recoverUrl(pid: number, metricsAddr: string | null): Promise<stri
159
161
  // App/supervisor tunnel identification (protection)
160
162
  // ---------------------------------------------------------------------------
161
163
 
162
- interface AppShare {
163
- shareUrl: string | null;
164
- tunnelPid: number | null;
165
- serverPort: number | null;
166
- }
167
-
168
164
  /** Read the app-share tunnel fresh from status.json each call (guards stale PID). */
169
165
  function readAppShare(): AppShare {
170
166
  let shareUrl: string | null = null;
@@ -181,15 +177,6 @@ function readAppShare(): AppShare {
181
177
  return { shareUrl, tunnelPid, serverPort };
182
178
  }
183
179
 
184
- /** A cloudflared entry belongs to the app/supervisor tunnel if it matches by
185
- * PID, public URL, or targets the PPM server port. Protect-by-default. */
186
- function isAppTunnel(entry: TunnelEntry, app: AppShare): boolean {
187
- if (app.tunnelPid != null && entry.pid === app.tunnelPid) return true;
188
- if (app.shareUrl && entry.url && entry.url === app.shareUrl) return true;
189
- if (app.serverPort != null && entry.port === app.serverPort) return true;
190
- return false;
191
- }
192
-
193
180
  // ---------------------------------------------------------------------------
194
181
  // Image verification (safe-kill guard, used by the route layer)
195
182
  // ---------------------------------------------------------------------------
@@ -125,22 +125,31 @@ class TunnelService {
125
125
  /** Get current tunnel URL (null if not running).
126
126
  * Falls back to status.json if the supervisor set the URL after this process started. */
127
127
  getTunnelUrl(): string | null {
128
- if (this.url) return this.url;
129
- // Lazy sync: supervisor may have written shareUrl after server startup
128
+ // A tunnel this process spawned can only change through this class, so its
129
+ // URL is safe to cache. A supervisor-managed one is not: the supervisor
130
+ // rewrites shareUrl on its own (quick-URL regeneration, switching to or
131
+ // from a named hostname) and the server would otherwise keep handing out
132
+ // the first URL it ever saw — the share popover and the cloud heartbeat
133
+ // both showed a dead temporary URL minutes after the hostname went live.
134
+ if (this.childProcess && this.url) return this.url;
130
135
  this.syncFromStatusFile();
131
136
  return this.url;
132
137
  }
133
138
 
134
139
  /** Re-read tunnel state from status.json (supervisor may have updated it after server started) */
135
140
  private syncFromStatusFile(): void {
136
- if (this.url) return; // already have a URL
141
+ if (this.childProcess) return; // we own this tunnel; status.json mirrors us, not the other way round
137
142
  try {
138
143
  const statusFile = resolve(getPpmDir(), "status.json");
139
144
  const status = JSON.parse(readFileSync(statusFile, "utf-8"));
140
145
  if (status.shareUrl) {
146
+ const changed = status.shareUrl !== this.url;
141
147
  this.url = status.shareUrl;
142
148
  this.supervisorManaged = true;
143
149
  if (status.tunnelPid) this.externalPid = status.tunnelPid;
150
+ // A new public URL must reach PPM Cloud too, or the permanent link
151
+ // keeps redirecting to the retired one.
152
+ if (changed) this.syncToCloud();
144
153
  }
145
154
  } catch {}
146
155
  }
@@ -35,6 +35,23 @@ export interface PpmConfig {
35
35
  clawbot?: PPMBotConfig;
36
36
  cloud_url?: string;
37
37
  query_audit: QueryAuditConfig;
38
+ tunnel: TunnelConfig;
39
+ }
40
+
41
+ /**
42
+ * Persisted named-tunnel state. `namedTunnelToken` is secret-by-contract —
43
+ * guarded by the config-key denylist and never returned unmasked by any route.
44
+ * `zoneID`/`accountID` are pinned at setup and re-checked on every reuse.
45
+ */
46
+ export interface TunnelConfig {
47
+ mode: "quick" | "named";
48
+ namedTunnelName?: string;
49
+ namedTunnelHostname?: string;
50
+ namedTunnelToken?: string;
51
+ zoneID?: string;
52
+ accountID?: string;
53
+ /** User answered "no domain" — popup must never nag again. */
54
+ dismissed?: boolean;
38
55
  }
39
56
 
40
57
  export interface QueryAuditConfig {
@@ -131,6 +148,9 @@ export const DEFAULT_CONFIG: PpmConfig = {
131
148
  permission_mode: "bypassPermissions",
132
149
  debounce_ms: 2000,
133
150
  },
151
+ tunnel: {
152
+ mode: "quick",
153
+ },
134
154
  };
135
155
 
136
156
  const VALID_TYPES = ["agent-sdk", "cli", "mock"] as const;
@@ -264,5 +284,16 @@ export function sanitizeConfig(config: PpmConfig): boolean {
264
284
  }
265
285
  }
266
286
 
287
+ // Only repair `tunnel` when storage itself is malformed (wrong type / bad enum).
288
+ // Never strip namedTunnel*/zoneID/accountID just because mode is "quick" or the
289
+ // combination looks "incomplete" — that degrade-to-quick judgment belongs to
290
+ // the runtime resolver (resolveTunnelConfig), or /disable's "keep the config so
291
+ // Retry works" contract silently breaks.
292
+ if (typeof config.tunnel !== "object" || config.tunnel === null ||
293
+ (config.tunnel.mode !== "quick" && config.tunnel.mode !== "named")) {
294
+ config.tunnel = structuredClone(DEFAULT_CONFIG.tunnel);
295
+ dirty = true;
296
+ }
297
+
267
298
  return dirty;
268
299
  }
package/src/web/app.tsx CHANGED
@@ -27,6 +27,7 @@ import { useServerReload } from "@/hooks/use-server-reload";
27
27
  import { CommandPalette } from "@/components/layout/command-palette";
28
28
  import { ComparePicker } from "@/components/editor/compare-picker";
29
29
  import { BugReportPopup } from "@/components/shared/bug-report-popup";
30
+ import { NamedTunnelSetupPopup } from "@/components/tunnels/named-tunnel/named-tunnel-setup-popup";
30
31
  import { ImageOverlay } from "@/components/shared/image-overlay";
31
32
  import { DiagramOverlay } from "@/components/shared/diagram-overlay";
32
33
  import { BackgroundOutputPanel } from "@/components/chat/background-output-panel";
@@ -359,6 +360,10 @@ export function App() {
359
360
  {/* Global bug report popup */}
360
361
  <BugReportPopup />
361
362
 
363
+ {/* Named-tunnel first-run setup popup — hidden unless auth is on, mode is
364
+ still quick and the user has not dismissed it (or a cert needs renewal) */}
365
+ <NamedTunnelSetupPopup />
366
+
362
367
  {/* Global image lightbox */}
363
368
  <ImageOverlay />
364
369
 
@@ -1,5 +1,5 @@
1
1
  import { useState, useEffect, useCallback, useRef, type MouseEvent } from "react";
2
- import { History, Settings2, Loader2, MessageSquare, RefreshCw, Search, Pencil, Check, X, BellOff, Circle, Pin, PinOff, Trash2, Users, Bot, Tags, CalendarX2 } from "lucide-react";
2
+ import { History, Settings2, Loader2, MessageSquare, RefreshCw, Search, Pencil, Check, X, Pin, PinOff, Trash2, Users, Bot, Tags, CalendarX2 } from "lucide-react";
3
3
  import { Activity } from "lucide-react";
4
4
  import { api, projectUrl } from "@/lib/api-client";
5
5
  import { useTabStore } from "@/stores/tab-store";
@@ -8,7 +8,8 @@ import { cn } from "@/lib/utils";
8
8
  import { AISettingsSection } from "@/components/settings/ai-settings-section";
9
9
  import { TagSettingsSection } from "@/components/settings/tag-settings-section";
10
10
  import { SessionContextMenu } from "./session-context-menu";
11
- import { SessionDebugButton } from "./session-debug-dialog";
11
+ import { SessionDebugDialog } from "./session-debug-dialog";
12
+ import { ChatToolbarOverflowMenu } from "./chat-toolbar-overflow-menu";
12
13
  import { UsageDetailPanel } from "./usage-badge";
13
14
  import { CodexUsagePanel } from "./codex-usage-panel";
14
15
  import { TeamActivityPanel } from "./team-activity-panel";
@@ -82,6 +83,7 @@ export function ChatHistoryBar({
82
83
  const [selectedTagId, setSelectedTagId] = useState<number | null>(null);
83
84
  const [tagCounts, setTagCounts] = useState<Record<number, number>>({});
84
85
  const [showTagSettings, setShowTagSettings] = useState(false);
86
+ const [debugOpen, setDebugOpen] = useState(false);
85
87
  const editInputRef = useRef<HTMLInputElement>(null);
86
88
  const openTab = useTabStore((s) => s.openTab);
87
89
  const PAGE_SIZE = 50;
@@ -273,112 +275,88 @@ export function ChatHistoryBar({
273
275
 
274
276
  return (
275
277
  <div className="border-b border-border/50">
276
- {/* Toolbar row — all buttons on one line */}
278
+ {/* Toolbar row — status chips scroll on the left, controls stay pinned right.
279
+ A narrow chat pane must never push the connection indicator out of view. */}
277
280
  <div className="flex items-center gap-1 px-2 py-1">
278
- {/* History */}
279
- <button
280
- onClick={() => togglePanel("history")}
281
- className={`flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] transition-colors ${
282
- activePanel === "history" ? "text-primary bg-primary/10" : "text-text-secondary hover:text-foreground hover:bg-surface-elevated"
283
- }`}
284
- >
285
- <History className="size-3" />
286
- <span>History</span>
287
- </button>
288
-
289
- {/* Active provider + AI Settings (combined) */}
290
- {sessionId && providerId && providerId !== "mock" ? (
281
+ <div className="flex min-w-0 flex-1 items-center gap-1 overflow-x-auto scrollbar-none">
282
+ {/* History */}
291
283
  <button
292
- onClick={() => togglePanel("config")}
293
- className={`flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] transition-colors ${
294
- activePanel === "config" ? "text-primary bg-primary/10" : "text-text-secondary hover:text-foreground hover:bg-surface-elevated"
284
+ onClick={() => togglePanel("history")}
285
+ className={`shrink-0 flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] transition-colors ${
286
+ activePanel === "history" ? "text-primary bg-primary/10" : "text-text-secondary hover:text-foreground hover:bg-surface-elevated"
295
287
  }`}
296
- title="AI Settings"
297
288
  >
298
- <ProviderBadge providerId={providerId} />
299
- <span className="capitalize">{providerId}</span>
289
+ <History className="size-3" />
290
+ <span>History</span>
300
291
  </button>
301
- ) : (
302
- <button
303
- onClick={() => togglePanel("config")}
304
- className={`p-1 rounded transition-colors ${
305
- activePanel === "config" ? "text-primary bg-primary/10" : "text-text-subtle hover:text-text-secondary hover:bg-surface-elevated"
306
- }`}
307
- title="AI Settings"
308
- >
309
- <Settings2 className="size-3" />
310
- </button>
311
- )}
312
-
313
- {/* Usage & Accounts — Claude and Codex both surface usage + account mgmt here */}
314
- {(isClaudeProvider || isCodexProvider) ? (
315
- <button
316
- onClick={() => togglePanel("usage")}
317
- className={`flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] font-medium tabular-nums transition-colors hover:bg-surface-elevated ${
318
- activePanel === "usage" ? "bg-primary/10" : ""
319
- } ${usageColor}`}
320
- title="Usage limits"
321
- >
322
- <Activity className="size-3" />
323
- {usageInfo.activeAccountLabel && (
324
- <span className="text-text-secondary font-normal truncate max-w-[60px]">[{usageInfo.activeAccountLabel}]</span>
325
- )}
326
- <span>5h:{fiveHourPct != null ? `${fiveHourPct}%` : "--%"}</span>
327
- <span className="text-text-subtle">·</span>
328
- <span>Wk:{sevenDayPct != null ? `${sevenDayPct}%` : "--%"}</span>
329
- </button>
330
- ) : null}
331
-
332
- {/* Team activity */}
333
- {teamActivity?.hasTeams && (
334
- <button
335
- onClick={() => {
336
- togglePanel("team");
337
- onTeamOpen?.();
338
- }}
339
- className={`relative flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] transition-colors ${
340
- activePanel === "team" ? "text-primary bg-primary/10" : "text-text-secondary hover:text-foreground hover:bg-surface-elevated"
341
- }`}
342
- title="Team activity"
343
- >
344
- <Users className="size-3" />
345
- <span>Team</span>
346
- {(teamActivity.unreadCount ?? 0) > 0 && (
347
- <span className="absolute -top-0.5 -right-0.5 size-2 bg-primary rounded-full animate-pulse" />
348
- )}
349
- </button>
350
- )}
351
292
 
352
- {/* Spacer */}
353
- <div className="flex-1" />
293
+ {/* Active provider + AI Settings (combined) */}
294
+ {sessionId && providerId && providerId !== "mock" ? (
295
+ <button
296
+ onClick={() => togglePanel("config")}
297
+ className={`shrink-0 flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] transition-colors ${
298
+ activePanel === "config" ? "text-primary bg-primary/10" : "text-text-secondary hover:text-foreground hover:bg-surface-elevated"
299
+ }`}
300
+ title="AI Settings"
301
+ >
302
+ <ProviderBadge providerId={providerId} />
303
+ <span className="capitalize">{providerId}</span>
304
+ </button>
305
+ ) : (
306
+ <button
307
+ onClick={() => togglePanel("config")}
308
+ className={`shrink-0 p-1 rounded transition-colors ${
309
+ activePanel === "config" ? "text-primary bg-primary/10" : "text-text-subtle hover:text-text-secondary hover:bg-surface-elevated"
310
+ }`}
311
+ title="AI Settings"
312
+ >
313
+ <Settings2 className="size-3" />
314
+ </button>
315
+ )}
354
316
 
355
- {/* Mark as read */}
356
- {hasUnread && sessionId && (
357
- <button
358
- onClick={() => clearForSession(sessionId)}
359
- className="p-1 rounded text-warning hover:text-warning/80 hover:bg-surface-elevated transition-colors"
360
- title="Mark as read"
361
- >
362
- <BellOff className="size-3" />
363
- </button>
364
- )}
317
+ {/* Usage & Accounts — Claude and Codex both surface usage + account mgmt here */}
318
+ {(isClaudeProvider || isCodexProvider) ? (
319
+ <button
320
+ onClick={() => togglePanel("usage")}
321
+ className={`shrink-0 flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] font-medium tabular-nums transition-colors hover:bg-surface-elevated ${
322
+ activePanel === "usage" ? "bg-primary/10" : ""
323
+ } ${usageColor}`}
324
+ title="Usage limits"
325
+ >
326
+ <Activity className="size-3" />
327
+ {usageInfo.activeAccountLabel && (
328
+ <span className="text-text-secondary font-normal truncate max-w-[60px]">[{usageInfo.activeAccountLabel}]</span>
329
+ )}
330
+ <span>5h:{fiveHourPct != null ? `${fiveHourPct}%` : "--%"}</span>
331
+ <span className="text-text-subtle">·</span>
332
+ <span>Wk:{sevenDayPct != null ? `${sevenDayPct}%` : "--%"}</span>
333
+ </button>
334
+ ) : null}
365
335
 
366
- {/* Mark as unread */}
367
- {!hasUnread && sessionId && (
368
- <button
369
- onClick={() => markUnread(sessionId, projectName)}
370
- className="p-1 rounded text-primary hover:text-primary/80 hover:bg-surface-elevated transition-colors"
371
- title="Mark as unread"
372
- >
373
- <Circle className="size-3 fill-current" />
374
- </button>
375
- )}
336
+ {/* Team activity */}
337
+ {teamActivity?.hasTeams && (
338
+ <button
339
+ onClick={() => {
340
+ togglePanel("team");
341
+ onTeamOpen?.();
342
+ }}
343
+ className={`shrink-0 relative flex items-center gap-1 px-1.5 py-0.5 rounded text-[11px] transition-colors ${
344
+ activePanel === "team" ? "text-primary bg-primary/10" : "text-text-secondary hover:text-foreground hover:bg-surface-elevated"
345
+ }`}
346
+ title="Team activity"
347
+ >
348
+ <Users className="size-3" />
349
+ <span>Team</span>
350
+ {(teamActivity.unreadCount ?? 0) > 0 && (
351
+ <span className="absolute -top-0.5 -right-0.5 size-2 bg-primary rounded-full animate-pulse" />
352
+ )}
353
+ </button>
354
+ )}
376
355
 
377
- {/* Debug info — copy session IDs + JSONL path */}
378
- {sessionId && (
379
- <SessionDebugButton sessionId={sessionId} projectName={projectName} />
380
- )}
356
+ </div>
381
357
 
358
+ {/* Pinned controls — always visible, never scrolled away */}
359
+ <div className="flex shrink-0 items-center gap-1 pl-1">
382
360
  {/* Reload messages + connection status */}
383
361
  {onReload && (
384
362
  <button
@@ -397,8 +375,27 @@ export function ChatHistoryBar({
397
375
  <span className={`absolute -top-0.5 -right-0.5 size-1.5 rounded-full ${isConnected ? "bg-success" : "bg-error animate-pulse"}`} />
398
376
  </button>
399
377
  )}
378
+
379
+ {/* Overflow menu — session actions, and the home for future toolbar actions */}
380
+ {sessionId && (
381
+ <ChatToolbarOverflowMenu
382
+ hasUnread={hasUnread}
383
+ onToggleUnread={() => hasUnread ? clearForSession(sessionId) : markUnread(sessionId, projectName)}
384
+ onOpenDebug={() => setDebugOpen(true)}
385
+ />
386
+ )}
387
+ </div>
400
388
  </div>
401
389
 
390
+ {sessionId && (
391
+ <SessionDebugDialog
392
+ sessionId={sessionId}
393
+ projectName={projectName}
394
+ open={debugOpen}
395
+ onOpenChange={setDebugOpen}
396
+ />
397
+ )}
398
+
402
399
  {/* Panels — only one visible at a time */}
403
400
 
404
401
  {/* History panel */}
@@ -0,0 +1,57 @@
1
+ import { BellOff, Bug, Circle, MoreHorizontal } from "lucide-react";
2
+ import {
3
+ DropdownMenu,
4
+ DropdownMenuContent,
5
+ DropdownMenuItem,
6
+ DropdownMenuTrigger,
7
+ } from "@/components/ui/dropdown-menu";
8
+
9
+ /**
10
+ * Session actions that do not earn permanent space in the chat toolbar.
11
+ *
12
+ * The toolbar's left zone scrolls once the chat panel gets narrow, so every
13
+ * control pinned on the right competes for the handful of pixels that stay
14
+ * visible. Only the connection indicator earns that spot; infrequent actions
15
+ * live behind this trigger, which is also where future toolbar actions belong.
16
+ */
17
+ export function ChatToolbarOverflowMenu({
18
+ hasUnread,
19
+ onToggleUnread,
20
+ onOpenDebug,
21
+ }: {
22
+ hasUnread: boolean;
23
+ onToggleUnread: () => void;
24
+ onOpenDebug: () => void;
25
+ }) {
26
+ return (
27
+ <DropdownMenu>
28
+ <DropdownMenuTrigger asChild>
29
+ <button
30
+ type="button"
31
+ className="flex items-center justify-center size-5 rounded text-text-subtle hover:text-text-secondary hover:bg-surface-elevated transition-colors"
32
+ title="More actions"
33
+ aria-label="More actions"
34
+ >
35
+ <MoreHorizontal className="size-3.5" />
36
+ </button>
37
+ </DropdownMenuTrigger>
38
+ {/* Anchored above: this toolbar sits at the bottom of the chat pane. */}
39
+ <DropdownMenuContent align="end" side="top" className="min-w-[190px]">
40
+ <DropdownMenuItem onClick={onToggleUnread} className="max-md:py-3">
41
+ {hasUnread ? (
42
+ <>
43
+ <BellOff className="size-3.5 text-warning" /> Mark as read
44
+ </>
45
+ ) : (
46
+ <>
47
+ <Circle className="size-3.5 fill-current text-primary" /> Mark as unread
48
+ </>
49
+ )}
50
+ </DropdownMenuItem>
51
+ <DropdownMenuItem onClick={onOpenDebug} className="max-md:py-3">
52
+ <Bug className="size-3.5" /> Session debug info
53
+ </DropdownMenuItem>
54
+ </DropdownMenuContent>
55
+ </DropdownMenu>
56
+ );
57
+ }
@@ -308,15 +308,30 @@ function TurnUsageHistory({ sessionId, projectName }: { sessionId: string; proje
308
308
  );
309
309
  }
310
310
 
311
- /** Toolbar button opening the session's debug facts and transcript maintenance. */
312
- export function SessionDebugButton({ sessionId, projectName }: { sessionId: string; projectName: string }) {
313
- const [open, setOpen] = useState(false);
311
+ /**
312
+ * Session debug facts and transcript maintenance.
313
+ *
314
+ * Controlled by the caller so the trigger can live anywhere — including inside a
315
+ * dropdown menu, which unmounts its own items on select and would take an
316
+ * internally-owned dialog down with them.
317
+ */
318
+ export function SessionDebugDialog({
319
+ sessionId,
320
+ projectName,
321
+ open,
322
+ onOpenChange,
323
+ }: {
324
+ sessionId: string;
325
+ projectName: string;
326
+ open: boolean;
327
+ onOpenChange: (open: boolean) => void;
328
+ }) {
314
329
  const [info, setInfo] = useState<string | null>(null);
315
330
  const [copied, setCopied] = useState(false);
316
331
  const isMobile = useIsMobile();
317
332
 
318
- const openPopup = () => {
319
- setOpen(true);
333
+ useEffect(() => {
334
+ if (!open) return;
320
335
  setCopied(false);
321
336
  setInfo(null);
322
337
  api.get<DebugInfo>(
@@ -333,7 +348,7 @@ export function SessionDebugButton({ sessionId, projectName }: { sessionId: stri
333
348
  ...gatherRenderStats(),
334
349
  ].filter(Boolean).join("\n"));
335
350
  }).catch(() => setInfo("Failed to load debug info"));
336
- };
351
+ }, [open, sessionId, projectName]);
337
352
 
338
353
  const copy = () => {
339
354
  if (!info) return;
@@ -365,27 +380,20 @@ export function SessionDebugButton({ sessionId, projectName }: { sessionId: stri
365
380
  </div>
366
381
  );
367
382
 
383
+ if (isMobile) {
384
+ return (
385
+ <BottomSheet open={open} onClose={() => onOpenChange(false)} className="popover-solid">
386
+ <div className="max-h-[85vh] overflow-y-auto px-4 pb-4 pt-1">{body}</div>
387
+ </BottomSheet>
388
+ );
389
+ }
390
+
368
391
  return (
369
- <>
370
- <button
371
- onClick={openPopup}
372
- className="p-1 rounded text-text-subtle hover:text-text-secondary hover:bg-surface-elevated transition-colors"
373
- title="Session debug info"
374
- >
375
- <Bug className="size-3" />
376
- </button>
377
- {isMobile ? (
378
- <BottomSheet open={open} onClose={() => setOpen(false)} className="popover-solid">
379
- <div className="max-h-[85vh] overflow-y-auto px-4 pb-4 pt-1">{body}</div>
380
- </BottomSheet>
381
- ) : (
382
- <Dialog open={open} onOpenChange={setOpen}>
383
- <DialogContent className="sm:max-w-lg">
384
- <DialogTitle className="sr-only">Session debug info</DialogTitle>
385
- {body}
386
- </DialogContent>
387
- </Dialog>
388
- )}
389
- </>
392
+ <Dialog open={open} onOpenChange={onOpenChange}>
393
+ <DialogContent className="sm:max-w-lg">
394
+ <DialogTitle className="sr-only">Session debug info</DialogTitle>
395
+ {body}
396
+ </DialogContent>
397
+ </Dialog>
390
398
  );
391
399
  }