@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,214 @@
1
+ # Integrations (PPMBot, Jira)
2
+
3
+ > Part of the [PPM system architecture](../system-architecture.md).
4
+
5
+ ## PPMBot Coordinator Service Layer (Telegram-based Team Leader)
6
+ **Component:** PPMBot coordinator orchestrator + delegation executor
7
+
8
+ **Responsibilities:**
9
+ - Manage single persistent coordinator session per Telegram chat in `~/.ppm/bot/` workspace
10
+ - Route incoming Telegram messages to coordinator (ask/answer) or delegation tracking
11
+ - Decide when to answer directly vs. delegate to subagents (based on project context)
12
+ - Execute delegated tasks in isolated project sessions
13
+ - Track task status and report results back to Telegram
14
+ - Format responses as Telegram HTML with progressive message editing
15
+
16
+ **Architecture:**
17
+ ```
18
+ Telegram → PPMBotTelegramService (polling) → PPMBotService (orchestrator)
19
+
20
+ PPMBotSessionManager (coordinator session per chat)
21
+ coordinatorSession.id → chatService.sendMessage()
22
+ Task Poller (5s interval)
23
+
24
+ executeDelegation(taskId, telegram, providerId)
25
+ ├─ getBotTask(taskId) → prompt
26
+ ├─ chatService.createSession(providerId, projectPath)
27
+ ├─ run async generator (abort, 900s timeout)
28
+ └─ updateBotTaskStatus(taskId, "completed", {result})
29
+
30
+ telegram.sendMessage(chatId, result summary)
31
+ ```
32
+
33
+ **Services (src/services/ppmbot/):**
34
+ - **PPMBotService** — Lifecycle (start/stop), message queue, Telegram polling loop, task poller loop
35
+ - **PPMBotSessionManager** — Coordinator session cache per chatID, project resolver (case-insensitive, prefix match)
36
+ - **PPMBotTelegramService** — Telegram Bot API (getUpdates polling, sendMessage, editMessage, setTyping)
37
+ - **PPMBotMemoryService** — SQLite project memories, contextual recall
38
+ - **executeDelegation()** — Task execution in isolated session, result capture, timeout/abort handling
39
+ - **PPMBotFormatterService** — Markdown → Telegram HTML, 4096-char chunking
40
+ - **PPMBotStreamerService** — ChatEvent → progressive Telegram message edits (1s throttle)
41
+
42
+ **Coordinator Identity (Persistent Cross-Provider):**
43
+ - Location: `~/.ppm/bot/coordinator.md` (loaded on startup, cached in `coordinatorIdentity`)
44
+ - Role definition: Team leader, project coordinator, decision-maker
45
+ - Decision framework: Answer directly (no project context) vs. Delegate (file access needed)
46
+ - Coordination tools: Bash-safe CLI commands (`ppm bot delegate`, `ppm bot task-status`, etc.)
47
+ - Cross-provider: Identity text injected as XML context block, works with Claude SDK + CLI providers
48
+
49
+ **Delegation Flow:**
50
+ 1. User asks task in Telegram
51
+ 2. Coordinator decides: delegate? → yes
52
+ 3. Coordinator calls bash: `ppm bot delegate --chat <chatId> --project <name> --prompt "<enriched>"`
53
+ 4. CLI creates `bot_tasks` row, returns taskId
54
+ 5. Service tells user: "Working on it, I'll notify you when done"
55
+ 6. Background poller (5s) detects pending task
56
+ 7. Executes: `chatService.createSession()` in target project
57
+ 8. Streams response, captures summary + full output
58
+ 9. Updates task status → "completed"
59
+ 10. Sends Telegram notification with result
60
+
61
+ **Task Execution (Isolation & Safety):**
62
+ - Each task = fresh isolated session (no shared context)
63
+ - Timeout: 900s default (configurable per task)
64
+ - Abort: AbortController on timeout, can be canceled mid-execution
65
+ - Result capture: Both summary (for notification) and full text (for detailed review)
66
+ - Error handling: Task status → "failed", error message stored, user notified
67
+
68
+ **Database Schema (v14):**
69
+ - `bot_tasks` — id (UUID), chatId, projectName, projectPath, prompt, status, resultSummary, resultFull, sessionId, error, reported, timeoutMs, createdAt, startedAt, completedAt
70
+ - Indexes: `idx_bot_tasks_status` (fast poller lookup), `idx_bot_tasks_chat` (history queries)
71
+
72
+ **Key Design Decisions:**
73
+ 1. **Single coordinator session** — Per chat, persistent, one identity (vs. per-task sessions in ClawBot)
74
+ 2. **Delegation via CLI** — Coordinator calls bash commands (safer than direct DB writes, auditable)
75
+ 3. **Isolated task execution** — Each delegated task spawns fresh session (no context bleed)
76
+ 4. **Background polling** — Task execution decoupled from message handler (non-blocking)
77
+ 5. **Result summary + full** — Notification shows short summary; user can fetch full output via CLI
78
+ 6. **Cross-provider identity** — Single `coordinator.md` works with any AI provider
79
+ 7. **Bash-safe tools only** — Coordinator restricted to Bash, Read, Write, Edit, Glob, Grep (safe delegation)
80
+
81
+ **CLI Expansion (ppm bot commands):**
82
+ ```
83
+ ppm bot delegate --chat <id> --project <name> --prompt "<text>" # Create task
84
+ ppm bot task-status <id> # Check status
85
+ ppm bot task-result <id> # Get full output
86
+ ppm bot tasks [--chat <id>] # List recent
87
+ ppm bot project list # Available projects
88
+ ppm bot project current # Active project
89
+ ppm bot project switch <name> # Switch project
90
+ ppm bot session new <title> # Create session
91
+ ppm bot session list # List sessions
92
+ ppm bot session resume <id> # Resume session
93
+ ppm bot session stop <id> # Stop session
94
+ ppm bot status # Bot health
95
+ ppm bot version # PPM version
96
+ ppm bot restart # Restart service
97
+ ppm bot help # Help
98
+ ```
99
+
100
+ **Settings UI (ppmbot-settings-section.tsx):**
101
+ - Enable/disable PPMBot
102
+ - Paired Telegram chats (approval management)
103
+ - Default project selection
104
+ - System prompt customization
105
+ - Task auto-refresh (poll interval, max history)
106
+ - Delegated tasks panel (status, result preview, delete)
107
+
108
+ **Legacy `clawbot` naming:** PPMBot replaced an earlier bot called ClawBot, but the config key and
109
+ its REST surface were never renamed. `config.clawbot` (typed `PPMBotConfig`) and
110
+ `GET|PUT /api/settings/clawbot` configure **PPMBot** — toggling `enabled` there starts or stops
111
+ `ppmbotService`. The old `ClawBotService` / `ClawBotSessionService` / `ClawBotMemoryService` /
112
+ `ClawBotStreamerService` no longer exist; the implementation is `src/services/ppmbot/*`. Treat
113
+ `clawbot` purely as a backward-compatible key name, not as a separate subsystem.
114
+
115
+ ---
116
+
117
+ ## Jira Watcher Auto-Debug Service
118
+ **Component:** Jira Cloud REST API poller + direct Claude debug session orchestrator
119
+
120
+ **Responsibilities:**
121
+ - Poll Jira Cloud per-project on configurable interval (30s–60m)
122
+ - Match issues via JQL filters (status, project key, priority, etc.)
123
+ - Auto-queue or manually trigger direct Claude debug sessions (no bot_task middleman)
124
+ - Manage concurrency: max 2 concurrent, max 1 per project
125
+ - Track results (pending/queued/running/done/failed) with unread status
126
+ - Notify via WS toast + Telegram when analysis completes
127
+ - Rate-limit aware (tracks Jira API quota, auto-backoff 429 responses)
128
+
129
+ **Architecture:**
130
+ ```
131
+ Jira Cloud API ← JiraWatcherService (poller, 30s–60m intervals per watcher)
132
+ ├─ searchIssues(jql) → issue list
133
+ ├─ insertResult() → SQLite jira_watch_results
134
+ └─ jiraDebugService.enqueue() → concurrency queue
135
+
136
+ JiraDebugSessionService (concurrency queue processor)
137
+ ├─ enqueue(resultId, promptOverride?) → validate + queue
138
+ ├─ processQueue() — respects MAX_CONCURRENT=2, MAX_PER_PROJECT=1
139
+ ├─ runDebugSession()
140
+ │ ├─ chatService.createSession(projectPath) — new isolated session
141
+ │ ├─ chatService.sendMessage(prompt) — send with bypassPermissions
142
+ │ ├─ capture lastAssistantText (max 500 chars)
143
+ │ └─ updateResultStatus() + notificationService.broadcastWs("jira:debug_complete")
144
+ └─ cancelDebug(resultId) — abort running session
145
+ ```
146
+
147
+ **Services (src/services/):**
148
+ - **JiraConfigService** — Config CRUD, AES-256 token encryption/decryption, per-project setup
149
+ - **JiraWatcherDbService** — Watchers + results table queries, enabled/disabled toggle, last polled tracking
150
+ - **JiraApiClient** — Jira Cloud REST v3 (search, getIssue, transitions, test connection), rate limit state, backoff logic
151
+ - **JiraWatcherService** — Main poller, timer management (startAll, startWatcher, stopWatcher, pollWatcher), prompt templating, session enqueueing
152
+ - **JiraDebugSessionService** — Concurrency queue, session lifecycle, timeout management, abort handling
153
+
154
+ **Database Schema (v19):**
155
+ - `jira_config` — id, project_id (FK), base_url, email, api_token_encrypted, created_at
156
+ - `jira_watchers` — id, jira_config_id (FK), name, jql, prompt_template, enabled, mode ("debug"|"notify"), interval_ms, last_polled_at, created_at
157
+ - `jira_watch_results` — id, watcher_id, issue_key, issue_summary, issue_updated, session_id (FK chat_sessions.id), status ("pending"|"queued"|"running"|"done"|"failed"), ai_summary, source ("watcher"|"manual"), triggered_by ("auto"|"manual"), read_at (nullable), deleted, created_at
158
+
159
+ **API Routes (src/server/routes/jira*.ts):**
160
+ ```
161
+ POST /api/jira/config — Create/update config (baseUrl, email, token)
162
+ GET /api/jira/config — Get config for active project
163
+ DELETE /api/jira/config — Delete config
164
+ POST /api/jira/config/test — Test Jira connection
165
+ GET /api/jira/watchers — List watchers for config
166
+ POST /api/jira/watchers — Create watcher (name, jql, mode, interval)
167
+ PATCH /api/jira/watchers/:id — Update watcher
168
+ DELETE /api/jira/watchers/:id — Delete watcher (soft delete results)
169
+ POST /api/jira/watchers/:id/enable — Enable/disable watcher
170
+ POST /api/jira/watchers/:id/poll — Trigger poll now
171
+ GET /api/jira/results — List results (paginated, filterable)
172
+ POST /api/jira/results/:id/debug — Manually trigger debug for result (with optional prompt override)
173
+ POST /api/jira/results/:id/read — Mark result as read
174
+ DELETE /api/jira/results/:id — Delete result (soft delete)
175
+ GET /api/jira/search — Search Jira (for filter builder UI)
176
+ GET /api/jira/ticket/:key — Get full ticket details
177
+ GET /api/jira/metadata — Fetch projects, issue types, priorities, statuses
178
+ ```
179
+
180
+ **CLI Commands (src/cli/commands/jira*.ts):**
181
+ ```
182
+ ppm jira config set <project> --url <url> --email <email> --token <token>
183
+ ppm jira config show <project>
184
+ ppm jira config remove <project>
185
+ ppm jira config test <project>
186
+ ppm jira watch add <project> <name> --jql <jql> [--mode debug|notify] [--interval 300000]
187
+ ppm jira watch list <project>
188
+ ppm jira watch enable/disable <project> <watcherId>
189
+ ppm jira watch remove <project> <watcherId>
190
+ ppm jira watch test <project> <watcherId>
191
+ ppm jira watch pull <project> <watcherId>
192
+ ppm jira results list <project> [--limit 50]
193
+ ppm jira results delete <project> <resultId>
194
+ ppm jira track <issue-key> — Manually track ticket (insert result, queue debug)
195
+ ```
196
+
197
+ **Frontend (src/web/components/jira/):**
198
+ - **jira-settings-tab.tsx** — Config form, test button, token input
199
+ - **jira-filter-builder.tsx** — JQL builder UI (projects, issue types, priorities, statuses, custom JQL)
200
+ - **jira-watcher-list.tsx** — List watchers, enable/disable, edit, delete, poll now, interval controls
201
+ - **jira-results-panel.tsx** — Results table (issue key, status, summary, AI summary), unread badge, delete, manual debug button
202
+ - **jira-debug-prompt-dialog.tsx** — Modal for prompt override when manually triggering debug
203
+ - **jira-ticket-detail.tsx** — Modal with full ticket, AI analysis, debug status
204
+ - **jira-store.ts** — Zustand (configs, watchers, results, filters, settings, unread count)
205
+
206
+ **Key Design Decisions:**
207
+ 1. **Direct Claude sessions** — Replaced bot_task flow with direct `chatService.sendMessage()` (simpler, faster, no task overhead)
208
+ 2. **Concurrency queue** — Max 2 concurrent globally, max 1 per project (prevents resource starvation, respects project context)
209
+ 3. **Manual debug trigger** — Users can override watcher prompt and manually queue debug for any pending result
210
+ 4. **Unread tracking** — `read_at` column marks when user views result, UI shows unread badge count
211
+ 5. **Prompt templating** — Support {issue_key}, {summary}, {description}, {status}, {priority} placeholders in watcher templates
212
+ 6. **Timeout protection** — 10-minute timeout with AbortController graceful cleanup and error capture
213
+ 7. **WS notifications** — `jira:debug_complete` event streamed to UI for instant toast feedback
214
+ 8. **Soft deletes** — Results marked deleted=1 (preserve history, don't lose tracking)
@@ -0,0 +1,391 @@
1
+ # Workspace & UI
2
+
3
+ > Part of the [PPM system architecture](../system-architecture.md).
4
+
5
+ ## File Service & Filtering (Lazy-Load Tree, Palette Index)
6
+
7
+ **Component:** FileFilterService + API endpoints `/files/list`, `/files/index`, settings endpoints
8
+
9
+ **Overview:** Provides efficient file discovery with VS Code-style glob filtering and gitignore support. Three-layer filter precedence enforces consistent exclude patterns across tree navigation and search indexing.
10
+
11
+ **Filter Precedence (evaluated low-to-high):**
12
+ 1. **Hardcoded defaults** — `node_modules/**`, `.git`, `.env*` (always excluded, cannot override)
13
+ 2. **Global config** — `files.exclude`, `files.searchExclude`, `files.useIgnoreFiles` (applies to all projects)
14
+ 3. **Per-project override** — Project-scoped settings (DB: `projects.settings` JSON, schema v21) override global
15
+
16
+ **API Endpoints:**
17
+ ```
18
+ GET /api/project/:name/files/list?path=<rel>
19
+ → 1-level directory children with gitignore decoration (isIgnored field)
20
+ → { items: [{ name, type, isDir, isIgnored }], ... }
21
+
22
+ GET /api/project/:name/files/index
23
+ → Flat full-project file list (cached in memory, watcher-invalidated)
24
+ → { files: [{ path, isIgnored }], ... }
25
+
26
+ GET /api/settings/files
27
+ → Global file filter config (all projects)
28
+ → { filesExclude: [], searchExclude: [], useIgnoreFiles: bool }
29
+
30
+ PATCH /api/settings/files
31
+ → Update global config (partial: only specified fields)
32
+ → Validates arrays ≤200 items, filters non-string patterns
33
+
34
+ GET /api/project/:name/settings
35
+ → Per-project settings (includes file filter overrides)
36
+ → { filesExclude?: [], searchExclude?: [], useIgnoreFiles?: bool, ... }
37
+
38
+ PATCH /api/project/:name/settings
39
+ → Per-project override (stored in projects.settings JSON, schema v21)
40
+ → Same validation as global, caches invalidation on write
41
+ ```
42
+
43
+ **Filtering Model:**
44
+
45
+ | Config | Applies To | Validation | Notes |
46
+ |--------|-----------|------------|-------|
47
+ | `filesExclude` | Tree navigation | Glob patterns (max 200) | Hides from tree explorer |
48
+ | `searchExclude` | Index + palette search | Glob patterns (max 200) | Hides from search results |
49
+ | `useIgnoreFiles` | Both (when true) | Boolean | Include `.gitignore` + `.git/info/exclude` in filtering |
50
+
51
+ **Frontend Integration:**
52
+ - `useFileStore()` hook manages lazy-loading: `loadRoot()`, `loadChildren()`, `loadIndex()`
53
+ - AbortController pool cancels pending requests on project switch
54
+ - File tree auto-expands root (1 level), children load on-demand with spinner
55
+ - Command palette + chat file-picker switched from tree-flattening to `fileIndex` from store
56
+ - "Indexing project…" hint shown when `loadIndex()` is pending
57
+
58
+ **Server-Side Implementation:**
59
+ - `FileFilterService.mergeFilters()` — Combine hardcoded + global + project overrides with precedence
60
+ - `FileFilterService.isPathIgnored()` — Check if path matches any exclude pattern (gitignore if enabled)
61
+ - `FileService.list()` — 1-level enumeration with `isIgnored` field computed per item
62
+ - In-memory `indexCache` (Map: projectName → FileIndex) invalidated by `fs.watch` (file changes) + manual `invalidateIndexCache()` calls
63
+ - WS `file:changed` events routed to `invalidateFolder()` or `invalidateIndex()` depending on scope
64
+
65
+ **Database Schema (v21+):**
66
+ ```typescript
67
+ // projects table gains:
68
+ settings: TEXT // JSON: { filesExclude?, searchExclude?, useIgnoreFiles? }
69
+
70
+ // Example:
71
+ projects.settings = JSON.stringify({
72
+ filesExclude: ["**/.venv", "**/*.pyc"],
73
+ searchExclude: ["**/node_modules"],
74
+ useIgnoreFiles: false
75
+ })
76
+ ```
77
+
78
+ **Deprecated:** `/api/project/:name/files/tree` (marked @deprecated, still functional for backward compat)
79
+
80
+ ---
81
+
82
+ ## Project Workspace Management
83
+
84
+ ### Keep-Alive Pattern (v2.0+)
85
+ When switching projects, workspaces are preserved instead of destroyed:
86
+ 1. **Workspace Mount State**: Each project's UI (tabs, terminal xterm DOM, file selections) remains mounted in the DOM
87
+ 2. **Visibility Toggle**: CSS `display: none/block` hides/shows workspaces instead of React unmounting
88
+ 3. **Terminal DOM Persistence**: xterm.js terminal instances retain their DOM structure across switches (prevents re-render flicker)
89
+ 4. **Cache Efficiency**: Zustand stores persist open tabs, selections, and scroll positions per project
90
+
91
+ **Benefits:**
92
+ - Instant project switching (no DOM reconstruction)
93
+ - Terminal history preserved across switches
94
+ - Smooth UX without flashing/re-rendering
95
+ - Reduced network requests (cached UI state)
96
+
97
+ ### Project Color, Avatar & Ordering (v2.0+)
98
+ **Storage**:
99
+ - Colors stored as optional `color` field in `Project` interface (hex string or undefined)
100
+ - Custom avatar images stored content-addressed at `~/.ppm/avatars/<sha256>.webp` via AvatarStorageService
101
+
102
+ **Endpoints:**
103
+ - `PATCH /api/projects/:name/color` — Update project color
104
+ - `POST /api/projects/:name/image` — Upload avatar (multipart, 2MB cap, client resizes to 128×128 webp 0.85)
105
+ - `GET /api/projects/:name/image` — Stream avatar (immutable cache headers, path-traversal safe)
106
+ - `DELETE /api/projects/:name/image` — Remove avatar (reverts to color+initials)
107
+ - `PATCH /api/projects/reorder` — Reorder projects array in config
108
+
109
+ **UI Components:**
110
+ - `ProjectBar` (52px sidebar) — Shows project avatars (custom image or color+initials), context menu for reorder/rename/delete/color-picker/change-image
111
+ - `ProjectBottomSheet` (mobile) — Bottom sheet switcher with long-press menu ("Change Image"/"Remove Image")
112
+ - `ProjectAvatar` component — Renders `<img>` with token auth + cache-bust query param, fallback to color+initials on missing/error
113
+ - `PROJECT_PALETTE` — 12-color palette for default colors when not customized
114
+
115
+ **Avatar Upload & Caching:**
116
+ - Client: canvas center-crop to 128×128, export as webp 0.85 quality (via `resize-image.ts`)
117
+ - Validation: MIME type (image/png, image/jpeg, image/webp, image/avif), file size ≤10MB
118
+ - Server: SHA256 hash for deduplication (same image across projects = same file)
119
+ - Cleanup: Deleted on project remove, preserved across rename (updated in project metadata)
120
+ - Auth: Token in URL query param allows `<img>` to load when auth enabled
121
+ - Cache: Immutable headers (max-age=31536000) + `?v=hash` cache-bust for updates
122
+
123
+ ---
124
+
125
+ ## Code Editor Migration (v2.0+)
126
+
127
+ **Migration**: CodeMirror 6 → Monaco Editor (@monaco-editor/react)
128
+
129
+ **Reasons:**
130
+ - Better syntax highlighting for complex languages
131
+ - Superior IntelliSense and code completion
132
+ - Performance improvements on large files
133
+ - More polished diff viewer experience
134
+
135
+ **Components Updated:**
136
+ - `src/web/components/editor/code-editor.tsx` — Monaco Editor with language detection
137
+ - `src/web/components/editor/diff-viewer.tsx` — Monaco diff viewer for git diffs
138
+
139
+ **Features:**
140
+ - Alt+Z toggle for word wrap
141
+ - Automatic language detection from file extension
142
+ - Theme sync with app dark/light mode
143
+ - Responsive layout with proper scrolling
144
+
145
+ ---
146
+
147
+ ## Terminal Flow
148
+
149
+ ```
150
+ User clicks Terminal tab
151
+
152
+ TerminalTab.tsx mounts
153
+
154
+ useTerminal hook opens WebSocket: WS /ws/project/:name/terminal/:id
155
+
156
+ TerminalService.spawn() creates PTY (Bun.spawn)
157
+
158
+ xterm.js renders terminal emulator
159
+
160
+ User types: "npm test"
161
+
162
+ xterm.js captures key event
163
+
164
+ Sends via WebSocket: { type: "input", data: "npm test\n" }
165
+
166
+ TerminalService.write(pty, "npm test\n")
167
+
168
+ npm process spawned inside PTY
169
+
170
+ Output captured: "PASS: all tests\n"
171
+
172
+ TerminalService sends: { type: "output", data: "PASS: all tests\n" }
173
+
174
+ xterm.js renders output
175
+
176
+ User resizes window → xterm.js resizes terminal
177
+
178
+ Sends: { type: "resize", cols: 120, rows: 40 }
179
+
180
+ TerminalService calls pty.resize()
181
+
182
+ Shell (bash/zsh) receives SIGWINCH signal
183
+
184
+ Terminal state updated
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Git Integration Flow
190
+
191
+ ```
192
+ User right-clicks file in FileTree
193
+
194
+ Context menu shows "Stage" option
195
+
196
+ User clicks "Stage"
197
+
198
+ FileActions.tsx calls POST /api/project/:name/git/stage
199
+
200
+ Sends: { path: "src/index.ts" }
201
+
202
+ GitService.stage(projectPath, "src/index.ts")
203
+
204
+ Executes: git add src/index.ts (via simple-git)
205
+
206
+ Returns: { ok: true }
207
+
208
+ GitStatusPanel.tsx refreshes: GET /api/project/:name/git/status
209
+
210
+ GitService.status() returns:
211
+ {
212
+ current: "main",
213
+ staged: ["src/index.ts"],
214
+ unstaged: ["README.md"],
215
+ untracked: ["temp.log"]
216
+ }
217
+
218
+ UI updates: "src/index.ts" moves from "Unstaged" to "Staged"
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Frontend Performance Optimization (v0.9.86+)
224
+
225
+ ### Memory & Re-Render Reduction
226
+
227
+ **1. useShallow Pattern (Zustand)**
228
+ - All destructured store selectors wrapped in `useShallow()` (36 sites)
229
+ - Prevents unnecessary re-renders when object properties mutate
230
+ - Example: `const { messages, addMessage } = chatStore(useShallow(...))`
231
+
232
+ **2. Component Memoization (React.memo)**
233
+ - 10 heavy components wrapped (CodeEditor, MessageBubble, ProjectBar, ProjectAvatar, TerminalTab, PanelLayout, Sidebar, StatusBar, StatusBarEntry, TabBar, TreeNode)
234
+ - Memoization skips re-renders if props unchanged
235
+ - Paired with `useCallback` to maintain stable references
236
+
237
+ **3. Lazy Loading**
238
+ - MarkdownRenderer lazy-loaded from 3 sites (reduces initial bundle)
239
+ - CodeMirror on-demand in postgres-viewer
240
+ - Mermaid diagram support loaded dynamically only when diagram syntax detected
241
+
242
+ **4. Code Splitting (vite.config.ts)**
243
+ - 5 vendor chunks: `vendor-monaco`, `vendor-mermaid`, `vendor-xterm`, `vendor-markdown`, `vendor-ui`
244
+ - Heavy libraries (>500KB) in separate chunks for better browser caching
245
+ - Each chunk independently cacheable and updated
246
+
247
+ **5. Chat Pagination & Message Caps**
248
+ - Chat history loads 50 messages per page with load-more button (prevents DOM bloat)
249
+ - Team activity capped at 500 messages (prevents unbounded growth)
250
+
251
+ ### Benefits
252
+ - Faster page load (lazy chunks load on-demand)
253
+ - Reduced re-render cycles (useShallow + memo)
254
+ - Lower memory footprint (capped message buffers)
255
+ - Better caching (vendor chunk stability across versions)
256
+
257
+ ---
258
+
259
+ ## OS File Explorer Window
260
+
261
+ A floating, OS-skinned window (Windows 11 / macOS Finder chrome, Linux → macOS skin) that browses
262
+ the **whole host filesystem** — not just registered project directories — through the widened
263
+ `/api/fs` family. This is a deliberate scope change from every other file-facing route in PPM
264
+ (project-scoped, path-validated against one repo root): the explorer's authorization boundary is
265
+ "the whole disk, behind PPM's existing session auth", not "one project".
266
+
267
+ ### FS scope = auth boundary
268
+
269
+ Every `/api/fs` route — including `docx-html`, `read`, `raw`, both SQLite doors — passes through
270
+ one shared guard chain (`src/services/fs-path-guard.service.ts`) before touching disk:
271
+
272
+ | Protection | Mechanism |
273
+ |---|---|
274
+ | PPM-dir shield | `assertNotPpmDir` refuses `getPpmDir()` (config, auth token, credentials) as a source **or** destination of any read or mutation, checked at both the given path and its resolved realpath (defeats a symlink pointed at the PPM dir) |
275
+ | Protected roots | `/`, drive roots (`C:\`), `$HOME` and the PPM dir itself refuse delete/rename/move as a source |
276
+ | Download tokens | `/api/fs/download/token` issues a single-use, path-bound token; `/api/fs/raw` spends it on first use, rejects replay and any path mismatch |
277
+ | Symlink safety | every op `lstat`s the entry itself (never follows to the target) so a link *to* a protected path can itself still be deleted, but nothing can read/write *through* one into the PPM dir |
278
+ | SQL injection surface | the external-DB doors (`/api/fs/sqlite/*`) block `ATTACH`/`DETACH` by keyword scan (after stripping comments/string literals) before executing any query — the same class of guard the project-scoped `/sqlite` route also needed |
279
+ | No event-loop blocking | every op is `fs.promises`-based with bounded concurrency and a per-entry timeout — a dead network mount or sleeping USB drive cannot stall unrelated requests, which matters once scope is the whole disk instead of one project |
280
+
281
+ ### API surface
282
+
283
+ | Method | Path | Purpose |
284
+ |---|---|---|
285
+ | GET | `/api/system/host` | `HostInfo`: platform, path separator, homedir, drives, known folders, OS-pinned folders (Quick Access / Finder Favorites / GTK+KDE bookmarks), warnings |
286
+ | GET | `/api/fs/browse` | Directory listing (existing route, whitelist widened to `/`) |
287
+ | GET | `/api/fs/stat` | Single-entry metadata |
288
+ | POST | `/api/fs/copy` \| `/move` \| `/rename` \| `/touch` \| `/mkdir` | Mutations, collision (`EEXIST`)/self-nesting (`EINVAL`) reported for the client to resolve |
289
+ | DELETE | `/api/fs/delete` \| `/rmdir` | `{permanent?}` — OS trash (Recycle Bin / Trash / gio) by default, permanent on request |
290
+ | POST/GET | `/api/fs/download/token` / `/api/fs/raw` | Single-use, path-bound download |
291
+ | GET/POST | `/api/fs/sqlite/{tables,schema,data,query}` | External `.db` viewer — same shape as the project-scoped `/sqlite` route, `path` absolute, PPM dir refused |
292
+
293
+ `host-info.service.ts` orchestrates three OS-specific provider sets (`src/services/host-info/`)
294
+ behind a 60s cache with in-flight de-duplication (concurrent `?refresh=true` calls share one
295
+ rebuild rather than spawning N PowerShell/plutil/findmnt processes).
296
+
297
+ ### Floating window layer
298
+
299
+ `src/web/components/floating-window/` — a content-agnostic window manager (zustand store):
300
+ drag/8-handle-resize gestures write geometry straight to the DOM element (no React re-render per
301
+ pointermove), committing to the store only on gesture end; rect + open windows persist to
302
+ `localStorage["ppm-windows"]`, restored once per app load and re-clamped to the current viewport.
303
+
304
+ Windows render in a portal at **z-30..38** (`30 + rank`, capped at an 8-window dense-rank limit) —
305
+ below the app's existing `z-40` click-away backdrops and `z-50` Radix layers, so command palette,
306
+ dropdowns and dialogs always stay reachable above any number of open explorer windows. Below the
307
+ `md` breakpoint the layer never mounts at all; `src/web/components/os-explorer/mobile/` renders the
308
+ same `ExplorerBody` component inside a full-screen bottom sheet instead (`variant="sheet"`).
309
+ Drag and resize share a `gestureAbandoned()` guard (`use-window-gesture-context.ts`) for the
310
+ pointer-up that still arrives after a mid-gesture window close (e.g. dragging by a titlebar button
311
+ that closes the frame).
312
+
313
+ **One chrome, every kind.** `WindowSkinChrome` (`window-skin-chrome.tsx`) is the titlebar every
314
+ window kind — explorer, team-member session, system monitor, detached tab — renders: it resolves
315
+ the active OS skin via `useExplorerSkin()` (Settings override, else host platform; Linux → macOS)
316
+ and delegates to that skin's `WindowsWindowChrome` / `MacosWindowChrome`
317
+ (`src/web/components/os-explorer/skins/`), scoped entirely through `[data-skin="windows"|"macos"]`
318
+ CSS variables layered over PPM's existing semantic theme tokens — no second color table. The
319
+ Windows skin's folder glyph draws only for `kind === "explorer"`; every other kind gets the bare
320
+ titlebar. The macOS skin boxes the title between the traffic lights and the PiP button as a flex
321
+ child (so a long title truncates instead of overlapping either), and puts the PiP button at the
322
+ titlebar's right end; the Windows skin puts it left of minimize.
323
+
324
+ **PiP is a capability of the frame, not of one kind.** `useWindowBodyElement`
325
+ (`use-window-body-element.ts`) creates the single DOM element `FloatingWindow` portals a window's
326
+ content into and publishes it as that window's PiP slot (`window-pip-registry.ts`, keyed by window
327
+ id). `PipCaptionButton` (`pip/pip-caption-button.tsx`), rendered by both skins, moves that slot into
328
+ a `documentPictureInPicture` window and back; it is absent (not disabled) where the API is
329
+ unsupported. `WindowPipPlaceholder` (`window-pip-placeholder.tsx`) takes the body's place in the
330
+ frame while it plays in PiP, with a ≥44px "Bring back" control. The mechanics below (attach/detach,
331
+ style mirroring, key forwarding, resize signalling) apply to whichever window kind currently owns
332
+ the slot — a tab-host window is only the one kind whose body is itself a portal target for another
333
+ component (`TabPool`).
334
+
335
+ #### Tab-host windows (detaching a tab into its own window)
336
+
337
+ - **Off-grid panel.** Detaching creates `` `__win__:${windowId}` `` (`windowPanelId()`,
338
+ `stores/panel-utils.ts`) — same treatment as `__dock__`: lives in `panels`, never in `grid`, so no
339
+ grid math (rows/columns/split) sees it. `stores/window-panel-actions.ts` is the only writer of
340
+ these panels and enforces the paired invariant: `focusedPanelId` never points at one (it would
341
+ send the next `openTab()` with no explicit panel into a window). `popOutTab`/`redockFromWindow`
342
+ create and destroy the panel and its window together; every close path (titlebar ×, keyboard,
343
+ reconcile) routes through `redockFromWindow`, which re-docks to the origin panel if it is still in
344
+ the grid, else the focused grid panel, else the first grid panel. All tab types pop out except
345
+ `system-monitor`, which already has its own window kind.
346
+ - **No-remount move.** `TabPool` (`components/layout/tab-pool.tsx`) mounts every tab once into a
347
+ wrapper `div[data-tab-pool-id]` created imperatively in `ReparentingTab`
348
+ (`components/layout/reparenting-tab.tsx`) and rendered into it via `createPortal` — React attaches
349
+ its listeners to the wrapper itself, so they keep firing after the node moves, including into
350
+ another document. A `useLayoutEffect` with no deps calls `appendChild` to move the wrapper into
351
+ whichever element last registered for the tab's panel id (`slotRegistry`,
352
+ `components/layout/tab-pool-registry.ts`); `TabHostWindowContent`'s slot `div` is always mounted
353
+ (never swapped for a placeholder), because it may currently be living inside the PiP document.
354
+ - **Persistence.** Window panels persist to their own global `localStorage["ppm-window-panels"]`
355
+ key (`stores/window-panel-persistence.ts`), separate from the per-project `ppm-panels-*` blob and
356
+ not synced to the server — the same limitation window geometry (`ppm-windows`) already has.
357
+ `WINDOW_KINDS` (`window-store-types.ts`) is the single list both the window store and
358
+ `window-persistence.ts` filter against; `team-member` is excluded from restore because its body
359
+ streams a live subagent session that cannot survive a reload.
360
+ - **Reconcile.** The two halves persist separately, so a reload can restore one without the other.
361
+ `reconcileTabHostWindows` (`stores/window-panel-reconcile.ts`), run once per project via
362
+ `useWindowPanelReconcile()` after the window layer restores, and unconditionally below `md` (the
363
+ window layer never mounts there): a panel whose window is gone comes back to the grid; a window
364
+ with no panel behind it closes.
365
+ - **PiP host.** `attachPipHost`/`isDocumentPipSupported` (`floating-window/pip/pip-host.ts`,
366
+ `pip-support.ts`) move a window's *slot* element — never a tab's own wrapper — into a
367
+ `documentPictureInPicture` window, one at a time per page. `pagehide` triggers a synchronous
368
+ restore (no `await` between it and the DOM move) so a closing PiP document never strips listeners
369
+ off a still-live terminal. `pip-style-copy.ts` mirrors stylesheets + `adoptedStyleSheets` once and
370
+ `<html>` class/inline theme CSS vars + `<body>` class **and inline style** on every theme change
371
+ (the page background is an inline `background: var(--bg)` on `<body>` in `index.html`, not a
372
+ class), plus a MutationObserver for Vite HMR-injected `<style>` tags. `pip-key-forward.ts`
373
+ re-dispatches keydown/keyup from the PiP window onto the main window for app-level shortcuts,
374
+ skipping targets that own their own input (`input`, `.monaco-editor`, `.xterm-helper-textarea`,
375
+ etc.). `pip-resize-signal.ts` dispatches a non-bubbling `ppm:host-resize` CustomEvent on each
376
+ `[data-tab-pool-id]` wrapper inside the slot (on attach, every PiP `resize`, and on detach); the
377
+ terminal and editors subscribe via `onHostResize` and re-fit, because main-window
378
+ `ResizeObserver`s are late or silent for a PiP-driven size.
379
+ - **Radix portals in PiP.** `PortalContainerProvider` (`components/ui/portal-container-context.tsx`)
380
+ is mounted inside `ReparentingTab` around each tab's content, fed the PiP document's `body` while
381
+ that tab's window is in PiP (`usePipPortalContainer`, `window-pip-registry.ts`) — so a tab's own
382
+ dropdowns/tooltips/dialogs render inside the PiP document instead of opening unreachably in the
383
+ main window. `undefined` (document default) while docked.
384
+ - **Known limitations** (see the comment block atop `pip/pip-caption-button.tsx`): sonner toasts
385
+ always render in the main window (one app-root toaster); `useIsMobile()`/Tailwind `md:` read the
386
+ main window's viewport, not the PiP window's; `onSelect`/`selectionchange` degrades for PiP
387
+ content; the terminal's reconnect check reads the main document's visibility; Monaco keybindings
388
+ (Ctrl+Z, Ctrl+F, …) don't fire while the editor sits in PiP (typing still reaches the buffer); a
389
+ tab-host window's titlebar keeps the tab title captured at pop-out time.
390
+ - **Mobile.** Pop-out and PiP are hidden entirely below `md` (`useIsMobile()`) — never a scaled-down
391
+ window.
@@ -690,7 +690,7 @@ Simplified interface: `createSession()` → `send()` / `stream()`.
690
690
  ```typescript
691
691
  import { unstable_v2_createSession } from "@anthropic-ai/claude-agent-sdk";
692
692
 
693
- await using session = unstable_v2_createSession({ model: "claude-opus-4-6" });
693
+ await using session = unstable_v2_createSession({ model: "claude-opus-5" });
694
694
 
695
695
  await session.send("Hello!");
696
696
  for await (const msg of session.stream()) {