@hienlh/ppm 0.18.8 → 0.18.9

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 (507) hide show
  1. package/.spike/s.err +63 -0
  2. package/.spike/tunnel.err +42 -0
  3. package/.spike/w.err +96 -0
  4. package/CHANGELOG.md +9 -0
  5. package/CLAUDE.md +1 -0
  6. package/assets/skills/ppm/SKILL.md +1 -1
  7. package/assets/skills/ppm/references/cli-reference.md +4 -4
  8. package/assets/skills/ppm/references/http-api.md +4 -3
  9. package/dist/web/assets/{ai-resource-editor-BydGrxjb.js → ai-resource-editor-DFCuNe-P.js} +1 -1
  10. package/dist/web/assets/{angular-html-jfMqUuRd.js → angular-html-Ctz0zN01.js} +1 -1
  11. package/dist/web/assets/{angular-ts-wytn9PMm.js → angular-ts-QXHpgB1C.js} +1 -1
  12. package/dist/web/assets/{api-settings-DlcoR5QT.js → api-settings-nblja3Rk.js} +1 -1
  13. package/dist/web/assets/{apl-i-ahKx6O.js → apl-b9KVk-O4.js} +1 -1
  14. package/dist/web/assets/architecture-PBZL5I3N-C7ra20CE.js +1 -0
  15. package/dist/web/assets/{astro-DVBCJfG6.js → astro-BlFEeGYr.js} +1 -1
  16. package/dist/web/assets/{audio-preview-DzBGq9Lk.js → audio-preview-CZLmhf__.js} +1 -1
  17. package/dist/web/assets/{blade-BHlL8SqU.js → blade-CGkj2MUI.js} +1 -1
  18. package/dist/web/assets/{bsl-D-UOfR1F.js → bsl-CVsbb6ap.js} +1 -1
  19. package/dist/web/assets/button-BA_fJOtX.js +1 -0
  20. package/dist/web/assets/{cairo-Bn6rucli.js → cairo-BbIHl2iE.js} +1 -1
  21. package/dist/web/assets/chat-tab-flMPLoKb.js +15 -0
  22. package/dist/web/assets/circle-hjUGru6R.js +1 -0
  23. package/dist/web/assets/circle-question-mark-CzR7YRc-.js +1 -0
  24. package/dist/web/assets/{cobol-Byn9FYKu.js → cobol-BWSGjmWb.js} +1 -1
  25. package/dist/web/assets/code-editor-C2VQbXzw.js +10 -0
  26. package/dist/web/assets/{coffee-DjBl4gm-.js → coffee-CWGNOxds.js} +1 -1
  27. package/dist/web/assets/{conflict-editor-CRConSGG.js → conflict-editor-CdH_h0vD.js} +3 -3
  28. package/dist/web/assets/{context-menu-DkQdt6YA.js → context-menu-Cq0u3SK9.js} +1 -1
  29. package/dist/web/assets/{cpp-CKzic-3E.js → cpp-DHGV24J2.js} +1 -1
  30. package/dist/web/assets/{crystal-Bkg-Ly_g.js → crystal-Vlwf2UMP.js} +1 -1
  31. package/dist/web/assets/{csv-preview-BtCGfmrq.js → csv-preview-CY_454vd.js} +1 -1
  32. package/dist/web/assets/{data-grid-overlay-editor-B1mTl3KS.js → data-grid-overlay-editor-D9il5DZS.js} +1 -1
  33. package/dist/web/assets/{database-viewer-2M5sKRqb.js → database-viewer-BCZOTrPT.js} +1 -1
  34. package/dist/web/assets/{diff-viewer-BMr7vOvZ.js → diff-viewer-BwfMN-nW.js} +1 -1
  35. package/dist/web/assets/{docx-preview-BpG2kr_-.js → docx-preview-D3Sdh_aT.js} +1 -1
  36. package/dist/web/assets/{edge-DVbZnd3Y.js → edge-Bhqk64zS.js} +1 -1
  37. package/dist/web/assets/{edit-diff-preview-BivQwZMD.js → edit-diff-preview-gq6ALf2B.js} +1 -1
  38. package/dist/web/assets/{elixir-Dwi8Wu7W.js → elixir-D466WCFm.js} +1 -1
  39. package/dist/web/assets/{elm-DtIv-HXJ.js → elm-Bfs2qNPR.js} +1 -1
  40. package/dist/web/assets/{erb-D3HEDz1x.js → erb-WI7jUaB6.js} +1 -1
  41. package/dist/web/assets/{erlang-2MjTCzGz.js → erlang-BCBe8nCc.js} +1 -1
  42. package/dist/web/assets/{esm-CZ8B8Ba2.js → esm-CZs9WVDO.js} +1 -1
  43. package/dist/web/assets/{explorer-body-DXufyj-9.js → explorer-body-BKOMM566.js} +2 -2
  44. package/dist/web/assets/{explorer-window-content-B3krk4G1.js → explorer-window-content-Bbzijk8t.js} +1 -1
  45. package/dist/web/assets/{extension-webview-12M45CGq.js → extension-webview-CuOQrHIS.js} +1 -1
  46. package/dist/web/assets/format-bytes-Dk7B73B7.js +1 -0
  47. package/dist/web/assets/{fortran-fixed-form-BLyAtyPM.js → fortran-fixed-form-CXLIv8Ox.js} +1 -1
  48. package/dist/web/assets/{fsharp-Bxbn_gbr.js → fsharp-CZsYmiw9.js} +1 -1
  49. package/dist/web/assets/{gdresource-sFMY4D2Q.js → gdresource-BGRvoWfC.js} +1 -1
  50. package/dist/web/assets/{git-commit-BzB9Lio5.js → git-commit-DH6mY3Km.js} +1 -1
  51. package/dist/web/assets/{git-log-panel-Cp4k3tX_.js → git-log-panel-DcV7PhqW.js} +1 -1
  52. package/dist/web/assets/{git-rebase-CKSVd848.js → git-rebase-C5Gql6Ma.js} +1 -1
  53. package/dist/web/assets/gitGraph-HDMCJU4V-D4hYLNJU.js +1 -0
  54. package/dist/web/assets/{glide-data-grid-B0BB0VDl.js → glide-data-grid-Cehfgrzc.js} +7 -7
  55. package/dist/web/assets/{glimmer-js-BY8aExAJ.js → glimmer-js-1-6JMJlj.js} +1 -1
  56. package/dist/web/assets/{glimmer-ts-Bak54dBX.js → glimmer-ts-C_Njj0nK.js} +1 -1
  57. package/dist/web/assets/{glsl-nR2eaJQe.js → glsl-DbkxE1TN.js} +1 -1
  58. package/dist/web/assets/{graphql-CGPPFAU6.js → graphql-BK75fiXl.js} +1 -1
  59. package/dist/web/assets/group-chat-tab-BVPYxjz-.js +1 -0
  60. package/dist/web/assets/{hack-CXIMX-Ol.js → hack-DG151vit.js} +1 -1
  61. package/dist/web/assets/{haml-tPY-9Pfm.js → haml-DKeIPQWM.js} +1 -1
  62. package/dist/web/assets/{handlebars-BuW1LT7T.js → handlebars-398uCI13.js} +1 -1
  63. package/dist/web/assets/{html-bgVcwZ-t.js → html-NLWdst5q.js} +1 -1
  64. package/dist/web/assets/{html-derivative-D6-IxTgn.js → html-derivative-CJf_Le2z.js} +1 -1
  65. package/dist/web/assets/{http-CJ1zyB-h.js → http-G1K2FozA.js} +1 -1
  66. package/dist/web/assets/{hurl-CmoT7l3T.js → hurl-WDC6sSBz.js} +1 -1
  67. package/dist/web/assets/{hxml-CztOsL8o.js → hxml-Dc3jBXuf.js} +1 -1
  68. package/dist/web/assets/{image-preview-3HfuxA0N.js → image-preview-D-Ok10eZ.js} +1 -1
  69. package/dist/web/assets/index-CerSxGdf.js +52 -0
  70. package/dist/web/assets/index-DRA_OpWY.css +2 -0
  71. package/dist/web/assets/info-3K5VOQVL-lRlrTlkb.js +1 -0
  72. package/dist/web/assets/{jinja-B1pq3jJq.js → jinja-CWsQj2y0.js} +1 -1
  73. package/dist/web/assets/{jison-D8B5pCwA.js → jison-CciJg2NW.js} +1 -1
  74. package/dist/web/assets/{julia-D0K3bwpU.js → julia-IOQNJAB7.js} +1 -1
  75. package/dist/web/assets/{just-B9Jlddu-.js → just-BGdHchwS.js} +1 -1
  76. package/dist/web/assets/{keybindings-store-oMJmtpH4.js → keybindings-store-aIY40k2o.js} +1 -1
  77. package/dist/web/assets/{latex-BPJSSE6j.js → latex-D6TOl-L2.js} +1 -1
  78. package/dist/web/assets/{liquid-lv10fo4U.js → liquid-CVSvu_Wn.js} +1 -1
  79. package/dist/web/assets/{lua-PNuaIBEF.js → lua-CcKiU6HW.js} +1 -1
  80. package/dist/web/assets/markdown-renderer-I89kyQhe.js +1 -0
  81. package/dist/web/assets/{markdown-renderer-DPcoPjmO.js → markdown-renderer-pVzBdkpl.js} +3 -3
  82. package/dist/web/assets/{marko-Du3frD6X.js → marko--UOicMGo.js} +1 -1
  83. package/dist/web/assets/{mdc-BeDVcFRl.js → mdc-D690aU2C.js} +1 -1
  84. package/dist/web/assets/{mobile-explorer-sheet-CEVcU964.js → mobile-explorer-sheet-5Uj9ZMM9.js} +1 -1
  85. package/dist/web/assets/{nextflow-DkcXP71s.js → nextflow-DR8PhpF8.js} +1 -1
  86. package/dist/web/assets/{nginx-C5n8N_bt.js → nginx-Qb9pUk1g.js} +1 -1
  87. package/dist/web/assets/{nim-CIhyfs-A.js → nim-DLa8R3NS.js} +1 -1
  88. package/dist/web/assets/{notification-store-B8AqxwRT.js → notification-store-DJ-OtAG3.js} +1 -1
  89. package/dist/web/assets/{number-overlay-editor-NgOsWJ7x.js → number-overlay-editor-D9SkFg1Y.js} +1 -1
  90. package/dist/web/assets/overview-panel-Cgi3UPY1.js +1 -0
  91. package/dist/web/assets/packet-RMMSAZCW-BIhk1mvp.js +1 -0
  92. package/dist/web/assets/{pdf-preview-BslNoDFw.js → pdf-preview-Di5xHFyT.js} +1 -1
  93. package/dist/web/assets/{perl-Cf31sZYE.js → perl-AMNGIneF.js} +1 -1
  94. package/dist/web/assets/{php-Dzl_MDIW.js → php-CDsOOxXn.js} +1 -1
  95. package/dist/web/assets/pie-UPGHQEXC-SLS6i76l.js +1 -0
  96. package/dist/web/assets/{postgres-viewer-BtSXQ3S4.js → postgres-viewer-CR6VpTrX.js} +3 -3
  97. package/dist/web/assets/process-table-DL6shbzt.js +1 -0
  98. package/dist/web/assets/{pug-CxSYHrB3.js → pug-C2kdkhQ6.js} +1 -1
  99. package/dist/web/assets/{qml-DlEjGhwN.js → qml-DRDkUp75.js} +1 -1
  100. package/dist/web/assets/radar-KQ55EAFF-JJ6O1Er_.js +1 -0
  101. package/dist/web/assets/{razor-KVt5uW14.js → razor-wY_6wUeC.js} +1 -1
  102. package/dist/web/assets/{rst-D5BwNTnw.js → rst-BRpofyNs.js} +1 -1
  103. package/dist/web/assets/{ruby-D5fejQwd.js → ruby-ieATBhWm.js} +1 -1
  104. package/dist/web/assets/{sas-Bj7B1CB2.js → sas-CoOOEbOO.js} +1 -1
  105. package/dist/web/assets/{scss-BB0CUoCL.js → scss-_nWV0bsb.js} +1 -1
  106. package/dist/web/assets/{settings-store-C9YT1Hir.js → settings-store-C20lqh0G.js} +2 -2
  107. package/dist/web/assets/settings-tab-jbiQwozX.js +1 -0
  108. package/dist/web/assets/{shaderlab-BdjEZUMc.js → shaderlab-XkqfIfO8.js} +1 -1
  109. package/dist/web/assets/{shellsession-Bp1OA1rR.js → shellsession-BKBIqTlM.js} +1 -1
  110. package/dist/web/assets/{soy-DlYz3wsC.js → soy-oVDnPzzh.js} +1 -1
  111. package/dist/web/assets/{sparql-CdfII5Jd.js → sparql-N2VclEsF.js} +1 -1
  112. package/dist/web/assets/{sql-query-editor-CkvpmXyA.js → sql-query-editor-BPYsJDsn.js} +1 -1
  113. package/dist/web/assets/{sqlite-viewer-CJbP6ruh.js → sqlite-viewer-Bq9ZJA2y.js} +1 -1
  114. package/dist/web/assets/{stata-BvUA6GUW.js → stata-BuuClVDg.js} +1 -1
  115. package/dist/web/assets/{surrealql--DLNbTyI.js → surrealql-DE5_63MS.js} +1 -1
  116. package/dist/web/assets/{svelte-CBfSsG4n.js → svelte--YWjlOrK.js} +1 -1
  117. package/dist/web/assets/system-monitor-body-CKEYWyN9.js +2 -0
  118. package/dist/web/assets/system-monitor-tab-WjhFFHyM.js +1 -0
  119. package/dist/web/assets/system-monitor-window-content-CMiISeoC.js +1 -0
  120. package/dist/web/assets/team-member-sheet-oY5EkH53.js +2 -0
  121. package/dist/web/assets/{team-member-window-content-Cxh-HF2V.js → team-member-window-content-yCBeI_5X.js} +1 -1
  122. package/dist/web/assets/{templ-Dv8zpKZW.js → templ-MlpvJx4a.js} +1 -1
  123. package/dist/web/assets/{terminal-tab-gQCs_fyx.js → terminal-tab-BxHtMR7h.js} +3 -3
  124. package/dist/web/assets/{tex-CsrOiqh1.js → tex-0loAoXJG.js} +1 -1
  125. package/dist/web/assets/{tool-cards-BG2fz83z.js → tool-cards-BcGrk1zk.js} +5 -5
  126. package/dist/web/assets/treemap-KZPCXAKY-Be3KNmns.js +1 -0
  127. package/dist/web/assets/{ts-tags-3T98k4EJ.js → ts-tags-pt-Ug0hK.js} +1 -1
  128. package/dist/web/assets/{twig-u6QZ45FH.js → twig-DOePpLOL.js} +1 -1
  129. package/dist/web/assets/{use-monaco-theme-DaqI7O-a.js → use-monaco-theme-CGucu3fb.js} +1 -1
  130. package/dist/web/assets/{use-open-team-member-DKpstvLS.js → use-open-team-member-DdrRXj-M.js} +1 -1
  131. package/dist/web/assets/{use-websocket-KVhDtbwK.js → use-websocket-C-Rxv8JN.js} +1 -1
  132. package/dist/web/assets/{vendor-mermaid-Bg4vE8QA.js → vendor-mermaid-DrwG0NYt.js} +1 -1
  133. package/dist/web/assets/{video-preview-CVEUDZBj.js → video-preview-DYAbbmd0.js} +1 -1
  134. package/dist/web/assets/{vue-CxIsxtwn.js → vue-D6f-rprj.js} +1 -1
  135. package/dist/web/assets/{vue-html-BGL5qnuH.js → vue-html-DEYRkS1V.js} +1 -1
  136. package/dist/web/assets/{vue-vine-DHPh_gMr.js → vue-vine-CxSG2ojf.js} +1 -1
  137. package/dist/web/assets/{xml-C-vM2m7J.js → xml-DhrxbATj.js} +1 -1
  138. package/dist/web/assets/{xsl-DvTXNwuO.js → xsl-CU0ZndUO.js} +1 -1
  139. package/dist/web/index.html +18 -17
  140. package/dist/web/sw.js +1 -1
  141. package/docs/system-architecture.md +2 -2
  142. package/package.json +1 -1
  143. package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
  144. package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
  145. package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
  146. package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
  147. package/src/server/index.ts +2 -8
  148. package/src/server/routes/resources.ts +119 -73
  149. package/src/services/autostart-generator.ts +79 -7
  150. package/src/services/autostart-register.ts +15 -2
  151. package/src/services/edge-forwarder.ts +191 -191
  152. package/src/services/proc-table-linux.ts +4 -0
  153. package/src/services/redact-secrets.ts +33 -0
  154. package/src/services/system-metrics/cpu-memory-collector.ts +101 -0
  155. package/src/services/system-metrics/disk-net-collector-darwin.ts +75 -0
  156. package/src/services/system-metrics/disk-net-collector-linux.ts +88 -0
  157. package/src/services/system-metrics/disk-net-collector-windows.ts +57 -0
  158. package/src/services/system-metrics/gpu-collector-nvidia.ts +78 -0
  159. package/src/services/system-metrics/gpu-process-memory-nvidia.ts +66 -0
  160. package/src/services/system-metrics/gpu-process-usage-windows.ts +138 -0
  161. package/src/services/system-metrics/kill-executor.ts +85 -0
  162. package/src/services/system-metrics/kill-guard.ts +124 -0
  163. package/src/services/system-metrics/kill-identity-resolver.ts +72 -0
  164. package/src/services/system-metrics/kill-request-handler.ts +79 -0
  165. package/src/services/system-metrics/metrics-collector-lock.ts +36 -0
  166. package/src/services/system-metrics/metrics-poll-scheduler.ts +83 -0
  167. package/src/services/system-metrics/metrics-subscriber-registry.ts +85 -0
  168. package/src/services/system-metrics/powershell-session-bootstrap.ts +48 -0
  169. package/src/services/system-metrics/powershell-session.ts +182 -0
  170. package/src/services/system-metrics/ppm-process-ownership.ts +34 -0
  171. package/src/services/system-metrics/ppm-protected-pids.ts +84 -0
  172. package/src/services/system-metrics/process-collector-darwin.ts +141 -0
  173. package/src/services/system-metrics/process-collector-linux.ts +85 -0
  174. package/src/services/system-metrics/process-collector-types.ts +80 -0
  175. package/src/services/system-metrics/process-collector-windows-parse.ts +153 -0
  176. package/src/services/system-metrics/process-collector-windows.ts +136 -0
  177. package/src/services/system-metrics/process-cpu-delta.ts +61 -0
  178. package/src/services/system-metrics/process-grouping.ts +142 -0
  179. package/src/services/system-metrics/process-io-delta.ts +84 -0
  180. package/src/services/system-metrics/process-io-linux.ts +46 -0
  181. package/src/services/system-metrics/process-net-collector-darwin.ts +103 -0
  182. package/src/services/system-metrics/process-rows-builder.ts +111 -0
  183. package/src/services/system-metrics/rate-delta.ts +47 -0
  184. package/src/services/system-metrics/system-metrics-platform.ts +51 -0
  185. package/src/services/system-metrics/system-metrics-tick.ts +178 -0
  186. package/src/services/system-metrics/system-metrics.service.ts +212 -0
  187. package/src/services/windows-process-tree.ts +351 -351
  188. package/src/types/system-metrics.ts +199 -0
  189. package/src/web/components/floating-window/window-content-registry.ts +2 -0
  190. package/src/web/components/floating-window/window-persistence.ts +1 -1
  191. package/src/web/components/floating-window/window-store-types.ts +1 -1
  192. package/src/web/components/system/build-kill-request.ts +9 -0
  193. package/src/web/components/system/chart-scale.ts +28 -0
  194. package/src/web/components/system/cpu-core-bars.tsx +33 -0
  195. package/src/web/components/system/kill-confirm-dialog.tsx +89 -0
  196. package/src/web/components/system/metric-chart-canvas.tsx +108 -0
  197. package/src/web/components/system/overview-cards/cpu-card.tsx +39 -0
  198. package/src/web/components/system/overview-cards/disk-card.tsx +41 -0
  199. package/src/web/components/system/overview-cards/gpu-card.tsx +33 -0
  200. package/src/web/components/system/overview-cards/mem-card.tsx +32 -0
  201. package/src/web/components/system/overview-cards/net-card.tsx +41 -0
  202. package/src/web/components/system/overview-panel.tsx +97 -0
  203. package/src/web/components/system/process-columns-grid.ts +93 -0
  204. package/src/web/components/system/process-group-row.tsx +71 -0
  205. package/src/web/components/system/process-row-format.ts +56 -0
  206. package/src/web/components/system/process-row.tsx +82 -0
  207. package/src/web/components/system/process-table-model.ts +127 -0
  208. package/src/web/components/system/process-table-sort.ts +90 -0
  209. package/src/web/components/system/process-table-toolbar.tsx +190 -0
  210. package/src/web/components/system/process-table-totals.ts +49 -0
  211. package/src/web/components/system/process-table.tsx +187 -0
  212. package/src/web/components/system/resolve-open-system-monitor-action.ts +29 -0
  213. package/src/web/components/system/resource-status-bar.tsx +17 -16
  214. package/src/web/components/system/sortable-header.tsx +65 -0
  215. package/src/web/components/system/sparkline-canvas.tsx +8 -9
  216. package/src/web/components/system/system-monitor-body.tsx +146 -0
  217. package/src/web/components/system/system-monitor-tab.tsx +2 -185
  218. package/src/web/components/system/system-monitor-window-content.tsx +18 -0
  219. package/src/web/components/system/use-open-system-monitor.ts +34 -0
  220. package/src/web/hooks/resource-monitor-lease.ts +55 -0
  221. package/src/web/hooks/use-element-width.ts +27 -0
  222. package/src/web/hooks/use-resource-monitor.ts +113 -35
  223. package/src/web/lib/format-bytes.ts +16 -0
  224. package/dist/web/assets/architecture-PBZL5I3N-Bs7wzj-W.js +0 -1
  225. package/dist/web/assets/arrow-right-DubGFkN8.js +0 -1
  226. package/dist/web/assets/button-B4MWPjWj.js +0 -1
  227. package/dist/web/assets/chat-tab-pBGQ9SCY.js +0 -15
  228. package/dist/web/assets/circle-question-mark-CENpx4oA.js +0 -1
  229. package/dist/web/assets/code-editor-XviNXdzi.js +0 -10
  230. package/dist/web/assets/gitGraph-HDMCJU4V-D7i54kbM.js +0 -1
  231. package/dist/web/assets/group-chat-tab-CcG_NXIS.js +0 -1
  232. package/dist/web/assets/index-BAVBuKmT.js +0 -52
  233. package/dist/web/assets/index-oxsyfDa0.css +0 -2
  234. package/dist/web/assets/info-3K5VOQVL-BV41AzR9.js +0 -1
  235. package/dist/web/assets/markdown-renderer-Dg5HE9Zq.js +0 -1
  236. package/dist/web/assets/packet-RMMSAZCW-CaJoP44m.js +0 -1
  237. package/dist/web/assets/pie-UPGHQEXC-DSGZmNw2.js +0 -1
  238. package/dist/web/assets/radar-KQ55EAFF-Be4VUTs0.js +0 -1
  239. package/dist/web/assets/settings-tab-COSUzGl8.js +0 -1
  240. package/dist/web/assets/system-monitor-tab-DThAFSd_.js +0 -1
  241. package/dist/web/assets/team-member-sheet-M83B4znI.js +0 -2
  242. package/dist/web/assets/treemap-KZPCXAKY-Cu2zgbxU.js +0 -1
  243. package/src/services/resource-monitor-utils.ts +0 -141
  244. package/src/services/resource-monitor.service.ts +0 -147
  245. package/src/web/components/system/system-monitor-group-row.tsx +0 -153
  246. /package/dist/web/assets/{abap-C1K0-wzc.js → abap-MRbmsXOs.js} +0 -0
  247. /package/dist/web/assets/{actionscript-3-CJhQVjLA.js → actionscript-3-BDDHKqa4.js} +0 -0
  248. /package/dist/web/assets/{ada-Bt8r9fME.js → ada-DpuV9KwV.js} +0 -0
  249. /package/dist/web/assets/{andromeeda-DF1I8qi3.js → andromeeda-D6qUCKJo.js} +0 -0
  250. /package/dist/web/assets/{apache-CnlleE6P.js → apache-CX1NU_Tl.js} +0 -0
  251. /package/dist/web/assets/{apex-j0C6Xmk6.js → apex-B4-aoQ3K.js} +0 -0
  252. /package/dist/web/assets/{api-settings-DfNRPr1q.js → api-settings-kQHV6pYZ.js} +0 -0
  253. /package/dist/web/assets/{api-themes-8WTH6KpV.js → api-themes-CrK0tkW_.js} +0 -0
  254. /package/dist/web/assets/{applescript-DO7AnO8U.js → applescript-Dm9NI6KR.js} +0 -0
  255. /package/dist/web/assets/{apply-theme-CNj1iA-v.js → apply-theme-BH_d4amk.js} +0 -0
  256. /package/dist/web/assets/{ara-i83AydZj.js → ara-BGN8GAYn.js} +0 -0
  257. /package/dist/web/assets/{asciidoc-DbBA6-sF.js → asciidoc-s_yVuR3t.js} +0 -0
  258. /package/dist/web/assets/{asm-B5S47Rgr.js → asm-BzQdSvTe.js} +0 -0
  259. /package/dist/web/assets/{aurora-x-De_IaSKw.js → aurora-x-BJTLETG_.js} +0 -0
  260. /package/dist/web/assets/{awk-CfyLHXqS.js → awk-BQEGWxvX.js} +0 -0
  261. /package/dist/web/assets/{ayu-dark-DTLdZ1Si.js → ayu-dark-CpTORmLc.js} +0 -0
  262. /package/dist/web/assets/{ayu-light-DTOfkzhu.js → ayu-light-D8PVj-e6.js} +0 -0
  263. /package/dist/web/assets/{ayu-mirage-DsAECCMv.js → ayu-mirage-DyElQHtm.js} +0 -0
  264. /package/dist/web/assets/{ballerina-CumGp9A7.js → ballerina-C82NkRtj.js} +0 -0
  265. /package/dist/web/assets/{bat-Ca2SBbYN.js → bat-0X7DtGI-.js} +0 -0
  266. /package/dist/web/assets/{beancount-CqyXBwwF.js → beancount-Xgvy6YRl.js} +0 -0
  267. /package/dist/web/assets/{berry-yl-kJr_H.js → berry-CCT2pZcQ.js} +0 -0
  268. /package/dist/web/assets/{bibtex-DoFFszjV.js → bibtex-CpXgZ9M_.js} +0 -0
  269. /package/dist/web/assets/{bicep-CWPi4nfK.js → bicep-fkeSA62l.js} +0 -0
  270. /package/dist/web/assets/{bird2-DXew-ut0.js → bird2-Co7SeAI8.js} +0 -0
  271. /package/dist/web/assets/{c-clbySDvd.js → c-BpmrTvJh.js} +0 -0
  272. /package/dist/web/assets/{c3-B65jvSM1.js → c3-BZ_Z0RrR.js} +0 -0
  273. /package/dist/web/assets/{cadence-Cm8tQTHN.js → cadence-B0GBC8OF.js} +0 -0
  274. /package/dist/web/assets/{can-open-in-ppm-DXGOSUQc.js → can-open-in-ppm-omBzUBBq.js} +0 -0
  275. /package/dist/web/assets/{catppuccin-frappe-DLeGslh_.js → catppuccin-frappe-DIt_xR7m.js} +0 -0
  276. /package/dist/web/assets/{catppuccin-latte-CR5GeHws.js → catppuccin-latte-Dw40AcqA.js} +0 -0
  277. /package/dist/web/assets/{catppuccin-macchiato-p-XgjxhP.js → catppuccin-macchiato-BJ7DfVEF.js} +0 -0
  278. /package/dist/web/assets/{catppuccin-mocha-B8QOAZLl.js → catppuccin-mocha-NI2lfXzU.js} +0 -0
  279. /package/dist/web/assets/{clarity-DPulbvKH.js → clarity-F39L0xMJ.js} +0 -0
  280. /package/dist/web/assets/{clock-D493FU_D.js → clock-CvhF4DJP.js} +0 -0
  281. /package/dist/web/assets/{clojure-DFuWS20u.js → clojure-DloMkd8K.js} +0 -0
  282. /package/dist/web/assets/{cmake-DejCqcu4.js → cmake-CwerJun_.js} +0 -0
  283. /package/dist/web/assets/{code-CLF5x7KK.js → code-DDPoqVri.js} +0 -0
  284. /package/dist/web/assets/{codeowners-BwAyqWIH.js → codeowners-CQyVz4Qf.js} +0 -0
  285. /package/dist/web/assets/{codeql-DgSwFjqI.js → codeql-Bb229zuY.js} +0 -0
  286. /package/dist/web/assets/{common-lisp-CxIVJCtf.js → common-lisp-KMlIwq5I.js} +0 -0
  287. /package/dist/web/assets/{copy-BApI9v7Z.js → copy-DKn11Pye.js} +0 -0
  288. /package/dist/web/assets/{coq-DLSjSnmf.js → coq-DHX_3IIo.js} +0 -0
  289. /package/dist/web/assets/{csharp-C1HHzXBp.js → csharp-CEmCZv9Q.js} +0 -0
  290. /package/dist/web/assets/{css-VXsMY--y.js → css-CqZqBD05.js} +0 -0
  291. /package/dist/web/assets/{csv-BEbcJdHz.js → csv-l1g_V5MV.js} +0 -0
  292. /package/dist/web/assets/{csv-parser-BRtnJCfv.js → csv-parser-CnS0wqr6.js} +0 -0
  293. /package/dist/web/assets/{cue-BkDnFqUD.js → cue-BrxRmilg.js} +0 -0
  294. /package/dist/web/assets/{cypher-1cMqojSQ.js → cypher-rZkKwqZc.js} +0 -0
  295. /package/dist/web/assets/{d-BnYjRXtH.js → d-BALR-QuP.js} +0 -0
  296. /package/dist/web/assets/{dark-plus-XfbaH7kZ.js → dark-plus-Cj7rVwh-.js} +0 -0
  297. /package/dist/web/assets/{dart-Ca7s-8hK.js → dart-CWQcdkXk.js} +0 -0
  298. /package/dist/web/assets/{data-grid-types-BXwlFMzs.js → data-grid-types-CYvF-xK5.js} +0 -0
  299. /package/dist/web/assets/{database-B9okYLx6.js → database-BH0urvbs.js} +0 -0
  300. /package/dist/web/assets/{dax-CmuOw-mY.js → dax-BNHD-QBA.js} +0 -0
  301. /package/dist/web/assets/{desktop-C2gJ6Ovb.js → desktop-CN0IXPrP.js} +0 -0
  302. /package/dist/web/assets/{diff-BCEo1Ej7.js → diff-BtOXapES.js} +0 -0
  303. /package/dist/web/assets/{dist-CUPbqNnL.js → dist-DB1Oaqcc.js} +0 -0
  304. /package/dist/web/assets/{dist-DOlBnxFX.js → dist-Di6G_5jU.js} +0 -0
  305. /package/dist/web/assets/{docker-DN2jlyAh.js → docker-DNsAo_qO.js} +0 -0
  306. /package/dist/web/assets/{dotenv-NExMY2kS.js → dotenv-D6Pl6aOU.js} +0 -0
  307. /package/dist/web/assets/{download-D9UYwY0-.js → download-zCATy4x4.js} +0 -0
  308. /package/dist/web/assets/{dracula-B9lbE01y.js → dracula-C3m-w12D.js} +0 -0
  309. /package/dist/web/assets/{dracula-soft-CMBBfKF_.js → dracula-soft-BYqvXm6Z.js} +0 -0
  310. /package/dist/web/assets/{dream-maker-DEyDwFsd.js → dream-maker-DZAPbPTi.js} +0 -0
  311. /package/dist/web/assets/{emacs-lisp-D_qP2zS6.js → emacs-lisp-Ao5SW8ay.js} +0 -0
  312. /package/dist/web/assets/{everforest-dark-DbHa2U-p.js → everforest-dark-uC8QYotQ.js} +0 -0
  313. /package/dist/web/assets/{everforest-light-BISkJchP.js → everforest-light-CTgsVNMr.js} +0 -0
  314. /package/dist/web/assets/{fennel-6B22SfJR.js → fennel-WuBw6IR1.js} +0 -0
  315. /package/dist/web/assets/{file-exclamation-point-a8f3_w7a.js → file-exclamation-point-COAwgNGw.js} +0 -0
  316. /package/dist/web/assets/{fish-CubIIvJD.js → fish-Byy9dusu.js} +0 -0
  317. /package/dist/web/assets/{fluent-DF55zQ09.js → fluent-CDxb_sgw.js} +0 -0
  318. /package/dist/web/assets/{fortran-free-form-DvOu8jAt.js → fortran-free-form-DKWSTamT.js} +0 -0
  319. /package/dist/web/assets/{gdscript-DCPxdLpq.js → gdscript-prYHMgtD.js} +0 -0
  320. /package/dist/web/assets/{gdshader-CTZ381FO.js → gdshader-D-RM-SQk.js} +0 -0
  321. /package/dist/web/assets/{genie-C_QDtvgU.js → genie-CowkJhej.js} +0 -0
  322. /package/dist/web/assets/{gherkin-BcvK42tF.js → gherkin-CLFpoVYJ.js} +0 -0
  323. /package/dist/web/assets/{github-dark-default-CKGVrl3Z.js → github-dark-default-BK_1Qgb8.js} +0 -0
  324. /package/dist/web/assets/{github-dark-dimmed-C3dQZ_LC.js → github-dark-dimmed-Cv9lj6f-.js} +0 -0
  325. /package/dist/web/assets/{github-dark-high-contrast-DW78QukY.js → github-dark-high-contrast-CW5ZgIDh.js} +0 -0
  326. /package/dist/web/assets/{github-dark-C9afs_4w.js → github-dark-nW2F-RLd.js} +0 -0
  327. /package/dist/web/assets/{github-light-BnP2dznS.js → github-light-D4PqBHGZ.js} +0 -0
  328. /package/dist/web/assets/{github-light-default-C2fPZzPG.js → github-light-default-B-cHtJJV.js} +0 -0
  329. /package/dist/web/assets/{github-light-high-contrast-BzIuUFR2.js → github-light-high-contrast-Dt0HJq50.js} +0 -0
  330. /package/dist/web/assets/{gleam-BpeKwEIO.js → gleam-DwSyXJWP.js} +0 -0
  331. /package/dist/web/assets/{gn-nUb_Mit0.js → gn-Cv5WEzHc.js} +0 -0
  332. /package/dist/web/assets/{gnuplot-D7I0v20p.js → gnuplot-D7bRdY_M.js} +0 -0
  333. /package/dist/web/assets/{go-D7Qqska7.js → go-DiRVJ22U.js} +0 -0
  334. /package/dist/web/assets/{groovy-DS-pne5-.js → groovy-BHAgLTeO.js} +0 -0
  335. /package/dist/web/assets/{gruvbox-dark-hard-C0W01fsq.js → gruvbox-dark-hard-C8QZ3gzY.js} +0 -0
  336. /package/dist/web/assets/{gruvbox-dark-medium-Bqo6fQbg.js → gruvbox-dark-medium-Dp1eeid2.js} +0 -0
  337. /package/dist/web/assets/{gruvbox-dark-soft-D-XSM_fu.js → gruvbox-dark-soft-Cwq0dWVj.js} +0 -0
  338. /package/dist/web/assets/{gruvbox-light-hard-IVAwMJRl.js → gruvbox-light-hard-CLQCq2-w.js} +0 -0
  339. /package/dist/web/assets/{gruvbox-light-medium-38ATiG7i.js → gruvbox-light-medium-APHsh6Mo.js} +0 -0
  340. /package/dist/web/assets/{gruvbox-light-soft-DnZr3c_0.js → gruvbox-light-soft-CX-fYc64.js} +0 -0
  341. /package/dist/web/assets/{haskell-uQcywkDH.js → haskell-C4Tw-TDa.js} +0 -0
  342. /package/dist/web/assets/{haxe-c6bI4_GT.js → haxe-B7fSduTQ.js} +0 -0
  343. /package/dist/web/assets/{hcl-CQXTiEXq.js → hcl-Bi3ho6yC.js} +0 -0
  344. /package/dist/web/assets/{hjson-ChETf2bz.js → hjson-BXwae2M1.js} +0 -0
  345. /package/dist/web/assets/{hlsl-BMC4JGoE.js → hlsl-CRuQLBSa.js} +0 -0
  346. /package/dist/web/assets/{horizon-BusFlhLW.js → horizon-DtdQ6qjv.js} +0 -0
  347. /package/dist/web/assets/{horizon-bright-2oD0Mz7W.js → horizon-bright-BXSF_uKq.js} +0 -0
  348. /package/dist/web/assets/{houston-DdbbjqFg.js → houston-C6ASpUjT.js} +0 -0
  349. /package/dist/web/assets/{hy-D_SOuqw9.js → hy-BrWBHtHY.js} +0 -0
  350. /package/dist/web/assets/{image-gallery-CrM5fHKy.js → image-gallery-CGvlv8zR.js} +0 -0
  351. /package/dist/web/assets/{imba-BxLOHO5I.js → imba-C_JJXckG.js} +0 -0
  352. /package/dist/web/assets/{ini-ox-CFcg0.js → ini-DEE_vSHQ.js} +0 -0
  353. /package/dist/web/assets/{java-Bzo8yIal.js → java-CnmpcjcT.js} +0 -0
  354. /package/dist/web/assets/{javascript-DHuz9VXn.js → javascript-C-M7sa2e.js} +0 -0
  355. /package/dist/web/assets/{json-0_y80FD5.js → json-BjZ3dAk6.js} +0 -0
  356. /package/dist/web/assets/{json5-CEQ50pGM.js → json5-BQ2vpqjp.js} +0 -0
  357. /package/dist/web/assets/{jsonc-CfrLEAKA.js → jsonc-C5MjoWGx.js} +0 -0
  358. /package/dist/web/assets/{jsonl-fKbrANC2.js → jsonl-JvhrmQJI.js} +0 -0
  359. /package/dist/web/assets/{jsonnet-DKbkPaQ2.js → jsonnet-C5pdZVuo.js} +0 -0
  360. /package/dist/web/assets/{jssm-Dxxx1Hqu.js → jssm-Db17uybX.js} +0 -0
  361. /package/dist/web/assets/{jsx-DlJL-Oj3.js → jsx-tJp2Cyqu.js} +0 -0
  362. /package/dist/web/assets/{kanagawa-dragon-CwN4SV1c.js → kanagawa-dragon-BculT_Y1.js} +0 -0
  363. /package/dist/web/assets/{kanagawa-lotus-BHltayiE.js → kanagawa-lotus-yQgHUGwU.js} +0 -0
  364. /package/dist/web/assets/{kanagawa-wave-D-KXPjw6.js → kanagawa-wave-CyGoWN4d.js} +0 -0
  365. /package/dist/web/assets/{kdl-DvtoJdFo.js → kdl-Bn8R1REF.js} +0 -0
  366. /package/dist/web/assets/{kotlin-CTS4MLcx.js → kotlin-DWughK73.js} +0 -0
  367. /package/dist/web/assets/{kusto-HtSE_sKm.js → kusto--serPb0x.js} +0 -0
  368. /package/dist/web/assets/{laserwave-DaXZG9ge.js → laserwave-DfAPJ1tt.js} +0 -0
  369. /package/dist/web/assets/{lean-BYtGUfWx.js → lean-UAm1HOKl.js} +0 -0
  370. /package/dist/web/assets/{less-BoxmU_Mk.js → less-Xj6Ka0fF.js} +0 -0
  371. /package/dist/web/assets/{lib-B1clP4ai.js → lib-DgNcCtj3.js} +0 -0
  372. /package/dist/web/assets/{libesm-ah-mr-sh.js → libesm-CPh1Av0r.js} +0 -0
  373. /package/dist/web/assets/{light-plus-Bt5CyUuo.js → light-plus-BfS7gPcj.js} +0 -0
  374. /package/dist/web/assets/{llvm-CSdk9q9V.js → llvm-DvWiVwvU.js} +0 -0
  375. /package/dist/web/assets/{log-B-kp_3CL.js → log-Bo5z9bNz.js} +0 -0
  376. /package/dist/web/assets/{logo-DdIsXFDO.js → logo-CrIjcMZT.js} +0 -0
  377. /package/dist/web/assets/{luau-DUBpLlzQ.js → luau-C9TsYwNt.js} +0 -0
  378. /package/dist/web/assets/{make-B3JVjoW_.js → make-GYq4qVbx.js} +0 -0
  379. /package/dist/web/assets/{markdown-Seon0vHs.js → markdown-p5mNledS.js} +0 -0
  380. /package/dist/web/assets/{material-theme-Nq-ChX1P.js → material-theme-CWYOVxsP.js} +0 -0
  381. /package/dist/web/assets/{material-theme-darker-CPV4ayXJ.js → material-theme-darker-BDGty7YH.js} +0 -0
  382. /package/dist/web/assets/{material-theme-lighter-0kyjYqEd.js → material-theme-lighter-JbgOgV3n.js} +0 -0
  383. /package/dist/web/assets/{material-theme-ocean-DGpAp5co.js → material-theme-ocean-EMOpLpa2.js} +0 -0
  384. /package/dist/web/assets/{material-theme-palenight-B0AUn0NG.js → material-theme-palenight-CY5hgm7h.js} +0 -0
  385. /package/dist/web/assets/{matlab-C2waytxs.js → matlab-C-He_NTH.js} +0 -0
  386. /package/dist/web/assets/{mdx-DAis6R6I.js → mdx-Cr2TR5fj.js} +0 -0
  387. /package/dist/web/assets/{media-url-DlYsHq0S.js → media-url-CylYQld1.js} +0 -0
  388. /package/dist/web/assets/{mermaid-_rnT2YGD.js → mermaid-BYc0-B0U.js} +0 -0
  389. /package/dist/web/assets/{min-dark-BSSjchUB.js → min-dark-CMJwqJqB.js} +0 -0
  390. /package/dist/web/assets/{min-light-DomAFQsa.js → min-light-Cx6vFiEX.js} +0 -0
  391. /package/dist/web/assets/{mipsasm-bBgtvPyG.js → mipsasm-Bjer5HwK.js} +0 -0
  392. /package/dist/web/assets/{mobile-bottom-sheet-CS3XMwFw.js → mobile-bottom-sheet-BUOJgiaZ.js} +0 -0
  393. /package/dist/web/assets/{mojo-Cp9BayW0.js → mojo-t90PR-Y2.js} +0 -0
  394. /package/dist/web/assets/{monokai-CL_9gbmn.js → monokai-dci_PdCm.js} +0 -0
  395. /package/dist/web/assets/{moonbit-BS_fcr-P.js → moonbit-AAzI-Hd-.js} +0 -0
  396. /package/dist/web/assets/{move-C79AH45U.js → move-kwBhnhrG.js} +0 -0
  397. /package/dist/web/assets/{narrat-CJ5s3BDf.js → narrat-CXww2YQL.js} +0 -0
  398. /package/dist/web/assets/{nextflow-groovy-ZHa4JrPJ.js → nextflow-groovy-CJXsuXGB.js} +0 -0
  399. /package/dist/web/assets/{night-owl-Jkf9zFQK.js → night-owl-_GD204Wr.js} +0 -0
  400. /package/dist/web/assets/{night-owl-light-DRPeaG5J.js → night-owl-light-DNgkw3kl.js} +0 -0
  401. /package/dist/web/assets/{nix-D2Jet9DN.js → nix-BgiorKFd.js} +0 -0
  402. /package/dist/web/assets/{nord-CREVs22j.js → nord-CaBmcxFC.js} +0 -0
  403. /package/dist/web/assets/{nushell-CAiDi_mR.js → nushell-DUh4UGx1.js} +0 -0
  404. /package/dist/web/assets/{objective-c-CVkmJkC1.js → objective-c-Cl9KU86S.js} +0 -0
  405. /package/dist/web/assets/{objective-cpp-DIKDO1Ly.js → objective-cpp-DVkIA8A0.js} +0 -0
  406. /package/dist/web/assets/{ocaml-R9qtGQhs.js → ocaml-vvoHTak0.js} +0 -0
  407. /package/dist/web/assets/{odin-DTYNQqVr.js → odin-Cyjw8woZ.js} +0 -0
  408. /package/dist/web/assets/{one-dark-pro-BSLWUJn5.js → one-dark-pro-B1cviILi.js} +0 -0
  409. /package/dist/web/assets/{one-light-DbkRXG3t.js → one-light-BPGUJeYI.js} +0 -0
  410. /package/dist/web/assets/{openscad-BlPcSnmT.js → openscad-BLMdTUU8.js} +0 -0
  411. /package/dist/web/assets/{pascal-B1Y46ZZB.js → pascal-i5niy3e7.js} +0 -0
  412. /package/dist/web/assets/{pkl-BhJSJbFv.js → pkl-CuOV7SsU.js} +0 -0
  413. /package/dist/web/assets/{plastic-BzxsCTpi.js → plastic-Bf_zE5KL.js} +0 -0
  414. /package/dist/web/assets/{plsql-DBba7dyP.js → plsql-cfqEtMD3.js} +0 -0
  415. /package/dist/web/assets/{plus-DmjC2iRB.js → plus-BM-Ty0fp.js} +0 -0
  416. /package/dist/web/assets/{po-BvgLlnNo.js → po-CFJcWgjr.js} +0 -0
  417. /package/dist/web/assets/{poimandres-DUaI_1JP.js → poimandres-G5YoaIFf.js} +0 -0
  418. /package/dist/web/assets/{polar-C7uILwJn.js → polar-rcjs3i9R.js} +0 -0
  419. /package/dist/web/assets/{postcss-BgJlpFdw.js → postcss-CBKY1FTZ.js} +0 -0
  420. /package/dist/web/assets/{powerquery-Dn1MIpZu.js → powerquery-Db7SXLbO.js} +0 -0
  421. /package/dist/web/assets/{powershell-Bo-DYzOS.js → powershell-LFy3MUTP.js} +0 -0
  422. /package/dist/web/assets/{prisma-CTLs5IdT.js → prisma-BE8GR1lH.js} +0 -0
  423. /package/dist/web/assets/{prolog-QRGun3eG.js → prolog-DOn5lR1e.js} +0 -0
  424. /package/dist/web/assets/{proto-B7PI7apn.js → proto-wr-TpAK_.js} +0 -0
  425. /package/dist/web/assets/{puppet-CBq0tLrP.js → puppet-D2Dkv62u.js} +0 -0
  426. /package/dist/web/assets/{purescript-DFewOQb2.js → purescript-DvgJgPdy.js} +0 -0
  427. /package/dist/web/assets/{python-iWuxKXvT.js → python-C7TlkHhK.js} +0 -0
  428. /package/dist/web/assets/{qmldir-cXiW3AsF.js → qmldir-CtZMwhcW.js} +0 -0
  429. /package/dist/web/assets/{qss-DASwAbBL.js → qss-dNZ2btnl.js} +0 -0
  430. /package/dist/web/assets/{r-TU2eaIPw.js → r-BlqnNkHS.js} +0 -0
  431. /package/dist/web/assets/{racket-SkRKqrLY.js → racket-CzRQrGc4.js} +0 -0
  432. /package/dist/web/assets/{raku-D31lthkZ.js → raku-BwutWhBF.js} +0 -0
  433. /package/dist/web/assets/{red-CTcQZevb.js → red-BMXMywmL.js} +0 -0
  434. /package/dist/web/assets/{reg-D8YAsTGf.js → reg-BqOKrIOw.js} +0 -0
  435. /package/dist/web/assets/{regexp-CD2uvAWx.js → regexp-Bero1BN2.js} +0 -0
  436. /package/dist/web/assets/{rel-CAaI-1fg.js → rel-BXKWIElA.js} +0 -0
  437. /package/dist/web/assets/{resolve-theme-CJvkL8hU.js → resolve-theme-IdhSR-gx.js} +0 -0
  438. /package/dist/web/assets/{riscv-DR-hJVIj.js → riscv-BbbBYJBo.js} +0 -0
  439. /package/dist/web/assets/{ron-CuUCJ0n4.js → ron-BtVTWW4b.js} +0 -0
  440. /package/dist/web/assets/{rose-pine-dawn-Bqz2sBRY.js → rose-pine-dawn-D7lwhUei.js} +0 -0
  441. /package/dist/web/assets/{rose-pine-aFHxW48i.js → rose-pine-hvkvQzvU.js} +0 -0
  442. /package/dist/web/assets/{rose-pine-moon-wqyh0an4.js → rose-pine-moon-CoHDmsIw.js} +0 -0
  443. /package/dist/web/assets/{rosmsg-CI1ywimO.js → rosmsg-CdaZFgI8.js} +0 -0
  444. /package/dist/web/assets/{run-in-terminal-CGW6o37_.js → run-in-terminal-CyS5Itj-.js} +0 -0
  445. /package/dist/web/assets/{rust-p7Imk4G_.js → rust-Dy2qsphD.js} +0 -0
  446. /package/dist/web/assets/{sass-C8JfaqCV.js → sass-Bz7NVxDb.js} +0 -0
  447. /package/dist/web/assets/{save-DRPrDfTt.js → save-C4z1p51e.js} +0 -0
  448. /package/dist/web/assets/{scala-DNxCW1By.js → scala-sXSwsNyq.js} +0 -0
  449. /package/dist/web/assets/{scheme-BYuUPJoL.js → scheme-DS7TUbN7.js} +0 -0
  450. /package/dist/web/assets/{sdbl-DbPeJPUr.js → sdbl-iISFvIep.js} +0 -0
  451. /package/dist/web/assets/{send-to-chat-YXHdAyLG.js → send-to-chat-BcO39BDR.js} +0 -0
  452. /package/dist/web/assets/{shellscript-DMiHlR3q.js → shellscript-BkIl4ApC.js} +0 -0
  453. /package/dist/web/assets/{shield-check-8GObuUAn.js → shield-check-C5laObJv.js} +0 -0
  454. /package/dist/web/assets/{shield-off-egKAZEwR.js → shield-off-DULFtyLS.js} +0 -0
  455. /package/dist/web/assets/{slack-dark-C4xGcQXI.js → slack-dark-B1eg0_m2.js} +0 -0
  456. /package/dist/web/assets/{slack-ochin-BzgRt_wm.js → slack-ochin-mdkc1ldu.js} +0 -0
  457. /package/dist/web/assets/{smalltalk-LDeL9PYH.js → smalltalk-CORtd03t.js} +0 -0
  458. /package/dist/web/assets/{snazzy-light-CXE7a5j_.js → snazzy-light-Bc6Q2G89.js} +0 -0
  459. /package/dist/web/assets/{solarized-dark-DgUhY74x.js → solarized-dark-CF83zRXM.js} +0 -0
  460. /package/dist/web/assets/{solarized-light-DD9C-H-9.js → solarized-light-BoKQZaYU.js} +0 -0
  461. /package/dist/web/assets/{solidity-CAbDB4D4.js → solidity-DOgi1N4w.js} +0 -0
  462. /package/dist/web/assets/{sparkles-n1hzh65o.js → sparkles-Dqsf3hq6.js} +0 -0
  463. /package/dist/web/assets/{splunk-kQREPfIc.js → splunk-BXfw5ZLy.js} +0 -0
  464. /package/dist/web/assets/{sql-CBzeNAD8.js → sql-BcVs-eX4.js} +0 -0
  465. /package/dist/web/assets/{ssh-config-L1euxrsM.js → ssh-config-CLCtNkkd.js} +0 -0
  466. /package/dist/web/assets/{stylus-DvBnYniP.js → stylus-DdP992aO.js} +0 -0
  467. /package/dist/web/assets/{swift-DF5NDQp6.js → swift-BnGb6Lgc.js} +0 -0
  468. /package/dist/web/assets/{synthwave-84-DbBhB_Hq.js → synthwave-84-cg9264l9.js} +0 -0
  469. /package/dist/web/assets/{system-verilog-D8s2ZW_k.js → system-verilog-GbHpszs3.js} +0 -0
  470. /package/dist/web/assets/{systemd-a5-XZJsG.js → systemd-Dz-bNsDQ.js} +0 -0
  471. /package/dist/web/assets/{table-BX2ZrJfM.js → table-CHmxuh6M.js} +0 -0
  472. /package/dist/web/assets/{talonscript-BLa0URTW.js → talonscript-CFIidoBA.js} +0 -0
  473. /package/dist/web/assets/{tasl-DIoV4XcC.js → tasl-Cu-TRTKx.js} +0 -0
  474. /package/dist/web/assets/{tcl-ztYAdXfQ.js → tcl-DwCHCB1K.js} +0 -0
  475. /package/dist/web/assets/{terraform-DvpCCiOZ.js → terraform-BzZw4T1z.js} +0 -0
  476. /package/dist/web/assets/{tokyo-night-BkHlYUv0.js → tokyo-night-RKsj2-tv.js} +0 -0
  477. /package/dist/web/assets/{toml-acIrxos6.js → toml-CirbOgDP.js} +0 -0
  478. /package/dist/web/assets/{tsv-BJB5EVCT.js → tsv-CraRcWdU.js} +0 -0
  479. /package/dist/web/assets/{tsx-B1MmXGT3.js → tsx-CjFg0lgw.js} +0 -0
  480. /package/dist/web/assets/{turtle-DFceTiqd.js → turtle-B-WBIOa6.js} +0 -0
  481. /package/dist/web/assets/{typescript-Dz9wU5Y1.js → typescript-MpLarYn1.js} +0 -0
  482. /package/dist/web/assets/{typespec-CPuYZijj.js → typespec-B7QlHMZ_.js} +0 -0
  483. /package/dist/web/assets/{typst-CfsCIYv8.js → typst-CcHSKFZj.js} +0 -0
  484. /package/dist/web/assets/{use-blob-url-BmlYYZ8L.js → use-blob-url-BKyVxOZw.js} +0 -0
  485. /package/dist/web/assets/{use-is-mobile-B8FA4kQf.js → use-is-mobile-BXGVvczu.js} +0 -0
  486. /package/dist/web/assets/{v-CGo0jcXA.js → v-xTGhWZuD.js} +0 -0
  487. /package/dist/web/assets/{vala-AsSR0hrb.js → vala-DwebjH3H.js} +0 -0
  488. /package/dist/web/assets/{vb-C7tvbXv1.js → vb-BxJT2RAy.js} +0 -0
  489. /package/dist/web/assets/{vendor-xterm-C1diXHJl.js → vendor-xterm-CU6zIYMB.js} +0 -0
  490. /package/dist/web/assets/{verilog--a33ND-p.js → verilog-CvV6RHPD.js} +0 -0
  491. /package/dist/web/assets/{vesper-B_Z0h4pn.js → vesper-CY3qd7E_.js} +0 -0
  492. /package/dist/web/assets/{vhdl-CWL5dZPN.js → vhdl-B9ZX-sUL.js} +0 -0
  493. /package/dist/web/assets/{viml-BglmT14Y.js → viml-Y42h_ExQ.js} +0 -0
  494. /package/dist/web/assets/{vitesse-black-RKFsSqQI.js → vitesse-black-DkXP6Sv-.js} +0 -0
  495. /package/dist/web/assets/{vitesse-dark-D7zDWNmc.js → vitesse-dark-B9CkIB6r.js} +0 -0
  496. /package/dist/web/assets/{vitesse-light-MAp87W5b.js → vitesse-light-C7DHrJCK.js} +0 -0
  497. /package/dist/web/assets/{vyper-CgCBYg1G.js → vyper-Cnd9s5j-.js} +0 -0
  498. /package/dist/web/assets/{wasm-Bwl4txwp.js → wasm-DQE71XTB.js} +0 -0
  499. /package/dist/web/assets/{wasm-BOG7ZeTT.js → wasm-iWe7Fzjc.js} +0 -0
  500. /package/dist/web/assets/{wenyan-DpShPKXZ.js → wenyan-Bc5Pnm9l.js} +0 -0
  501. /package/dist/web/assets/{wgsl-BakcCblK.js → wgsl-D-YUAWkP.js} +0 -0
  502. /package/dist/web/assets/{wikitext-NroRWVAO.js → wikitext-DYQDUYf2.js} +0 -0
  503. /package/dist/web/assets/{wit-B5CM2pg6.js → wit-P6u7mfwy.js} +0 -0
  504. /package/dist/web/assets/{wolfram-7MTFBJpR.js → wolfram-6SXLUqao.js} +0 -0
  505. /package/dist/web/assets/{yaml-Bwr01G2K.js → yaml-CQiMLVcZ.js} +0 -0
  506. /package/dist/web/assets/{zenscript-Dj8GATvi.js → zenscript-DFMywo_P.js} +0 -0
  507. /package/dist/web/assets/{zig-LAE-fbS-.js → zig-CtAjaIiF.js} +0 -0
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Live re-query for a kill request. A pid is not an identity: Windows recycles
3
+ * pids fast enough that the `node` the user clicked two seconds ago can be
4
+ * `lsass` by the time the POST lands. The route therefore never authorises
5
+ * against the snapshot — it re-collects the process table (one round trip, the
6
+ * same per-OS source the tick uses), compares the client's `startedAt` claim
7
+ * with the live one, and hands the guard the FRESH name plus fresh ppid maps.
8
+ */
9
+ import type { ProcessCollector, RawProcessRow } from "./process-collector-types.ts";
10
+
11
+ export interface LiveProcessIdentity {
12
+ pid: number;
13
+ name: string;
14
+ startedAt: number;
15
+ }
16
+
17
+ /** macOS `ps` start times are 1 s resolution and other sources may be coarser. */
18
+ export const IDENTITY_TOLERANCE_MS = 2000;
19
+
20
+ /** An unknown start time (0) on either side cannot prove a mismatch. */
21
+ export function identityMatches(claimedStartedAt: number, liveStartedAt: number): boolean {
22
+ if (!claimedStartedAt || !liveStartedAt) return true;
23
+ return Math.abs(claimedStartedAt - liveStartedAt) <= IDENTITY_TOLERANCE_MS;
24
+ }
25
+
26
+ export interface GuardMaps {
27
+ ppidOf: Map<number, number>;
28
+ startedAtOf: Map<number, number>;
29
+ byPid: Map<number, RawProcessRow>;
30
+ /** Rows that were refused because their pid was already present. */
31
+ warnings: string[];
32
+ }
33
+
34
+ /**
35
+ * A pid appears once in any real process table. A second row for the same pid
36
+ * can only be a forged line that slipped through the transport, so the FIRST
37
+ * row wins and the duplicate is refused — a forgery must never be able to
38
+ * overwrite the name the kill guard is about to trust.
39
+ */
40
+ export function buildGuardMaps(rows: readonly RawProcessRow[]): GuardMaps {
41
+ const ppidOf = new Map<number, number>();
42
+ const startedAtOf = new Map<number, number>();
43
+ const byPid = new Map<number, RawProcessRow>();
44
+ const warnings: string[] = [];
45
+ for (const r of rows) {
46
+ if (byPid.has(r.pid)) {
47
+ warnings.push(`Duplicate row for PID ${r.pid} ignored (name "${r.name}")`);
48
+ continue;
49
+ }
50
+ byPid.set(r.pid, r);
51
+ ppidOf.set(r.pid, r.ppid);
52
+ startedAtOf.set(r.pid, r.startedAt);
53
+ }
54
+ return { ppidOf, startedAtOf, byPid, warnings };
55
+ }
56
+
57
+ export interface LiveResolution {
58
+ live: LiveProcessIdentity | null;
59
+ maps: GuardMaps;
60
+ warnings: string[];
61
+ }
62
+
63
+ export async function resolveLiveProcess(pid: number, collector: ProcessCollector): Promise<LiveResolution> {
64
+ const collection = await collector.collect();
65
+ const maps = buildGuardMaps(collection.rows);
66
+ const row = maps.byPid.get(pid);
67
+ return {
68
+ live: row ? { pid: row.pid, name: row.name, startedAt: row.startedAt } : null,
69
+ maps,
70
+ warnings: [...collection.warnings, ...maps.warnings],
71
+ };
72
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The kill decision chain, transport-free so it is testable without Hono:
3
+ * parse → live re-query → identity check → guard on the FRESH name → execute.
4
+ * Authorising against the snapshot would authorise against data up to one tick
5
+ * old, and Windows recycles pids fast enough for that to matter.
6
+ */
7
+ import type { KillProcessRequest, KillProcessResult, MetricsPlatform } from "../../types/system-metrics.ts";
8
+ import { ok, err, type ApiResponse } from "../../types/api.ts";
9
+ import type { ProcessCollector } from "./process-collector-types.ts";
10
+ import { identityMatches, resolveLiveProcess } from "./kill-identity-resolver.ts";
11
+ import { checkKillAllowed } from "./kill-guard.ts";
12
+ import type { ProtectedPids } from "./ppm-protected-pids.ts";
13
+
14
+ export interface KillHandlerDeps {
15
+ platform: MetricsPlatform;
16
+ collector: ProcessCollector;
17
+ resolveProtected: (isAlive: (pid: number) => boolean, nameOf: (pid: number) => string | undefined) => ProtectedPids;
18
+ execute: (pid: number, tree: boolean) => Promise<KillProcessResult>;
19
+ /** Audit line: pid + name + result ONLY. `~/.ppm/ppm.log`'s tail is served
20
+ * unauthenticated by `/api/logs/recent`, so a command line must never land here. */
21
+ log: (line: string) => void;
22
+ }
23
+
24
+ export type KillStatus = 200 | 400 | 403 | 404 | 409 | 500;
25
+
26
+ export interface KillOutcome {
27
+ status: KillStatus;
28
+ body: ApiResponse<KillProcessResult>;
29
+ }
30
+
31
+ export function parseKillRequest(body: unknown): KillProcessRequest | null {
32
+ if (!body || typeof body !== "object") return null;
33
+ const b = body as Record<string, unknown>;
34
+ const pid = b.pid;
35
+ const startedAt = b.startedAt;
36
+ if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0) return null;
37
+ if (typeof startedAt !== "number" || !Number.isFinite(startedAt) || startedAt < 0) return null;
38
+ if (b.tree !== undefined && typeof b.tree !== "boolean") return null;
39
+ return { pid, startedAt, tree: b.tree === true };
40
+ }
41
+
42
+ export async function handleKillRequest(body: unknown, deps: KillHandlerDeps): Promise<KillOutcome> {
43
+ const req = parseKillRequest(body);
44
+ if (!req) return { status: 400, body: err("Body must be {pid: positive integer, startedAt: epoch ms, tree?: boolean}") };
45
+ const tree = req.tree === true;
46
+
47
+ const { live, maps } = await resolveLiveProcess(req.pid, deps.collector);
48
+ if (!live) return { status: 404, body: err(`PID ${req.pid} is no longer running`) };
49
+ if (!identityMatches(req.startedAt, live.startedAt)) {
50
+ return { status: 409, body: err(`PID ${req.pid} was recycled — refresh and try again`) };
51
+ }
52
+
53
+ const protectedPids = deps.resolveProtected(
54
+ (pid) => maps.byPid.has(pid),
55
+ (pid) => maps.byPid.get(pid)?.name.toLowerCase(),
56
+ );
57
+ const verdict = checkKillAllowed({ pid: live.pid, name: live.name }, tree, {
58
+ platform: deps.platform,
59
+ protectedPids: protectedPids.pids,
60
+ ppidOf: maps.ppidOf,
61
+ startedAtOf: maps.startedAtOf,
62
+ });
63
+ const prefix = `[SystemMetrics] kill pid=${live.pid} name=${live.name} tree=${tree}`;
64
+ if (!verdict.allowed) {
65
+ deps.log(`${prefix} → refused: ${verdict.reason}`);
66
+ return { status: 403, body: err(verdict.reason ?? "Refused") };
67
+ }
68
+
69
+ deps.log(`${prefix} → allowed`);
70
+ try {
71
+ const result = await deps.execute(live.pid, tree);
72
+ deps.log(`${prefix} → done (${result.method}, ${result.killed.length} signalled)`);
73
+ return { status: 200, body: ok(result) };
74
+ } catch (e) {
75
+ const message = (e as Error)?.message ?? String(e);
76
+ deps.log(`${prefix} → failed: ${message}`);
77
+ return { status: 500, body: err(`Failed to end PID ${live.pid}: ${message}`) };
78
+ }
79
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * One holder at a time for the process collector. The PowerShell session takes
3
+ * a single request at a time, and a kill re-collects through the same collector
4
+ * the poll tick uses — so a kill waits for an in-flight tick, while a tick that
5
+ * arrives during a kill (or another tick) is simply skipped: metrics are lossy,
6
+ * a dropped poll is harmless, but two overlapping collections would either fail
7
+ * with "request already in flight" or double-consume the CPU delta baseline.
8
+ */
9
+ export class CollectorLock {
10
+ private inflight: Promise<unknown> | null = null;
11
+
12
+ isHeld(): boolean {
13
+ return this.inflight !== null;
14
+ }
15
+
16
+ /** Run now if free, otherwise skip and resolve to `null`. */
17
+ async tryRun<T>(work: () => Promise<T>): Promise<T | null> {
18
+ if (this.inflight) return null;
19
+ return this.hold(work());
20
+ }
21
+
22
+ /** Wait for the current holder (however it ends), then run. */
23
+ async runExclusive<T>(work: () => Promise<T>): Promise<T> {
24
+ while (this.inflight) await this.inflight.catch(() => {});
25
+ return this.hold(work());
26
+ }
27
+
28
+ private async hold<T>(p: Promise<T>): Promise<T> {
29
+ this.inflight = p;
30
+ try {
31
+ return await p;
32
+ } finally {
33
+ this.inflight = null;
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Turns live subscriber demand into exactly one poll timer, plus the delayed
3
+ * child teardown when full-tier demand disappears. Timers follow demand:
4
+ * ≥1 full subscriber → full cadence; else ≥1 light → light cadence; else none.
5
+ */
6
+ import type { MetricsTier } from "../../types/system-metrics.ts";
7
+
8
+ export interface PollSchedulerOptions {
9
+ intervals: { full: number; light: number };
10
+ /** Grace before `onIdle` fires after the last full subscriber leaves, so a
11
+ * window reopen does not pay the PowerShell bootstrap again. */
12
+ idleTeardownMs: number;
13
+ onTick: () => void;
14
+ /** Full-tier demand has been absent for the whole grace period. */
15
+ onIdle: () => void;
16
+ /** Full-tier collection is about to start for the first time. */
17
+ onFullStart: () => void;
18
+ }
19
+
20
+ export class PollScheduler {
21
+ private timer: ReturnType<typeof setInterval> | null = null;
22
+ private idleTimer: ReturnType<typeof setTimeout> | null = null;
23
+ private tier: MetricsTier | null = null;
24
+
25
+ constructor(private readonly opts: PollSchedulerOptions) {}
26
+
27
+ activeTier(): MetricsTier | null {
28
+ return this.tier;
29
+ }
30
+
31
+ /** Returns true when the active tier changed (so delta baselines may need a reset). */
32
+ reconcile(fullCount: number, lightCount: number): boolean {
33
+ const desired: MetricsTier | null = fullCount > 0 ? "full" : lightCount > 0 ? "light" : null;
34
+ if (desired === "full") this.clearIdle();
35
+ else if (this.tier === "full") this.armIdle();
36
+ if (desired === this.tier) return false;
37
+
38
+ if (this.timer) clearInterval(this.timer);
39
+ this.timer = null;
40
+ this.tier = desired;
41
+ if (desired === "full") this.opts.onFullStart();
42
+ if (desired) {
43
+ this.timer = setInterval(this.opts.onTick, this.opts.intervals[desired]);
44
+ this.opts.onTick();
45
+ }
46
+ return true;
47
+ }
48
+
49
+ /** Re-arm the idle teardown after an out-of-band full collection (a kill). */
50
+ armIdle(): void {
51
+ this.clearIdle();
52
+ this.idleTimer = setTimeout(() => {
53
+ this.idleTimer = null;
54
+ if (this.tier !== "full") this.opts.onIdle();
55
+ }, this.opts.idleTeardownMs);
56
+ }
57
+
58
+ stop(): void {
59
+ if (this.timer) clearInterval(this.timer);
60
+ this.timer = null;
61
+ this.tier = null;
62
+ this.clearIdle();
63
+ }
64
+
65
+ private clearIdle(): void {
66
+ if (this.idleTimer) clearTimeout(this.idleTimer);
67
+ this.idleTimer = null;
68
+ }
69
+ }
70
+
71
+ const installedTeardowns = new WeakSet<() => void>();
72
+
73
+ /** A hard exit must not leave a PowerShell child holding the server's
74
+ * inheritable listening socket (the zombie-port state). The server's own
75
+ * SIGTERM/SIGINT handler calls `process.exit`, which fires `exit` — so this
76
+ * hook only tears down and never exits itself. Installed once per teardown fn. */
77
+ export function installProcessExitHooks(teardown: () => void): void {
78
+ if (installedTeardowns.has(teardown)) return;
79
+ installedTeardowns.add(teardown);
80
+ process.on("exit", teardown);
81
+ process.on("SIGTERM", teardown);
82
+ process.on("SIGINT", teardown);
83
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * SSE subscriber leases. A proxy in front of PPM (Cloudflare Tunnel) may keep
3
+ * the origin request alive after the browser left, so `cancel()` cannot be
4
+ * trusted: each subscriber holds a lease the client renews by pinging, and the
5
+ * server reaps silent ones. Without this, a phone that closed its tab would keep
6
+ * the PowerShell child running forever and burn one of the five stream slots.
7
+ */
8
+ import type { MetricsSnapshot, MetricsTier } from "../../types/system-metrics.ts";
9
+
10
+ export interface MetricsSubscriber {
11
+ sid: string;
12
+ tier: MetricsTier;
13
+ lastPingAt: number;
14
+ deliver: (snapshot: MetricsSnapshot) => void;
15
+ /** Called once when the server drops the subscriber (reap or explicit stop). */
16
+ close: () => void;
17
+ }
18
+
19
+ export const SID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
20
+
21
+ /** Accept only a short opaque id so a hostile query cannot bloat the map. */
22
+ export function isValidSid(raw: string | undefined): raw is string {
23
+ return typeof raw === "string" && SID_PATTERN.test(raw);
24
+ }
25
+
26
+ export class SubscriberRegistry {
27
+ private readonly subs = new Map<string, MetricsSubscriber>();
28
+
29
+ add(sub: MetricsSubscriber): void {
30
+ this.subs.set(sub.sid, sub);
31
+ }
32
+
33
+ has(sid: string): boolean {
34
+ return this.subs.has(sid);
35
+ }
36
+
37
+ /** Remove and end the stream, so an explicit DELETE also closes the HTTP
38
+ * response a proxy might otherwise hold open. `close` must be idempotent. */
39
+ remove(sid: string): boolean {
40
+ const s = this.subs.get(sid);
41
+ if (!s) return false;
42
+ this.subs.delete(sid);
43
+ try { s.close(); } catch { /* stream already gone */ }
44
+ return true;
45
+ }
46
+
47
+ ping(sid: string, now: number): boolean {
48
+ const s = this.subs.get(sid);
49
+ if (!s) return false;
50
+ s.lastPingAt = now;
51
+ return true;
52
+ }
53
+
54
+ /** Drop and close every lease silent for longer than `timeoutMs`. */
55
+ reap(now: number, timeoutMs: number): MetricsSubscriber[] {
56
+ const expired: MetricsSubscriber[] = [];
57
+ for (const s of this.subs.values()) {
58
+ if (now - s.lastPingAt > timeoutMs) expired.push(s);
59
+ }
60
+ for (const s of expired) {
61
+ this.subs.delete(s.sid);
62
+ try { s.close(); } catch { /* stream already gone */ }
63
+ }
64
+ return expired;
65
+ }
66
+
67
+ count(tier?: MetricsTier): number {
68
+ if (!tier) return this.subs.size;
69
+ let n = 0;
70
+ for (const s of this.subs.values()) if (s.tier === tier) n++;
71
+ return n;
72
+ }
73
+
74
+ list(tier: MetricsTier): MetricsSubscriber[] {
75
+ return [...this.subs.values()].filter((s) => s.tier === tier);
76
+ }
77
+
78
+ /** Close everything — server shutdown. */
79
+ clear(): void {
80
+ for (const s of this.subs.values()) {
81
+ try { s.close(); } catch { /* stream already gone */ }
82
+ }
83
+ this.subs.clear();
84
+ }
85
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The PowerShell REPL bootstrap and the real spawner for the long-lived session.
3
+ *
4
+ * Why not `-Command -` with stdin scripts: PS 5.1 executes stdin line by line,
5
+ * so a multi-line construct makes the child exit 0 silently with no stderr.
6
+ * Instead this bootstrap IS the loop: one request = one line
7
+ * `<id> <base64(UTF-16LE script)>`, one reply = everything up to a literal
8
+ * `__END_<id>__` line. Per-request ids mean a hostile command line containing a
9
+ * sentinel can desync at most the one in-flight reply.
10
+ */
11
+
12
+ /** One `-Command` string. `try{} catch{}` must stay one logical statement — a
13
+ * semicolon before `catch` is a parse error that kills the child at startup
14
+ * with `MissingCatchOrFinally`. */
15
+ export const POWERSHELL_BOOTSTRAP = [
16
+ "[Console]::OutputEncoding=[Text.Encoding]::UTF8",
17
+ "$ErrorActionPreference='Continue'",
18
+ "$in=[Console]::In",
19
+ "while($true){ $line=$in.ReadLine(); if($null -eq $line){break}; if($line -eq ''){continue}; " +
20
+ "$sp=$line.IndexOf(' '); $id=$line.Substring(0,$sp); " +
21
+ "$code=[Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($line.Substring($sp+1))); " +
22
+ "try { Invoke-Expression $code | Out-String -Width 1000000 -Stream | ForEach-Object { $_ } } catch { Write-Output ('__ERR__ ' + $_.Exception.Message) }; " +
23
+ "Write-Output ('__END_' + $id + '__') }",
24
+ ].join("; ");
25
+
26
+ /** The minimal duplex surface the session needs, so tests can inject a fake. */
27
+ export interface PsChild {
28
+ pid: number;
29
+ stdin: { write(data: string): unknown; flush?(): unknown };
30
+ stdout: ReadableStream<Uint8Array>;
31
+ stderr?: ReadableStream<Uint8Array> | null;
32
+ exited: Promise<number>;
33
+ kill(): void;
34
+ }
35
+
36
+ export type PsSpawner = () => PsChild;
37
+
38
+ /** `-NoProfile`: a user profile can redefine cmdlets and poison the parse.
39
+ * `-NonInteractive`: a prompt would wedge the pipe forever. */
40
+ export const defaultPsSpawner: PsSpawner = () =>
41
+ Bun.spawn(["powershell.exe", "-NoProfile", "-NonInteractive", "-Command", POWERSHELL_BOOTSTRAP], {
42
+ stdin: "pipe", stdout: "pipe", stderr: "pipe", windowsHide: true,
43
+ }) as unknown as PsChild;
44
+
45
+ /** Encode one request line. The id is a small monotonic counter, never user input. */
46
+ export function encodeRequestLine(id: string, script: string): string {
47
+ return `${id} ${Buffer.from(script, "utf16le").toString("base64")}\n`;
48
+ }
@@ -0,0 +1,182 @@
1
+ /**
2
+ * ONE long-lived PowerShell child for the polling lifetime.
3
+ *
4
+ * Why not spawn per tick: every `powershell.exe` spawn costs a 32 MiB allocator
5
+ * segment Bun never returns to the OS (see windows-process-tree.ts) and ~400 ms
6
+ * versus ~140 ms in-session. Requests are serialised, time-limited, and a
7
+ * failed child may be restarted only a fixed number of times for the server's
8
+ * whole life — a refilling budget would re-arm against a permanently wedged
9
+ * CIM provider and spawn hundreds of times a day.
10
+ */
11
+ import { defaultPsSpawner, encodeRequestLine, type PsChild, type PsSpawner } from "./powershell-session-bootstrap.ts";
12
+
13
+ export { POWERSHELL_BOOTSTRAP, defaultPsSpawner, type PsChild, type PsSpawner } from "./powershell-session-bootstrap.ts";
14
+
15
+ export interface PowerShellSessionOptions {
16
+ spawn?: PsSpawner;
17
+ /** Measured p95 real tick is 206 ms; 5 s only fires on a wedged CIM provider. */
18
+ requestTimeoutMs?: number;
19
+ /** Absolute cap for the server's lifetime — a refilling budget would re-arm
20
+ * against a permanently wedged provider and spawn hundreds of times a day. */
21
+ maxRestarts?: number;
22
+ /** Child working set creeps over hours; a scheduled recycle is free of the budget. */
23
+ recycleAfterMs?: number;
24
+ now?: () => number;
25
+ }
26
+
27
+ export const PS_DISABLED_WARNING = "Windows process collection disabled after repeated PowerShell failures";
28
+
29
+ export class PsSessionBusyError extends Error { constructor() { super("PowerShell request already in flight"); } }
30
+ export class PsSessionDisabledError extends Error { constructor() { super(PS_DISABLED_WARNING); } }
31
+
32
+ interface Pending { id: string; resolve: (s: string) => void; reject: (e: Error) => void; timer: ReturnType<typeof setTimeout> }
33
+
34
+ /** Anything larger than this without an end marker is not a reply we want. */
35
+ const MAX_BUFFER_CHARS = 8 * 1024 * 1024;
36
+
37
+ export class PowerShellSession {
38
+ private readonly spawn: PsSpawner;
39
+ private readonly requestTimeoutMs: number;
40
+ private readonly maxRestarts: number;
41
+ private readonly recycleAfterMs: number;
42
+ private readonly now: () => number;
43
+
44
+ private child: PsChild | null = null;
45
+ private generation = 0;
46
+ private spawnedAt = 0;
47
+ private restarts = 0;
48
+ private everStarted = false;
49
+ private previousDiedAbnormally = false;
50
+ private disabled = false;
51
+ private buffer = "";
52
+ private pending: Pending | null = null;
53
+ private nextId = 1;
54
+
55
+ constructor(opts: PowerShellSessionOptions = {}) {
56
+ this.spawn = opts.spawn ?? defaultPsSpawner;
57
+ this.requestTimeoutMs = opts.requestTimeoutMs ?? 5000;
58
+ this.maxRestarts = opts.maxRestarts ?? 5;
59
+ this.recycleAfterMs = opts.recycleAfterMs ?? 6 * 60 * 60 * 1000;
60
+ this.now = opts.now ?? Date.now;
61
+ }
62
+
63
+ isHealthy(): boolean { return this.child !== null && !this.disabled; }
64
+ isDisabled(): boolean { return this.disabled; }
65
+ isBusy(): boolean { return this.pending !== null; }
66
+ restartCount(): number { return this.restarts; }
67
+ childPid(): number | null { return this.child?.pid ?? null; }
68
+
69
+ request(script: string): Promise<string> {
70
+ if (this.disabled) return Promise.reject(new PsSessionDisabledError());
71
+ if (this.pending) return Promise.reject(new PsSessionBusyError());
72
+ if (this.child && this.now() - this.spawnedAt >= this.recycleAfterMs) this.stop();
73
+ if (!this.child) {
74
+ try { this.start(); } catch (e) { return Promise.reject(e as Error); }
75
+ }
76
+ const child = this.child!;
77
+ const id = String(this.nextId++);
78
+ return new Promise<string>((resolve, reject) => {
79
+ const timer = setTimeout(() => this.onFailure(`PowerShell request timed out after ${this.requestTimeoutMs} ms`), this.requestTimeoutMs);
80
+ this.pending = { id, resolve, reject, timer };
81
+ try {
82
+ child.stdin.write(encodeRequestLine(id, script));
83
+ child.stdin.flush?.();
84
+ } catch (e) {
85
+ this.onFailure(`PowerShell stdin write failed: ${(e as Error).message}`);
86
+ }
87
+ });
88
+ }
89
+
90
+ /** Write nothing, kill, clear. Safe to call repeatedly. No subscribers must mean no child. */
91
+ stop(): void {
92
+ this.teardown(new Error("PowerShell session stopped"));
93
+ }
94
+
95
+ private teardown(pendingError: Error): void {
96
+ const child = this.child;
97
+ this.child = null;
98
+ this.generation++;
99
+ this.buffer = "";
100
+ this.failPending(pendingError);
101
+ if (child) { try { child.kill(); } catch { /* already gone */ } }
102
+ }
103
+
104
+ private start(): void {
105
+ if (this.everStarted && this.previousDiedAbnormally) {
106
+ if (this.restarts >= this.maxRestarts) {
107
+ this.disabled = true;
108
+ throw new PsSessionDisabledError();
109
+ }
110
+ this.restarts++;
111
+ }
112
+ this.everStarted = true;
113
+ this.previousDiedAbnormally = false;
114
+ const gen = ++this.generation;
115
+ const child = this.spawn();
116
+ this.child = child;
117
+ this.spawnedAt = this.now();
118
+ this.buffer = "";
119
+ void this.pump(child, gen);
120
+ void drain(child.stderr);
121
+ child.exited.then(
122
+ () => { if (gen === this.generation) this.onFailure("PowerShell exited unexpectedly"); },
123
+ () => { if (gen === this.generation) this.onFailure("PowerShell exited unexpectedly"); },
124
+ );
125
+ }
126
+
127
+ private async pump(child: PsChild, gen: number): Promise<void> {
128
+ const reader = child.stdout.getReader();
129
+ const decoder = new TextDecoder();
130
+ try {
131
+ while (true) {
132
+ const { done, value } = await reader.read();
133
+ if (done || gen !== this.generation) break;
134
+ this.buffer += decoder.decode(value, { stream: true });
135
+ this.scan();
136
+ }
137
+ } catch { /* stream torn down with the child */ }
138
+ if (gen === this.generation) this.onFailure("PowerShell stdout closed");
139
+ }
140
+
141
+ /** Resolve the pending request on ITS marker; discard any stale marker's output. */
142
+ private scan(): void {
143
+ while (true) {
144
+ const m = /__END_(\d+)__/.exec(this.buffer);
145
+ if (!m) {
146
+ if (this.buffer.length > MAX_BUFFER_CHARS) this.buffer = "";
147
+ return;
148
+ }
149
+ const reply = this.buffer.slice(0, m.index);
150
+ this.buffer = this.buffer.slice(m.index + m[0].length).replace(/^\r?\n/, "");
151
+ const p = this.pending;
152
+ if (p && p.id === m[1]) {
153
+ this.pending = null;
154
+ clearTimeout(p.timer);
155
+ p.resolve(reply);
156
+ }
157
+ }
158
+ }
159
+
160
+ /** Timeout, exit or write failure: kill, mark for a counted restart, reject. */
161
+ private onFailure(reason: string): void {
162
+ this.previousDiedAbnormally = true;
163
+ this.teardown(new Error(reason));
164
+ }
165
+
166
+ private failPending(error: Error): void {
167
+ const p = this.pending;
168
+ if (!p) return;
169
+ this.pending = null;
170
+ clearTimeout(p.timer);
171
+ p.reject(error);
172
+ }
173
+ }
174
+
175
+ /** A full stderr pipe would block the child; read and discard it. */
176
+ async function drain(stream: ReadableStream<Uint8Array> | null | undefined): Promise<void> {
177
+ if (!stream) return;
178
+ try {
179
+ const reader = stream.getReader();
180
+ while (!(await reader.read()).done) { /* discard */ }
181
+ } catch { /* closed with the child */ }
182
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The cosmetic `ppm` flag: PPM's roots (server + supervisor/parent), every
3
+ * descendant of those roots, and the app share tunnel. Drives the "PPM only"
4
+ * filter in the UI. It is NOT a safety mechanism — the kill guard walks the
5
+ * ppid maps itself and never keys off this flag.
6
+ */
7
+ import { collectDescendants } from "./kill-guard.ts";
8
+
9
+ export interface PpmOwnershipInput {
10
+ roots: ReadonlySet<number>;
11
+ /** Extra pids owned outright (the share tunnel, preview tunnels). */
12
+ extraPids: readonly number[];
13
+ ppidOf: ReadonlyMap<number, number>;
14
+ startedAtOf: ReadonlyMap<number, number>;
15
+ }
16
+
17
+ /**
18
+ * Descendants follow ppid links only while the parent started no later than
19
+ * the child — Windows never clears a dead parent's ppid reference, so an
20
+ * unguarded walk would adopt whatever unrelated process later reused that pid.
21
+ */
22
+ export function computePpmPids(input: PpmOwnershipInput): Set<number> {
23
+ const out = new Set<number>();
24
+ const ctx = { ppidOf: input.ppidOf, startedAtOf: input.startedAtOf };
25
+ for (const root of input.roots) {
26
+ if (!input.ppidOf.has(root)) continue;
27
+ out.add(root);
28
+ for (const pid of collectDescendants(root, ctx)) out.add(pid);
29
+ }
30
+ for (const pid of input.extraPids) {
31
+ if (input.ppidOf.has(pid)) out.add(pid);
32
+ }
33
+ return out;
34
+ }