@hienlh/ppm 0.18.7 → 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 (510) 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 +16 -0
  5. package/CLAUDE.md +1 -0
  6. package/assets/skills/ppm/SKILL.md +1 -1
  7. package/assets/skills/ppm/references/http-api.md +5 -3
  8. package/dist/web/assets/{ai-resource-editor-DZQUyrsU.js → ai-resource-editor-DFCuNe-P.js} +1 -1
  9. package/dist/web/assets/{angular-html-jfMqUuRd.js → angular-html-Ctz0zN01.js} +1 -1
  10. package/dist/web/assets/{angular-ts-wytn9PMm.js → angular-ts-QXHpgB1C.js} +1 -1
  11. package/dist/web/assets/{api-settings-DlcoR5QT.js → api-settings-nblja3Rk.js} +1 -1
  12. package/dist/web/assets/{apl-i-ahKx6O.js → apl-b9KVk-O4.js} +1 -1
  13. package/dist/web/assets/architecture-PBZL5I3N-C7ra20CE.js +1 -0
  14. package/dist/web/assets/{astro-DVBCJfG6.js → astro-BlFEeGYr.js} +1 -1
  15. package/dist/web/assets/{audio-preview-GGksv6U8.js → audio-preview-CZLmhf__.js} +1 -1
  16. package/dist/web/assets/{blade-BHlL8SqU.js → blade-CGkj2MUI.js} +1 -1
  17. package/dist/web/assets/{bsl-D-UOfR1F.js → bsl-CVsbb6ap.js} +1 -1
  18. package/dist/web/assets/button-BA_fJOtX.js +1 -0
  19. package/dist/web/assets/{cairo-Bn6rucli.js → cairo-BbIHl2iE.js} +1 -1
  20. package/dist/web/assets/chat-tab-flMPLoKb.js +15 -0
  21. package/dist/web/assets/circle-hjUGru6R.js +1 -0
  22. package/dist/web/assets/circle-question-mark-CzR7YRc-.js +1 -0
  23. package/dist/web/assets/{cobol-Byn9FYKu.js → cobol-BWSGjmWb.js} +1 -1
  24. package/dist/web/assets/code-editor-C2VQbXzw.js +10 -0
  25. package/dist/web/assets/{coffee-DjBl4gm-.js → coffee-CWGNOxds.js} +1 -1
  26. package/dist/web/assets/{conflict-editor-Dg_JIcKq.js → conflict-editor-CdH_h0vD.js} +3 -3
  27. package/dist/web/assets/{context-menu-DkQdt6YA.js → context-menu-Cq0u3SK9.js} +1 -1
  28. package/dist/web/assets/{cpp-CKzic-3E.js → cpp-DHGV24J2.js} +1 -1
  29. package/dist/web/assets/{crystal-Bkg-Ly_g.js → crystal-Vlwf2UMP.js} +1 -1
  30. package/dist/web/assets/{csv-preview-DsJ_a2Op.js → csv-preview-CY_454vd.js} +1 -1
  31. package/dist/web/assets/{data-grid-overlay-editor-B1mTl3KS.js → data-grid-overlay-editor-D9il5DZS.js} +1 -1
  32. package/dist/web/assets/{database-viewer-CzjnrnMz.js → database-viewer-BCZOTrPT.js} +1 -1
  33. package/dist/web/assets/{diff-viewer-DUNkO-ll.js → diff-viewer-BwfMN-nW.js} +1 -1
  34. package/dist/web/assets/{docx-preview-DujpUDkE.js → docx-preview-D3Sdh_aT.js} +1 -1
  35. package/dist/web/assets/{edge-DVbZnd3Y.js → edge-Bhqk64zS.js} +1 -1
  36. package/dist/web/assets/{edit-diff-preview-BivQwZMD.js → edit-diff-preview-gq6ALf2B.js} +1 -1
  37. package/dist/web/assets/{elixir-Dwi8Wu7W.js → elixir-D466WCFm.js} +1 -1
  38. package/dist/web/assets/{elm-DtIv-HXJ.js → elm-Bfs2qNPR.js} +1 -1
  39. package/dist/web/assets/{erb-D3HEDz1x.js → erb-WI7jUaB6.js} +1 -1
  40. package/dist/web/assets/{erlang-2MjTCzGz.js → erlang-BCBe8nCc.js} +1 -1
  41. package/dist/web/assets/{esm-CZ8B8Ba2.js → esm-CZs9WVDO.js} +1 -1
  42. package/dist/web/assets/{explorer-body-DSDJUQs7.js → explorer-body-BKOMM566.js} +2 -2
  43. package/dist/web/assets/{explorer-window-content-CWYBapkj.js → explorer-window-content-Bbzijk8t.js} +1 -1
  44. package/dist/web/assets/{extension-webview-DBTFznQp.js → extension-webview-CuOQrHIS.js} +1 -1
  45. package/dist/web/assets/format-bytes-Dk7B73B7.js +1 -0
  46. package/dist/web/assets/{fortran-fixed-form-BLyAtyPM.js → fortran-fixed-form-CXLIv8Ox.js} +1 -1
  47. package/dist/web/assets/{fsharp-Bxbn_gbr.js → fsharp-CZsYmiw9.js} +1 -1
  48. package/dist/web/assets/{gdresource-sFMY4D2Q.js → gdresource-BGRvoWfC.js} +1 -1
  49. package/dist/web/assets/{git-commit-BzB9Lio5.js → git-commit-DH6mY3Km.js} +1 -1
  50. package/dist/web/assets/{git-log-panel-D8ZQdoYl.js → git-log-panel-DcV7PhqW.js} +1 -1
  51. package/dist/web/assets/{git-rebase-CKSVd848.js → git-rebase-C5Gql6Ma.js} +1 -1
  52. package/dist/web/assets/gitGraph-HDMCJU4V-D4hYLNJU.js +1 -0
  53. package/dist/web/assets/{glide-data-grid-uIjdTT7c.js → glide-data-grid-Cehfgrzc.js} +7 -7
  54. package/dist/web/assets/{glimmer-js-BY8aExAJ.js → glimmer-js-1-6JMJlj.js} +1 -1
  55. package/dist/web/assets/{glimmer-ts-Bak54dBX.js → glimmer-ts-C_Njj0nK.js} +1 -1
  56. package/dist/web/assets/{glsl-nR2eaJQe.js → glsl-DbkxE1TN.js} +1 -1
  57. package/dist/web/assets/{graphql-CGPPFAU6.js → graphql-BK75fiXl.js} +1 -1
  58. package/dist/web/assets/group-chat-tab-BVPYxjz-.js +1 -0
  59. package/dist/web/assets/{hack-CXIMX-Ol.js → hack-DG151vit.js} +1 -1
  60. package/dist/web/assets/{haml-tPY-9Pfm.js → haml-DKeIPQWM.js} +1 -1
  61. package/dist/web/assets/{handlebars-BuW1LT7T.js → handlebars-398uCI13.js} +1 -1
  62. package/dist/web/assets/{html-bgVcwZ-t.js → html-NLWdst5q.js} +1 -1
  63. package/dist/web/assets/{html-derivative-D6-IxTgn.js → html-derivative-CJf_Le2z.js} +1 -1
  64. package/dist/web/assets/{http-CJ1zyB-h.js → http-G1K2FozA.js} +1 -1
  65. package/dist/web/assets/{hurl-CmoT7l3T.js → hurl-WDC6sSBz.js} +1 -1
  66. package/dist/web/assets/{hxml-CztOsL8o.js → hxml-Dc3jBXuf.js} +1 -1
  67. package/dist/web/assets/{image-preview-B0VXSpYu.js → image-preview-D-Ok10eZ.js} +1 -1
  68. package/dist/web/assets/index-CerSxGdf.js +52 -0
  69. package/dist/web/assets/index-DRA_OpWY.css +2 -0
  70. package/dist/web/assets/info-3K5VOQVL-lRlrTlkb.js +1 -0
  71. package/dist/web/assets/{jinja-B1pq3jJq.js → jinja-CWsQj2y0.js} +1 -1
  72. package/dist/web/assets/{jison-D8B5pCwA.js → jison-CciJg2NW.js} +1 -1
  73. package/dist/web/assets/{julia-D0K3bwpU.js → julia-IOQNJAB7.js} +1 -1
  74. package/dist/web/assets/{just-B9Jlddu-.js → just-BGdHchwS.js} +1 -1
  75. package/dist/web/assets/{keybindings-store-FyolpNND.js → keybindings-store-aIY40k2o.js} +1 -1
  76. package/dist/web/assets/{latex-BPJSSE6j.js → latex-D6TOl-L2.js} +1 -1
  77. package/dist/web/assets/{liquid-lv10fo4U.js → liquid-CVSvu_Wn.js} +1 -1
  78. package/dist/web/assets/{lua-PNuaIBEF.js → lua-CcKiU6HW.js} +1 -1
  79. package/dist/web/assets/markdown-renderer-I89kyQhe.js +1 -0
  80. package/dist/web/assets/{markdown-renderer-BaBQ6Wm6.js → markdown-renderer-pVzBdkpl.js} +3 -3
  81. package/dist/web/assets/{marko-Du3frD6X.js → marko--UOicMGo.js} +1 -1
  82. package/dist/web/assets/{mdc-BeDVcFRl.js → mdc-D690aU2C.js} +1 -1
  83. package/dist/web/assets/media-url-CylYQld1.js +1 -0
  84. package/dist/web/assets/{mobile-explorer-sheet-Zxjl-e4c.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-DnGpxgkF.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-xzAA4-kD.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-Dkec6GyK.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-Bz1XrUqI.js → sql-query-editor-BPYsJDsn.js} +1 -1
  113. package/dist/web/assets/{sqlite-viewer-D5-NZw6b.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-DSpZ2zhL.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-DXazqejW.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-Bgp8iceS.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-CpF3A7JL.js → use-monaco-theme-CGucu3fb.js} +1 -1
  130. package/dist/web/assets/{use-open-team-member-CUvV02fA.js → use-open-team-member-DdrRXj-M.js} +1 -1
  131. package/dist/web/assets/{use-websocket-TnL2I1io.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-DYAbbmd0.js +1 -0
  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/src/server/helpers/media-route-handlers.ts +22 -3
  144. package/src/server/index.ts +2 -8
  145. package/src/server/routes/files.ts +5 -2
  146. package/src/server/routes/fs-browse.ts +5 -2
  147. package/src/server/routes/resources.ts +119 -73
  148. package/src/services/autostart-generator.ts +79 -7
  149. package/src/services/autostart-register.ts +15 -2
  150. package/src/services/fs-path-guard.service.ts +17 -1
  151. package/src/services/media-transcode/transcode-stream.ts +27 -5
  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/types/system-metrics.ts +199 -0
  188. package/src/web/components/editor/video-player/video-player.tsx +54 -22
  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/src/web/lib/media-url.ts +30 -4
  225. package/.release-run.sh +0 -5
  226. package/dist/web/assets/architecture-PBZL5I3N-Bs7wzj-W.js +0 -1
  227. package/dist/web/assets/arrow-right-DubGFkN8.js +0 -1
  228. package/dist/web/assets/button-B4MWPjWj.js +0 -1
  229. package/dist/web/assets/chat-tab-Xd2WMjdX.js +0 -15
  230. package/dist/web/assets/circle-question-mark-CENpx4oA.js +0 -1
  231. package/dist/web/assets/code-editor-DqXYJWAB.js +0 -10
  232. package/dist/web/assets/gitGraph-HDMCJU4V-D7i54kbM.js +0 -1
  233. package/dist/web/assets/group-chat-tab-B3sryFdA.js +0 -1
  234. package/dist/web/assets/index-DgbOF3xa.js +0 -52
  235. package/dist/web/assets/index-oxsyfDa0.css +0 -2
  236. package/dist/web/assets/info-3K5VOQVL-BV41AzR9.js +0 -1
  237. package/dist/web/assets/markdown-renderer-feiuhJ9n.js +0 -1
  238. package/dist/web/assets/media-url-CUpN5vI1.js +0 -1
  239. package/dist/web/assets/packet-RMMSAZCW-CaJoP44m.js +0 -1
  240. package/dist/web/assets/pie-UPGHQEXC-DSGZmNw2.js +0 -1
  241. package/dist/web/assets/radar-KQ55EAFF-Be4VUTs0.js +0 -1
  242. package/dist/web/assets/settings-tab-Bd8e6iqY.js +0 -1
  243. package/dist/web/assets/system-monitor-tab-A0jvt5Qw.js +0 -1
  244. package/dist/web/assets/team-member-sheet-5Oaqm8I_.js +0 -2
  245. package/dist/web/assets/treemap-KZPCXAKY-Cu2zgbxU.js +0 -1
  246. package/dist/web/assets/video-preview-CwtLPELG.js +0 -1
  247. package/src/services/resource-monitor-utils.ts +0 -141
  248. package/src/services/resource-monitor.service.ts +0 -147
  249. package/src/web/components/system/system-monitor-group-row.tsx +0 -153
  250. /package/dist/web/assets/{abap-C1K0-wzc.js → abap-MRbmsXOs.js} +0 -0
  251. /package/dist/web/assets/{actionscript-3-CJhQVjLA.js → actionscript-3-BDDHKqa4.js} +0 -0
  252. /package/dist/web/assets/{ada-Bt8r9fME.js → ada-DpuV9KwV.js} +0 -0
  253. /package/dist/web/assets/{andromeeda-DF1I8qi3.js → andromeeda-D6qUCKJo.js} +0 -0
  254. /package/dist/web/assets/{apache-CnlleE6P.js → apache-CX1NU_Tl.js} +0 -0
  255. /package/dist/web/assets/{apex-j0C6Xmk6.js → apex-B4-aoQ3K.js} +0 -0
  256. /package/dist/web/assets/{api-settings-DfNRPr1q.js → api-settings-kQHV6pYZ.js} +0 -0
  257. /package/dist/web/assets/{api-themes-8WTH6KpV.js → api-themes-CrK0tkW_.js} +0 -0
  258. /package/dist/web/assets/{applescript-DO7AnO8U.js → applescript-Dm9NI6KR.js} +0 -0
  259. /package/dist/web/assets/{apply-theme-CNj1iA-v.js → apply-theme-BH_d4amk.js} +0 -0
  260. /package/dist/web/assets/{ara-i83AydZj.js → ara-BGN8GAYn.js} +0 -0
  261. /package/dist/web/assets/{asciidoc-DbBA6-sF.js → asciidoc-s_yVuR3t.js} +0 -0
  262. /package/dist/web/assets/{asm-B5S47Rgr.js → asm-BzQdSvTe.js} +0 -0
  263. /package/dist/web/assets/{aurora-x-De_IaSKw.js → aurora-x-BJTLETG_.js} +0 -0
  264. /package/dist/web/assets/{awk-CfyLHXqS.js → awk-BQEGWxvX.js} +0 -0
  265. /package/dist/web/assets/{ayu-dark-DTLdZ1Si.js → ayu-dark-CpTORmLc.js} +0 -0
  266. /package/dist/web/assets/{ayu-light-DTOfkzhu.js → ayu-light-D8PVj-e6.js} +0 -0
  267. /package/dist/web/assets/{ayu-mirage-DsAECCMv.js → ayu-mirage-DyElQHtm.js} +0 -0
  268. /package/dist/web/assets/{ballerina-CumGp9A7.js → ballerina-C82NkRtj.js} +0 -0
  269. /package/dist/web/assets/{bat-Ca2SBbYN.js → bat-0X7DtGI-.js} +0 -0
  270. /package/dist/web/assets/{beancount-CqyXBwwF.js → beancount-Xgvy6YRl.js} +0 -0
  271. /package/dist/web/assets/{berry-yl-kJr_H.js → berry-CCT2pZcQ.js} +0 -0
  272. /package/dist/web/assets/{bibtex-DoFFszjV.js → bibtex-CpXgZ9M_.js} +0 -0
  273. /package/dist/web/assets/{bicep-CWPi4nfK.js → bicep-fkeSA62l.js} +0 -0
  274. /package/dist/web/assets/{bird2-DXew-ut0.js → bird2-Co7SeAI8.js} +0 -0
  275. /package/dist/web/assets/{c-clbySDvd.js → c-BpmrTvJh.js} +0 -0
  276. /package/dist/web/assets/{c3-B65jvSM1.js → c3-BZ_Z0RrR.js} +0 -0
  277. /package/dist/web/assets/{cadence-Cm8tQTHN.js → cadence-B0GBC8OF.js} +0 -0
  278. /package/dist/web/assets/{can-open-in-ppm-DXGOSUQc.js → can-open-in-ppm-omBzUBBq.js} +0 -0
  279. /package/dist/web/assets/{catppuccin-frappe-DLeGslh_.js → catppuccin-frappe-DIt_xR7m.js} +0 -0
  280. /package/dist/web/assets/{catppuccin-latte-CR5GeHws.js → catppuccin-latte-Dw40AcqA.js} +0 -0
  281. /package/dist/web/assets/{catppuccin-macchiato-p-XgjxhP.js → catppuccin-macchiato-BJ7DfVEF.js} +0 -0
  282. /package/dist/web/assets/{catppuccin-mocha-B8QOAZLl.js → catppuccin-mocha-NI2lfXzU.js} +0 -0
  283. /package/dist/web/assets/{clarity-DPulbvKH.js → clarity-F39L0xMJ.js} +0 -0
  284. /package/dist/web/assets/{clock-D493FU_D.js → clock-CvhF4DJP.js} +0 -0
  285. /package/dist/web/assets/{clojure-DFuWS20u.js → clojure-DloMkd8K.js} +0 -0
  286. /package/dist/web/assets/{cmake-DejCqcu4.js → cmake-CwerJun_.js} +0 -0
  287. /package/dist/web/assets/{code-CLF5x7KK.js → code-DDPoqVri.js} +0 -0
  288. /package/dist/web/assets/{codeowners-BwAyqWIH.js → codeowners-CQyVz4Qf.js} +0 -0
  289. /package/dist/web/assets/{codeql-DgSwFjqI.js → codeql-Bb229zuY.js} +0 -0
  290. /package/dist/web/assets/{common-lisp-CxIVJCtf.js → common-lisp-KMlIwq5I.js} +0 -0
  291. /package/dist/web/assets/{copy-BApI9v7Z.js → copy-DKn11Pye.js} +0 -0
  292. /package/dist/web/assets/{coq-DLSjSnmf.js → coq-DHX_3IIo.js} +0 -0
  293. /package/dist/web/assets/{csharp-C1HHzXBp.js → csharp-CEmCZv9Q.js} +0 -0
  294. /package/dist/web/assets/{css-VXsMY--y.js → css-CqZqBD05.js} +0 -0
  295. /package/dist/web/assets/{csv-BEbcJdHz.js → csv-l1g_V5MV.js} +0 -0
  296. /package/dist/web/assets/{csv-parser-BRtnJCfv.js → csv-parser-CnS0wqr6.js} +0 -0
  297. /package/dist/web/assets/{cue-BkDnFqUD.js → cue-BrxRmilg.js} +0 -0
  298. /package/dist/web/assets/{cypher-1cMqojSQ.js → cypher-rZkKwqZc.js} +0 -0
  299. /package/dist/web/assets/{d-BnYjRXtH.js → d-BALR-QuP.js} +0 -0
  300. /package/dist/web/assets/{dark-plus-XfbaH7kZ.js → dark-plus-Cj7rVwh-.js} +0 -0
  301. /package/dist/web/assets/{dart-Ca7s-8hK.js → dart-CWQcdkXk.js} +0 -0
  302. /package/dist/web/assets/{data-grid-types-BXwlFMzs.js → data-grid-types-CYvF-xK5.js} +0 -0
  303. /package/dist/web/assets/{database-B9okYLx6.js → database-BH0urvbs.js} +0 -0
  304. /package/dist/web/assets/{dax-CmuOw-mY.js → dax-BNHD-QBA.js} +0 -0
  305. /package/dist/web/assets/{desktop-C2gJ6Ovb.js → desktop-CN0IXPrP.js} +0 -0
  306. /package/dist/web/assets/{diff-BCEo1Ej7.js → diff-BtOXapES.js} +0 -0
  307. /package/dist/web/assets/{dist-CUPbqNnL.js → dist-DB1Oaqcc.js} +0 -0
  308. /package/dist/web/assets/{dist-DOlBnxFX.js → dist-Di6G_5jU.js} +0 -0
  309. /package/dist/web/assets/{docker-DN2jlyAh.js → docker-DNsAo_qO.js} +0 -0
  310. /package/dist/web/assets/{dotenv-NExMY2kS.js → dotenv-D6Pl6aOU.js} +0 -0
  311. /package/dist/web/assets/{download-D9UYwY0-.js → download-zCATy4x4.js} +0 -0
  312. /package/dist/web/assets/{dracula-B9lbE01y.js → dracula-C3m-w12D.js} +0 -0
  313. /package/dist/web/assets/{dracula-soft-CMBBfKF_.js → dracula-soft-BYqvXm6Z.js} +0 -0
  314. /package/dist/web/assets/{dream-maker-DEyDwFsd.js → dream-maker-DZAPbPTi.js} +0 -0
  315. /package/dist/web/assets/{emacs-lisp-D_qP2zS6.js → emacs-lisp-Ao5SW8ay.js} +0 -0
  316. /package/dist/web/assets/{everforest-dark-DbHa2U-p.js → everforest-dark-uC8QYotQ.js} +0 -0
  317. /package/dist/web/assets/{everforest-light-BISkJchP.js → everforest-light-CTgsVNMr.js} +0 -0
  318. /package/dist/web/assets/{fennel-6B22SfJR.js → fennel-WuBw6IR1.js} +0 -0
  319. /package/dist/web/assets/{file-exclamation-point-a8f3_w7a.js → file-exclamation-point-COAwgNGw.js} +0 -0
  320. /package/dist/web/assets/{fish-CubIIvJD.js → fish-Byy9dusu.js} +0 -0
  321. /package/dist/web/assets/{fluent-DF55zQ09.js → fluent-CDxb_sgw.js} +0 -0
  322. /package/dist/web/assets/{fortran-free-form-DvOu8jAt.js → fortran-free-form-DKWSTamT.js} +0 -0
  323. /package/dist/web/assets/{gdscript-DCPxdLpq.js → gdscript-prYHMgtD.js} +0 -0
  324. /package/dist/web/assets/{gdshader-CTZ381FO.js → gdshader-D-RM-SQk.js} +0 -0
  325. /package/dist/web/assets/{genie-C_QDtvgU.js → genie-CowkJhej.js} +0 -0
  326. /package/dist/web/assets/{gherkin-BcvK42tF.js → gherkin-CLFpoVYJ.js} +0 -0
  327. /package/dist/web/assets/{github-dark-default-CKGVrl3Z.js → github-dark-default-BK_1Qgb8.js} +0 -0
  328. /package/dist/web/assets/{github-dark-dimmed-C3dQZ_LC.js → github-dark-dimmed-Cv9lj6f-.js} +0 -0
  329. /package/dist/web/assets/{github-dark-high-contrast-DW78QukY.js → github-dark-high-contrast-CW5ZgIDh.js} +0 -0
  330. /package/dist/web/assets/{github-dark-C9afs_4w.js → github-dark-nW2F-RLd.js} +0 -0
  331. /package/dist/web/assets/{github-light-BnP2dznS.js → github-light-D4PqBHGZ.js} +0 -0
  332. /package/dist/web/assets/{github-light-default-C2fPZzPG.js → github-light-default-B-cHtJJV.js} +0 -0
  333. /package/dist/web/assets/{github-light-high-contrast-BzIuUFR2.js → github-light-high-contrast-Dt0HJq50.js} +0 -0
  334. /package/dist/web/assets/{gleam-BpeKwEIO.js → gleam-DwSyXJWP.js} +0 -0
  335. /package/dist/web/assets/{gn-nUb_Mit0.js → gn-Cv5WEzHc.js} +0 -0
  336. /package/dist/web/assets/{gnuplot-D7I0v20p.js → gnuplot-D7bRdY_M.js} +0 -0
  337. /package/dist/web/assets/{go-D7Qqska7.js → go-DiRVJ22U.js} +0 -0
  338. /package/dist/web/assets/{groovy-DS-pne5-.js → groovy-BHAgLTeO.js} +0 -0
  339. /package/dist/web/assets/{gruvbox-dark-hard-C0W01fsq.js → gruvbox-dark-hard-C8QZ3gzY.js} +0 -0
  340. /package/dist/web/assets/{gruvbox-dark-medium-Bqo6fQbg.js → gruvbox-dark-medium-Dp1eeid2.js} +0 -0
  341. /package/dist/web/assets/{gruvbox-dark-soft-D-XSM_fu.js → gruvbox-dark-soft-Cwq0dWVj.js} +0 -0
  342. /package/dist/web/assets/{gruvbox-light-hard-IVAwMJRl.js → gruvbox-light-hard-CLQCq2-w.js} +0 -0
  343. /package/dist/web/assets/{gruvbox-light-medium-38ATiG7i.js → gruvbox-light-medium-APHsh6Mo.js} +0 -0
  344. /package/dist/web/assets/{gruvbox-light-soft-DnZr3c_0.js → gruvbox-light-soft-CX-fYc64.js} +0 -0
  345. /package/dist/web/assets/{haskell-uQcywkDH.js → haskell-C4Tw-TDa.js} +0 -0
  346. /package/dist/web/assets/{haxe-c6bI4_GT.js → haxe-B7fSduTQ.js} +0 -0
  347. /package/dist/web/assets/{hcl-CQXTiEXq.js → hcl-Bi3ho6yC.js} +0 -0
  348. /package/dist/web/assets/{hjson-ChETf2bz.js → hjson-BXwae2M1.js} +0 -0
  349. /package/dist/web/assets/{hlsl-BMC4JGoE.js → hlsl-CRuQLBSa.js} +0 -0
  350. /package/dist/web/assets/{horizon-BusFlhLW.js → horizon-DtdQ6qjv.js} +0 -0
  351. /package/dist/web/assets/{horizon-bright-2oD0Mz7W.js → horizon-bright-BXSF_uKq.js} +0 -0
  352. /package/dist/web/assets/{houston-DdbbjqFg.js → houston-C6ASpUjT.js} +0 -0
  353. /package/dist/web/assets/{hy-D_SOuqw9.js → hy-BrWBHtHY.js} +0 -0
  354. /package/dist/web/assets/{image-gallery-CrM5fHKy.js → image-gallery-CGvlv8zR.js} +0 -0
  355. /package/dist/web/assets/{imba-BxLOHO5I.js → imba-C_JJXckG.js} +0 -0
  356. /package/dist/web/assets/{ini-ox-CFcg0.js → ini-DEE_vSHQ.js} +0 -0
  357. /package/dist/web/assets/{java-Bzo8yIal.js → java-CnmpcjcT.js} +0 -0
  358. /package/dist/web/assets/{javascript-DHuz9VXn.js → javascript-C-M7sa2e.js} +0 -0
  359. /package/dist/web/assets/{json-0_y80FD5.js → json-BjZ3dAk6.js} +0 -0
  360. /package/dist/web/assets/{json5-CEQ50pGM.js → json5-BQ2vpqjp.js} +0 -0
  361. /package/dist/web/assets/{jsonc-CfrLEAKA.js → jsonc-C5MjoWGx.js} +0 -0
  362. /package/dist/web/assets/{jsonl-fKbrANC2.js → jsonl-JvhrmQJI.js} +0 -0
  363. /package/dist/web/assets/{jsonnet-DKbkPaQ2.js → jsonnet-C5pdZVuo.js} +0 -0
  364. /package/dist/web/assets/{jssm-Dxxx1Hqu.js → jssm-Db17uybX.js} +0 -0
  365. /package/dist/web/assets/{jsx-DlJL-Oj3.js → jsx-tJp2Cyqu.js} +0 -0
  366. /package/dist/web/assets/{kanagawa-dragon-CwN4SV1c.js → kanagawa-dragon-BculT_Y1.js} +0 -0
  367. /package/dist/web/assets/{kanagawa-lotus-BHltayiE.js → kanagawa-lotus-yQgHUGwU.js} +0 -0
  368. /package/dist/web/assets/{kanagawa-wave-D-KXPjw6.js → kanagawa-wave-CyGoWN4d.js} +0 -0
  369. /package/dist/web/assets/{kdl-DvtoJdFo.js → kdl-Bn8R1REF.js} +0 -0
  370. /package/dist/web/assets/{kotlin-CTS4MLcx.js → kotlin-DWughK73.js} +0 -0
  371. /package/dist/web/assets/{kusto-HtSE_sKm.js → kusto--serPb0x.js} +0 -0
  372. /package/dist/web/assets/{laserwave-DaXZG9ge.js → laserwave-DfAPJ1tt.js} +0 -0
  373. /package/dist/web/assets/{lean-BYtGUfWx.js → lean-UAm1HOKl.js} +0 -0
  374. /package/dist/web/assets/{less-BoxmU_Mk.js → less-Xj6Ka0fF.js} +0 -0
  375. /package/dist/web/assets/{lib-B1clP4ai.js → lib-DgNcCtj3.js} +0 -0
  376. /package/dist/web/assets/{libesm-ah-mr-sh.js → libesm-CPh1Av0r.js} +0 -0
  377. /package/dist/web/assets/{light-plus-Bt5CyUuo.js → light-plus-BfS7gPcj.js} +0 -0
  378. /package/dist/web/assets/{llvm-CSdk9q9V.js → llvm-DvWiVwvU.js} +0 -0
  379. /package/dist/web/assets/{log-B-kp_3CL.js → log-Bo5z9bNz.js} +0 -0
  380. /package/dist/web/assets/{logo-DdIsXFDO.js → logo-CrIjcMZT.js} +0 -0
  381. /package/dist/web/assets/{luau-DUBpLlzQ.js → luau-C9TsYwNt.js} +0 -0
  382. /package/dist/web/assets/{make-B3JVjoW_.js → make-GYq4qVbx.js} +0 -0
  383. /package/dist/web/assets/{markdown-Seon0vHs.js → markdown-p5mNledS.js} +0 -0
  384. /package/dist/web/assets/{material-theme-Nq-ChX1P.js → material-theme-CWYOVxsP.js} +0 -0
  385. /package/dist/web/assets/{material-theme-darker-CPV4ayXJ.js → material-theme-darker-BDGty7YH.js} +0 -0
  386. /package/dist/web/assets/{material-theme-lighter-0kyjYqEd.js → material-theme-lighter-JbgOgV3n.js} +0 -0
  387. /package/dist/web/assets/{material-theme-ocean-DGpAp5co.js → material-theme-ocean-EMOpLpa2.js} +0 -0
  388. /package/dist/web/assets/{material-theme-palenight-B0AUn0NG.js → material-theme-palenight-CY5hgm7h.js} +0 -0
  389. /package/dist/web/assets/{matlab-C2waytxs.js → matlab-C-He_NTH.js} +0 -0
  390. /package/dist/web/assets/{mdx-DAis6R6I.js → mdx-Cr2TR5fj.js} +0 -0
  391. /package/dist/web/assets/{mermaid-_rnT2YGD.js → mermaid-BYc0-B0U.js} +0 -0
  392. /package/dist/web/assets/{min-dark-BSSjchUB.js → min-dark-CMJwqJqB.js} +0 -0
  393. /package/dist/web/assets/{min-light-DomAFQsa.js → min-light-Cx6vFiEX.js} +0 -0
  394. /package/dist/web/assets/{mipsasm-bBgtvPyG.js → mipsasm-Bjer5HwK.js} +0 -0
  395. /package/dist/web/assets/{mobile-bottom-sheet-CS3XMwFw.js → mobile-bottom-sheet-BUOJgiaZ.js} +0 -0
  396. /package/dist/web/assets/{mojo-Cp9BayW0.js → mojo-t90PR-Y2.js} +0 -0
  397. /package/dist/web/assets/{monokai-CL_9gbmn.js → monokai-dci_PdCm.js} +0 -0
  398. /package/dist/web/assets/{moonbit-BS_fcr-P.js → moonbit-AAzI-Hd-.js} +0 -0
  399. /package/dist/web/assets/{move-C79AH45U.js → move-kwBhnhrG.js} +0 -0
  400. /package/dist/web/assets/{narrat-CJ5s3BDf.js → narrat-CXww2YQL.js} +0 -0
  401. /package/dist/web/assets/{nextflow-groovy-ZHa4JrPJ.js → nextflow-groovy-CJXsuXGB.js} +0 -0
  402. /package/dist/web/assets/{night-owl-Jkf9zFQK.js → night-owl-_GD204Wr.js} +0 -0
  403. /package/dist/web/assets/{night-owl-light-DRPeaG5J.js → night-owl-light-DNgkw3kl.js} +0 -0
  404. /package/dist/web/assets/{nix-D2Jet9DN.js → nix-BgiorKFd.js} +0 -0
  405. /package/dist/web/assets/{nord-CREVs22j.js → nord-CaBmcxFC.js} +0 -0
  406. /package/dist/web/assets/{nushell-CAiDi_mR.js → nushell-DUh4UGx1.js} +0 -0
  407. /package/dist/web/assets/{objective-c-CVkmJkC1.js → objective-c-Cl9KU86S.js} +0 -0
  408. /package/dist/web/assets/{objective-cpp-DIKDO1Ly.js → objective-cpp-DVkIA8A0.js} +0 -0
  409. /package/dist/web/assets/{ocaml-R9qtGQhs.js → ocaml-vvoHTak0.js} +0 -0
  410. /package/dist/web/assets/{odin-DTYNQqVr.js → odin-Cyjw8woZ.js} +0 -0
  411. /package/dist/web/assets/{one-dark-pro-BSLWUJn5.js → one-dark-pro-B1cviILi.js} +0 -0
  412. /package/dist/web/assets/{one-light-DbkRXG3t.js → one-light-BPGUJeYI.js} +0 -0
  413. /package/dist/web/assets/{openscad-BlPcSnmT.js → openscad-BLMdTUU8.js} +0 -0
  414. /package/dist/web/assets/{pascal-B1Y46ZZB.js → pascal-i5niy3e7.js} +0 -0
  415. /package/dist/web/assets/{pkl-BhJSJbFv.js → pkl-CuOV7SsU.js} +0 -0
  416. /package/dist/web/assets/{plastic-BzxsCTpi.js → plastic-Bf_zE5KL.js} +0 -0
  417. /package/dist/web/assets/{plsql-DBba7dyP.js → plsql-cfqEtMD3.js} +0 -0
  418. /package/dist/web/assets/{plus-DmjC2iRB.js → plus-BM-Ty0fp.js} +0 -0
  419. /package/dist/web/assets/{po-BvgLlnNo.js → po-CFJcWgjr.js} +0 -0
  420. /package/dist/web/assets/{poimandres-DUaI_1JP.js → poimandres-G5YoaIFf.js} +0 -0
  421. /package/dist/web/assets/{polar-C7uILwJn.js → polar-rcjs3i9R.js} +0 -0
  422. /package/dist/web/assets/{postcss-BgJlpFdw.js → postcss-CBKY1FTZ.js} +0 -0
  423. /package/dist/web/assets/{powerquery-Dn1MIpZu.js → powerquery-Db7SXLbO.js} +0 -0
  424. /package/dist/web/assets/{powershell-Bo-DYzOS.js → powershell-LFy3MUTP.js} +0 -0
  425. /package/dist/web/assets/{prisma-CTLs5IdT.js → prisma-BE8GR1lH.js} +0 -0
  426. /package/dist/web/assets/{prolog-QRGun3eG.js → prolog-DOn5lR1e.js} +0 -0
  427. /package/dist/web/assets/{proto-B7PI7apn.js → proto-wr-TpAK_.js} +0 -0
  428. /package/dist/web/assets/{puppet-CBq0tLrP.js → puppet-D2Dkv62u.js} +0 -0
  429. /package/dist/web/assets/{purescript-DFewOQb2.js → purescript-DvgJgPdy.js} +0 -0
  430. /package/dist/web/assets/{python-iWuxKXvT.js → python-C7TlkHhK.js} +0 -0
  431. /package/dist/web/assets/{qmldir-cXiW3AsF.js → qmldir-CtZMwhcW.js} +0 -0
  432. /package/dist/web/assets/{qss-DASwAbBL.js → qss-dNZ2btnl.js} +0 -0
  433. /package/dist/web/assets/{r-TU2eaIPw.js → r-BlqnNkHS.js} +0 -0
  434. /package/dist/web/assets/{racket-SkRKqrLY.js → racket-CzRQrGc4.js} +0 -0
  435. /package/dist/web/assets/{raku-D31lthkZ.js → raku-BwutWhBF.js} +0 -0
  436. /package/dist/web/assets/{red-CTcQZevb.js → red-BMXMywmL.js} +0 -0
  437. /package/dist/web/assets/{reg-D8YAsTGf.js → reg-BqOKrIOw.js} +0 -0
  438. /package/dist/web/assets/{regexp-CD2uvAWx.js → regexp-Bero1BN2.js} +0 -0
  439. /package/dist/web/assets/{rel-CAaI-1fg.js → rel-BXKWIElA.js} +0 -0
  440. /package/dist/web/assets/{resolve-theme-CJvkL8hU.js → resolve-theme-IdhSR-gx.js} +0 -0
  441. /package/dist/web/assets/{riscv-DR-hJVIj.js → riscv-BbbBYJBo.js} +0 -0
  442. /package/dist/web/assets/{ron-CuUCJ0n4.js → ron-BtVTWW4b.js} +0 -0
  443. /package/dist/web/assets/{rose-pine-dawn-Bqz2sBRY.js → rose-pine-dawn-D7lwhUei.js} +0 -0
  444. /package/dist/web/assets/{rose-pine-aFHxW48i.js → rose-pine-hvkvQzvU.js} +0 -0
  445. /package/dist/web/assets/{rose-pine-moon-wqyh0an4.js → rose-pine-moon-CoHDmsIw.js} +0 -0
  446. /package/dist/web/assets/{rosmsg-CI1ywimO.js → rosmsg-CdaZFgI8.js} +0 -0
  447. /package/dist/web/assets/{run-in-terminal-CGW6o37_.js → run-in-terminal-CyS5Itj-.js} +0 -0
  448. /package/dist/web/assets/{rust-p7Imk4G_.js → rust-Dy2qsphD.js} +0 -0
  449. /package/dist/web/assets/{sass-C8JfaqCV.js → sass-Bz7NVxDb.js} +0 -0
  450. /package/dist/web/assets/{save-DRPrDfTt.js → save-C4z1p51e.js} +0 -0
  451. /package/dist/web/assets/{scala-DNxCW1By.js → scala-sXSwsNyq.js} +0 -0
  452. /package/dist/web/assets/{scheme-BYuUPJoL.js → scheme-DS7TUbN7.js} +0 -0
  453. /package/dist/web/assets/{sdbl-DbPeJPUr.js → sdbl-iISFvIep.js} +0 -0
  454. /package/dist/web/assets/{send-to-chat-YXHdAyLG.js → send-to-chat-BcO39BDR.js} +0 -0
  455. /package/dist/web/assets/{shellscript-DMiHlR3q.js → shellscript-BkIl4ApC.js} +0 -0
  456. /package/dist/web/assets/{shield-check-8GObuUAn.js → shield-check-C5laObJv.js} +0 -0
  457. /package/dist/web/assets/{shield-off-egKAZEwR.js → shield-off-DULFtyLS.js} +0 -0
  458. /package/dist/web/assets/{slack-dark-C4xGcQXI.js → slack-dark-B1eg0_m2.js} +0 -0
  459. /package/dist/web/assets/{slack-ochin-BzgRt_wm.js → slack-ochin-mdkc1ldu.js} +0 -0
  460. /package/dist/web/assets/{smalltalk-LDeL9PYH.js → smalltalk-CORtd03t.js} +0 -0
  461. /package/dist/web/assets/{snazzy-light-CXE7a5j_.js → snazzy-light-Bc6Q2G89.js} +0 -0
  462. /package/dist/web/assets/{solarized-dark-DgUhY74x.js → solarized-dark-CF83zRXM.js} +0 -0
  463. /package/dist/web/assets/{solarized-light-DD9C-H-9.js → solarized-light-BoKQZaYU.js} +0 -0
  464. /package/dist/web/assets/{solidity-CAbDB4D4.js → solidity-DOgi1N4w.js} +0 -0
  465. /package/dist/web/assets/{sparkles-n1hzh65o.js → sparkles-Dqsf3hq6.js} +0 -0
  466. /package/dist/web/assets/{splunk-kQREPfIc.js → splunk-BXfw5ZLy.js} +0 -0
  467. /package/dist/web/assets/{sql-CBzeNAD8.js → sql-BcVs-eX4.js} +0 -0
  468. /package/dist/web/assets/{ssh-config-L1euxrsM.js → ssh-config-CLCtNkkd.js} +0 -0
  469. /package/dist/web/assets/{stylus-DvBnYniP.js → stylus-DdP992aO.js} +0 -0
  470. /package/dist/web/assets/{swift-DF5NDQp6.js → swift-BnGb6Lgc.js} +0 -0
  471. /package/dist/web/assets/{synthwave-84-DbBhB_Hq.js → synthwave-84-cg9264l9.js} +0 -0
  472. /package/dist/web/assets/{system-verilog-D8s2ZW_k.js → system-verilog-GbHpszs3.js} +0 -0
  473. /package/dist/web/assets/{systemd-a5-XZJsG.js → systemd-Dz-bNsDQ.js} +0 -0
  474. /package/dist/web/assets/{table-BX2ZrJfM.js → table-CHmxuh6M.js} +0 -0
  475. /package/dist/web/assets/{talonscript-BLa0URTW.js → talonscript-CFIidoBA.js} +0 -0
  476. /package/dist/web/assets/{tasl-DIoV4XcC.js → tasl-Cu-TRTKx.js} +0 -0
  477. /package/dist/web/assets/{tcl-ztYAdXfQ.js → tcl-DwCHCB1K.js} +0 -0
  478. /package/dist/web/assets/{terraform-DvpCCiOZ.js → terraform-BzZw4T1z.js} +0 -0
  479. /package/dist/web/assets/{tokyo-night-BkHlYUv0.js → tokyo-night-RKsj2-tv.js} +0 -0
  480. /package/dist/web/assets/{toml-acIrxos6.js → toml-CirbOgDP.js} +0 -0
  481. /package/dist/web/assets/{tsv-BJB5EVCT.js → tsv-CraRcWdU.js} +0 -0
  482. /package/dist/web/assets/{tsx-B1MmXGT3.js → tsx-CjFg0lgw.js} +0 -0
  483. /package/dist/web/assets/{turtle-DFceTiqd.js → turtle-B-WBIOa6.js} +0 -0
  484. /package/dist/web/assets/{typescript-Dz9wU5Y1.js → typescript-MpLarYn1.js} +0 -0
  485. /package/dist/web/assets/{typespec-CPuYZijj.js → typespec-B7QlHMZ_.js} +0 -0
  486. /package/dist/web/assets/{typst-CfsCIYv8.js → typst-CcHSKFZj.js} +0 -0
  487. /package/dist/web/assets/{use-blob-url-BmlYYZ8L.js → use-blob-url-BKyVxOZw.js} +0 -0
  488. /package/dist/web/assets/{use-is-mobile-B8FA4kQf.js → use-is-mobile-BXGVvczu.js} +0 -0
  489. /package/dist/web/assets/{v-CGo0jcXA.js → v-xTGhWZuD.js} +0 -0
  490. /package/dist/web/assets/{vala-AsSR0hrb.js → vala-DwebjH3H.js} +0 -0
  491. /package/dist/web/assets/{vb-C7tvbXv1.js → vb-BxJT2RAy.js} +0 -0
  492. /package/dist/web/assets/{vendor-xterm-C1diXHJl.js → vendor-xterm-CU6zIYMB.js} +0 -0
  493. /package/dist/web/assets/{verilog--a33ND-p.js → verilog-CvV6RHPD.js} +0 -0
  494. /package/dist/web/assets/{vesper-B_Z0h4pn.js → vesper-CY3qd7E_.js} +0 -0
  495. /package/dist/web/assets/{vhdl-CWL5dZPN.js → vhdl-B9ZX-sUL.js} +0 -0
  496. /package/dist/web/assets/{viml-BglmT14Y.js → viml-Y42h_ExQ.js} +0 -0
  497. /package/dist/web/assets/{vitesse-black-RKFsSqQI.js → vitesse-black-DkXP6Sv-.js} +0 -0
  498. /package/dist/web/assets/{vitesse-dark-D7zDWNmc.js → vitesse-dark-B9CkIB6r.js} +0 -0
  499. /package/dist/web/assets/{vitesse-light-MAp87W5b.js → vitesse-light-C7DHrJCK.js} +0 -0
  500. /package/dist/web/assets/{vyper-CgCBYg1G.js → vyper-Cnd9s5j-.js} +0 -0
  501. /package/dist/web/assets/{wasm-Bwl4txwp.js → wasm-DQE71XTB.js} +0 -0
  502. /package/dist/web/assets/{wasm-BOG7ZeTT.js → wasm-iWe7Fzjc.js} +0 -0
  503. /package/dist/web/assets/{wenyan-DpShPKXZ.js → wenyan-Bc5Pnm9l.js} +0 -0
  504. /package/dist/web/assets/{wgsl-BakcCblK.js → wgsl-D-YUAWkP.js} +0 -0
  505. /package/dist/web/assets/{wikitext-NroRWVAO.js → wikitext-DYQDUYf2.js} +0 -0
  506. /package/dist/web/assets/{wit-B5CM2pg6.js → wit-P6u7mfwy.js} +0 -0
  507. /package/dist/web/assets/{wolfram-7MTFBJpR.js → wolfram-6SXLUqao.js} +0 -0
  508. /package/dist/web/assets/{yaml-Bwr01G2K.js → yaml-CQiMLVcZ.js} +0 -0
  509. /package/dist/web/assets/{zenscript-Dj8GATvi.js → zenscript-DFMywo_P.js} +0 -0
  510. /package/dist/web/assets/{zig-LAE-fbS-.js → zig-CtAjaIiF.js} +0 -0
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Zero-IO parser for the tagged, tab-separated lines one Windows tick returns:
3
+ *
4
+ * P<TAB>pid<TAB>ppid<TAB>Name<TAB>KernelModeTime<TAB>UserModeTime<TAB>WorkingSetSize<TAB>CreationDateUtcTicks<TAB>ReadTransferCount<TAB>WriteTransferCount
5
+ * C<TAB>pid<TAB>CreationDateUtcTicks<TAB>CommandLine (every 30 s only)
6
+ * D… / N… (disk/net counters)
7
+ * G… / M… (per-process GPU)
8
+ * __ERR__ <message> (a failed block)
9
+ *
10
+ * `CommandLine` is always the LAST field and may itself contain tabs, so rows
11
+ * are split with a field limit — a naive `split("\t")` corrupts them.
12
+ *
13
+ * The two transfer counts are appended AFTER the creation ticks so a `P` row
14
+ * from an older shape (or a host where the properties are empty) still parses,
15
+ * it just reports no disk figures.
16
+ */
17
+ import { parsePerfRawDiskNet } from "./disk-net-collector-windows.ts";
18
+ import { parseGpuLines, type ParsedGpuLines } from "./gpu-process-usage-windows.ts";
19
+ import type { CounterSample } from "./rate-delta.ts";
20
+ import { stripExecutableExtension, type RawProcessRow } from "./process-collector-types.ts";
21
+
22
+ export interface WindowsCommandLine {
23
+ pid: number;
24
+ startedAt: number;
25
+ command: string;
26
+ }
27
+
28
+ export interface ParsedWindowsTick {
29
+ /** PID 0 (System Idle Process) is excluded — its kernel time is idle time and
30
+ * inflates a naive CPU roll-up to ~99 %. */
31
+ processes: RawProcessRow[];
32
+ /** Null when the tick carried no `C` section. */
33
+ commands: WindowsCommandLine[] | null;
34
+ disk: CounterSample | null;
35
+ net: CounterSample | null;
36
+ /** Raw per-process GPU samples; the collector turns them into rates. */
37
+ gpu: ParsedGpuLines;
38
+ errors: string[];
39
+ }
40
+
41
+ /** .NET ticks (100 ns since 0001-01-01) → Unix epoch ms. Input MUST already be
42
+ * UTC — the query calls `.ToUniversalTime()` because only .NET on that machine
43
+ * knows the DST rule in force when the process started. BigInt because the
44
+ * tick value exceeds 2^53. */
45
+ export function ticksToEpochMs(ticks: string): number {
46
+ if (!/^\d+$/.test(ticks)) return 0;
47
+ const EPOCH_TICKS = 621355968000000000n;
48
+ const ms = (BigInt(ticks) - EPOCH_TICKS) / 10000n;
49
+ return ms > 0n ? Number(ms) : 0;
50
+ }
51
+
52
+ /** Split into at most `limit` fields; the remainder stays glued to the last one. */
53
+ export function splitLimited(line: string, limit: number): string[] {
54
+ const out: string[] = [];
55
+ let start = 0;
56
+ while (out.length < limit - 1) {
57
+ const i = line.indexOf("\t", start);
58
+ if (i < 0) break;
59
+ out.push(line.slice(start, i));
60
+ start = i + 1;
61
+ }
62
+ out.push(line.slice(start));
63
+ return out;
64
+ }
65
+
66
+ const HUNDRED_NS_PER_MS = 10_000;
67
+ const BYTES_PER_MB = 1024 * 1024;
68
+
69
+ /** An empty (property absent / access denied) or non-numeric counter field is
70
+ * "the OS did not say", which must stay `undefined` rather than become 0. */
71
+ function optionalCount(field: string | undefined): number | undefined {
72
+ const text = (field ?? "").trim();
73
+ if (!/^\d+$/.test(text)) return undefined;
74
+ const n = Number(text);
75
+ return Number.isFinite(n) ? n : undefined;
76
+ }
77
+
78
+ function parseProcessLine(f: string[]): RawProcessRow | null {
79
+ const pid = Number(f[1]);
80
+ const ppid = Number(f[2]);
81
+ const kernel = Number(f[4]);
82
+ const user = Number(f[5]);
83
+ const ws = Number(f[6]);
84
+ if (![pid, ppid, kernel, user, ws].every(Number.isFinite)) return null;
85
+ if (pid === 0) return null;
86
+ return {
87
+ pid,
88
+ ppid: ppid >= 0 ? ppid : -1,
89
+ name: stripExecutableExtension((f[3] ?? "").trim()) || String(pid),
90
+ command: null,
91
+ cpuMs: (kernel + user) / HUNDRED_NS_PER_MS,
92
+ ramMB: ws / BYTES_PER_MB,
93
+ startedAt: ticksToEpochMs((f[7] ?? "").trim()),
94
+ diskReadBytes: optionalCount(f[8]),
95
+ diskWriteBytes: optionalCount(f[9]),
96
+ };
97
+ }
98
+
99
+ /** `CommandLine` arrives base64(UTF-8) because argv is attacker-controlled and
100
+ * the transport is line-framed. Anything that is not valid base64 is dropped —
101
+ * a raw string here means the field was tampered with, not that it is a command. */
102
+ export function decodeCommandLine(b64: string): string {
103
+ if (!b64 || !/^[A-Za-z0-9+/]+={0,2}$/.test(b64)) return "";
104
+ try {
105
+ return Buffer.from(b64, "base64").toString("utf-8").trim();
106
+ } catch {
107
+ return "";
108
+ }
109
+ }
110
+
111
+ export function parseWindowsTick(text: string): ParsedWindowsTick {
112
+ const processes: RawProcessRow[] = [];
113
+ let commands: WindowsCommandLine[] | null = null;
114
+ const counterLines: string[] = [];
115
+ const gpuLines: string[] = [];
116
+ const errors: string[] = [];
117
+
118
+ for (const raw of text.split("\n")) {
119
+ const line = raw.endsWith("\r") ? raw.slice(0, -1) : raw;
120
+ if (!line) continue;
121
+ switch (line.slice(0, 2)) {
122
+ case "P\t": {
123
+ const row = parseProcessLine(splitLimited(line, 10));
124
+ if (row) processes.push(row);
125
+ break;
126
+ }
127
+ case "C\t": {
128
+ const f = splitLimited(line, 4);
129
+ const pid = Number(f[1]);
130
+ // A `C` section that exists but is all-null still counts as fetched.
131
+ commands ??= [];
132
+ if (!Number.isFinite(pid) || f.length < 4) break;
133
+ const command = decodeCommandLine((f[3] ?? "").trim());
134
+ if (command) commands.push({ pid, startedAt: ticksToEpochMs((f[2] ?? "").trim()), command });
135
+ break;
136
+ }
137
+ case "D\t":
138
+ case "N\t":
139
+ counterLines.push(line);
140
+ break;
141
+ case "G\t":
142
+ case "M\t":
143
+ gpuLines.push(line);
144
+ break;
145
+ default:
146
+ if (line.startsWith("__ERR__")) errors.push(line.slice("__ERR__".length).trim());
147
+ break;
148
+ }
149
+ }
150
+
151
+ const { disk, net } = parsePerfRawDiskNet(counterLines);
152
+ return { processes, commands, disk, net, gpu: parseGpuLines(gpuLines), errors };
153
+ }
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Windows process collector: one `Win32_Process` + disk + net round trip per
3
+ * tick through the long-lived PowerShell session (measured 172-206 ms), plus
4
+ * the expensive `CommandLine` pass only every 30 s.
5
+ *
6
+ * `Get-Process` is not used at all: unelevated it silently returns null CPU and
7
+ * start time for ~45 % of rows. `Win32_Process` with this property list has
8
+ * zero nulls. All scripts are static strings — no user input ever reaches them.
9
+ */
10
+ import type { ProcessCollection, ProcessCollector, RawProcessRow } from "./process-collector-types.ts";
11
+ import { createStickyColumns } from "./process-collector-types.ts";
12
+ import { PowerShellSession, PsSessionDisabledError, PS_DISABLED_WARNING } from "./powershell-session.ts";
13
+ import { parseWindowsTick, type WindowsCommandLine } from "./process-collector-windows-parse.ts";
14
+ import { computeGpuPercents, memBytesToMB, type GpuUsageState } from "./gpu-process-usage-windows.ts";
15
+
16
+ /** `.ToUniversalTime()` here, not in JS: only .NET on this machine knows which
17
+ * DST rule applied at the instant each process started. */
18
+ const CREATION_UTC_TICKS = "$($_.CreationDate.ToUniversalTime().Ticks)";
19
+
20
+ export const WINDOWS_TICK_SCRIPT = [
21
+ "Get-CimInstance Win32_Process -Property ProcessId,ParentProcessId,Name,KernelModeTime,UserModeTime,WorkingSetSize,CreationDate,ReadTransferCount,WriteTransferCount | " +
22
+ `ForEach-Object { "P\`t$($_.ProcessId)\`t$($_.ParentProcessId)\`t$($_.Name)\`t$($_.KernelModeTime)\`t$($_.UserModeTime)\`t$($_.WorkingSetSize)\`t${CREATION_UTC_TICKS}\`t$($_.ReadTransferCount)\`t$($_.WriteTransferCount)" }`,
23
+ "Get-CimInstance Win32_PerfRawData_PerfDisk_PhysicalDisk -Filter \"Name='_Total'\" | " +
24
+ 'ForEach-Object { "D`t$($_.DiskReadBytesPerSec)`t$($_.DiskWriteBytesPerSec)`t$($_.Timestamp_PerfTime)`t$($_.Frequency_PerfTime)" }',
25
+ "Get-CimInstance Win32_PerfRawData_Tcpip_NetworkInterface | " +
26
+ 'ForEach-Object { "N`t$($_.Name)`t$($_.BytesReceivedPersec)`t$($_.BytesSentPersec)`t$($_.Timestamp_Sys100NS)" }',
27
+ // 505 engine instances on a dev box, of which ~50 are busy: filtering in
28
+ // PowerShell keeps the reply an order of magnitude smaller than the class.
29
+ "Get-CimInstance Win32_PerfRawData_GPUPerformanceCounters_GPUEngine | Where-Object { $_.UtilizationPercentage -gt 0 } | " +
30
+ 'ForEach-Object { "G`t$($_.Name)`t$($_.UtilizationPercentage)`t$($_.Timestamp_Sys100NS)" }',
31
+ "Get-CimInstance Win32_PerfRawData_GPUPerformanceCounters_GPUProcessMemory | " +
32
+ 'ForEach-Object { "M`t$($_.Name)`t$($_.DedicatedUsage)" }',
33
+ ].join("\n");
34
+
35
+ /** +10 ms and +95 KB per fetch, and ~half the rows are access-denied (null)
36
+ * unelevated — so it runs on its own slow cadence and merges by identity.
37
+ * `CommandLine` is the only attacker-controlled field in the whole round trip
38
+ * (any local process picks its own argv), so it travels base64-encoded: raw,
39
+ * an embedded CR/LF would let it forge a `P` row for another pid or inject an
40
+ * `__END_<id>__` line that truncates the reply. */
41
+ export const WINDOWS_COMMANDLINE_SCRIPT =
42
+ "Get-CimInstance Win32_Process -Property ProcessId,CommandLine,CreationDate | " +
43
+ `ForEach-Object { "C\`t$($_.ProcessId)\`t${CREATION_UTC_TICKS}\`t$([Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes([string]$_.CommandLine)))" }`;
44
+
45
+ export const COMMANDLINE_REFRESH_MS = 30_000;
46
+
47
+ export interface WindowsProcessCollectorOptions {
48
+ session?: PowerShellSession;
49
+ now?: () => number;
50
+ commandRefreshMs?: number;
51
+ /** Seam for the one-shot startup timing line, so tests stay silent. */
52
+ log?: (message: string) => void;
53
+ }
54
+
55
+ export interface WindowsProcessCollector extends ProcessCollector {
56
+ readonly session: PowerShellSession;
57
+ }
58
+
59
+ export function createWindowsProcessCollector(opts: WindowsProcessCollectorOptions = {}): WindowsProcessCollector {
60
+ const session = opts.session ?? new PowerShellSession();
61
+ const now = opts.now ?? Date.now;
62
+ const refreshMs = opts.commandRefreshMs ?? COMMANDLINE_REFRESH_MS;
63
+ const log = opts.log ?? ((m: string) => console.log(m));
64
+ const observeColumns = createStickyColumns();
65
+ let commandByPid = new Map<number, WindowsCommandLine>();
66
+ let lastCommandFetchAt = Number.NEGATIVE_INFINITY;
67
+ let gpuState: GpuUsageState | null = null;
68
+ let logged = false;
69
+
70
+ return {
71
+ session,
72
+ stop: () => session.stop(),
73
+ async collect(): Promise<ProcessCollection> {
74
+ if (session.isDisabled()) return { rows: [], columns: observeColumns({}), warnings: [PS_DISABLED_WARNING] };
75
+
76
+ const wantCommands = now() - lastCommandFetchAt >= refreshMs;
77
+ const script = wantCommands ? `${WINDOWS_TICK_SCRIPT}\n${WINDOWS_COMMANDLINE_SCRIPT}` : WINDOWS_TICK_SCRIPT;
78
+ const startedRequestAt = now();
79
+ let text: string;
80
+ try {
81
+ text = await session.request(script);
82
+ } catch (e) {
83
+ if (e instanceof PsSessionDisabledError) {
84
+ return { rows: [], columns: observeColumns({}), warnings: [PS_DISABLED_WARNING] };
85
+ }
86
+ throw e;
87
+ }
88
+ if (!logged) {
89
+ logged = true;
90
+ // One line, once: the round trip now also carries the two GPU classes,
91
+ // and the 2 s tick budget is the thing that would break first.
92
+ log(`[system-metrics] windows tick round trip (incl. GPU pass): ${now() - startedRequestAt} ms`);
93
+ }
94
+
95
+ const parsed = parseWindowsTick(text);
96
+ if (parsed.commands) {
97
+ commandByPid = new Map(parsed.commands.map((c) => [c.pid, c]));
98
+ lastCommandFetchAt = now();
99
+ }
100
+
101
+ // First row for a pid wins, like the guard maps: a forged duplicate must
102
+ // not decide which start time the GPU delta key is anchored to.
103
+ const startedAtByPid = new Map<number, number>();
104
+ for (const p of parsed.processes) if (!startedAtByPid.has(p.pid)) startedAtByPid.set(p.pid, p.startedAt);
105
+ const gpu = computeGpuPercents(gpuState, parsed.gpu.engines, (pid) => startedAtByPid.get(pid));
106
+ gpuState = gpu.next;
107
+
108
+ const rows: RawProcessRow[] = parsed.processes.map((r) => ({
109
+ ...r,
110
+ command: mergeCommand(r, commandByPid.get(r.pid)),
111
+ // Windows reports GPU per pid for the whole machine, so a pid with no
112
+ // engine instance is measured-and-idle (0), not unmeasurable.
113
+ gpuPct: parsed.gpu.present ? gpu.pctByPid.get(r.pid) ?? 0 : undefined,
114
+ gpuMemMB: parsed.gpu.present ? memBytesToMB(parsed.gpu.memBytesByPid.get(r.pid) ?? 0) : undefined,
115
+ }));
116
+ return {
117
+ rows,
118
+ disk: parsed.disk,
119
+ net: parsed.net,
120
+ columns: observeColumns({
121
+ disk: rows.some((r) => r.diskReadBytes !== undefined),
122
+ gpu: parsed.gpu.present,
123
+ }),
124
+ warnings: parsed.errors.map((e) => `PowerShell: ${e}`),
125
+ };
126
+ },
127
+ };
128
+ }
129
+
130
+ /** A pid new since the last 30 s fetch — or recycled since — has no command
131
+ * yet; the row falls back to its name until the next fetch. */
132
+ export function mergeCommand(row: RawProcessRow, cached: WindowsCommandLine | undefined): string | null {
133
+ if (!cached) return null;
134
+ if (cached.startedAt && row.startedAt && cached.startedAt !== row.startedAt) return null;
135
+ return cached.command;
136
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Instantaneous per-process CPU% from cumulative CPU time, shared by all OSes.
3
+ *
4
+ * Every OS's "CPU%" column is a lifetime average (`ps %cpu`, `/proc` utime over
5
+ * elapsed) — exactly why the old sparkline was a flat line. Machine-normalised
6
+ * like Task Manager: `deltaCpuMs / (wallMs × coreCount) × 100`, so a busy single
7
+ * thread on a 20-core box reads 5 % and group roll-ups sum to roughly the
8
+ * system total.
9
+ */
10
+
11
+ export interface CpuTimeSample {
12
+ /** `${pid}:${startedAt}` — the same pid with a new start time is a new
13
+ * process and gets a fresh baseline. `${pid}:0` when the start is unknown,
14
+ * an accepted hole that mis-attributes at most one tick. */
15
+ key: string;
16
+ cpuMs: number;
17
+ }
18
+
19
+ export interface CpuDeltaState {
20
+ at: number;
21
+ byKey: Map<string, number>;
22
+ }
23
+
24
+ export function cpuSampleKey(pid: number, startedAt: number): string {
25
+ return `${pid}:${startedAt}`;
26
+ }
27
+
28
+ const round1 = (n: number): number => Math.round(n * 10) / 10;
29
+
30
+ /**
31
+ * Unknown key → 0 (a first observation is never a guess). Counter going
32
+ * backwards → 0 and the baseline is reset. Dead keys are dropped from `next`
33
+ * every tick so a long session cannot grow the map without bound.
34
+ */
35
+ export function computeCpuPercents(
36
+ prev: CpuDeltaState | null,
37
+ samples: readonly CpuTimeSample[],
38
+ now: number,
39
+ coreCount: number,
40
+ ): { percentByKey: Map<string, number>; next: CpuDeltaState } {
41
+ const percentByKey = new Map<string, number>();
42
+ const nextByKey = new Map<string, number>();
43
+ const wallMs = prev ? now - prev.at : 0;
44
+ const cores = Math.max(1, coreCount);
45
+ const usable = prev !== null && wallMs > 0;
46
+
47
+ for (const s of samples) {
48
+ nextByKey.set(s.key, s.cpuMs);
49
+ let pct = 0;
50
+ if (usable) {
51
+ const before = prev!.byKey.get(s.key);
52
+ if (before !== undefined) {
53
+ const delta = s.cpuMs - before;
54
+ if (delta >= 0) pct = round1(Math.min(100, (delta / (wallMs * cores)) * 100));
55
+ }
56
+ }
57
+ percentByKey.set(s.key, pct);
58
+ }
59
+
60
+ return { percentByKey, next: { at: now, byKey: nextByKey } };
61
+ }
@@ -0,0 +1,142 @@
1
+ /**
2
+ * App grouping: roll every process up to its nearest ancestor below an OS
3
+ * "shell/service boundary", so Chrome is one row with 40 children and a
4
+ * terminal is one row with its shells. Exe-name grouping survives only as the
5
+ * bucket for orphans — it would merge every unrelated `node` on the machine
6
+ * into one row, which is worse than Task Manager.
7
+ */
8
+ import type { MetricsPlatform, ProcessGroup, ProcessInfo } from "../../types/system-metrics.ts";
9
+
10
+ /** Names are extension-free per the contract, so one literal matches every OS. */
11
+ const WIN32_BOUNDARY_NAMES: ReadonlySet<string> = new Set([
12
+ "services", "svchost", "explorer", "wininit", "winlogon", "csrss", "userinit", "smss",
13
+ ]);
14
+ const POSIX_BOUNDARY_NAMES: ReadonlySet<string> = new Set(["launchd", "systemd", "init"]);
15
+
16
+ const round1 = (n: number): number => Math.round(n * 10) / 10;
17
+
18
+ /** The optional per-process columns, which roll up by summation. */
19
+ type OptionalMetric = "diskReadBps" | "diskWriteBps" | "gpuPct" | "gpuMemMB" | "netInBps" | "netOutBps";
20
+
21
+ /**
22
+ * Sum over the members that HAVE a value; `undefined` when none does, so a
23
+ * group on a host that cannot measure a column stays "—" instead of claiming a
24
+ * confident 0. A member without a value contributes nothing rather than
25
+ * suppressing its siblings' figures — on Linux that is the common case (an
26
+ * access-denied `/proc/<pid>/io` next to readable ones).
27
+ */
28
+ function sumOptional(procs: readonly ProcessInfo[], field: OptionalMetric): number | undefined {
29
+ let total = 0;
30
+ let measured = false;
31
+ for (const p of procs) {
32
+ const v = p[field];
33
+ if (typeof v === "number" && Number.isFinite(v)) {
34
+ total += v;
35
+ measured = true;
36
+ }
37
+ }
38
+ if (!measured) return undefined;
39
+ // A group's engine busy is still a share of one GPU, so it cannot exceed 100 %.
40
+ return round1(field === "gpuPct" ? Math.min(100, total) : total);
41
+ }
42
+
43
+ function isBoundary(p: ProcessInfo, platform: MetricsPlatform): boolean {
44
+ const name = p.name.toLowerCase();
45
+ if (platform === "win32") return p.pid === 0 || p.pid === 4 || WIN32_BOUNDARY_NAMES.has(name);
46
+ return p.pid <= 1 || POSIX_BOUNDARY_NAMES.has(name);
47
+ }
48
+
49
+ /**
50
+ * Climb `ppid` until the parent is absent, is a boundary, or started AFTER the
51
+ * child (Windows never clears a dead parent's ppid, so a recycled pid would
52
+ * otherwise adopt an unrelated subtree). Returns the chain from `p` upward.
53
+ */
54
+ function ancestorChain(p: ProcessInfo, byPid: ReadonlyMap<number, ProcessInfo>, platform: MetricsPlatform): ProcessInfo[] {
55
+ const chain = [p];
56
+ const visited = new Set<number>([p.pid]);
57
+ let cur = p;
58
+ while (true) {
59
+ const parent = byPid.get(cur.ppid);
60
+ if (!parent || visited.has(parent.pid) || isBoundary(parent, platform)) break;
61
+ if (parent.startedAt && cur.startedAt && parent.startedAt > cur.startedAt) break;
62
+ visited.add(parent.pid);
63
+ chain.push(parent);
64
+ cur = parent;
65
+ }
66
+ return chain;
67
+ }
68
+
69
+ /**
70
+ * The PPM subtree always splits out of whatever shell chain launched it: on a
71
+ * dev host that chain is explorer → WindowsTerminal → bun → server, and without
72
+ * this rule PPM would roll up under "WindowsTerminal" and hand the UI a tree-kill
73
+ * button whose blast radius includes the server. The topmost PPM root in the
74
+ * chain wins so supervisor + server + children form ONE group.
75
+ */
76
+ function resolveRoot(chain: ProcessInfo[], ppmRoots: ReadonlySet<number>): ProcessInfo {
77
+ for (let i = chain.length - 1; i >= 0; i--) {
78
+ if (ppmRoots.has(chain[i]!.pid)) return chain[i]!;
79
+ }
80
+ return chain[chain.length - 1]!;
81
+ }
82
+
83
+ /**
84
+ * @param ppmRoots PPM's own roots (server + supervisor/parent): grouping boundaries.
85
+ * @param selfPid This server's pid. Two PPM instances can share a machine (dev
86
+ * beside prod), so a PPM group is labelled by which one it is.
87
+ */
88
+ export function groupProcesses(
89
+ procs: readonly ProcessInfo[],
90
+ platform: MetricsPlatform,
91
+ ppmRoots: ReadonlySet<number> = new Set(),
92
+ selfPid: number = -1,
93
+ ): ProcessGroup[] {
94
+ const byPid = new Map<number, ProcessInfo>();
95
+ for (const p of procs) byPid.set(p.pid, p);
96
+
97
+ const members = new Map<string, { label: string; rootPid: number | null; procs: ProcessInfo[] }>();
98
+ for (const p of procs) {
99
+ let key: string;
100
+ let label: string;
101
+ let rootPid: number | null;
102
+ if (p.ppid === -1) {
103
+ key = `exe:${p.name.toLowerCase()}`;
104
+ label = p.name;
105
+ rootPid = null;
106
+ } else {
107
+ const root = resolveRoot(ancestorChain(p, byPid, platform), ppmRoots);
108
+ key = `root:${root.pid}`;
109
+ label = ppmRoots.has(root.pid) ? `PPM (pid ${root.pid})` : root.name;
110
+ rootPid = root.pid;
111
+ }
112
+ const g = members.get(key);
113
+ if (g) g.procs.push(p);
114
+ else members.set(key, { label, rootPid, procs: [p] });
115
+ }
116
+
117
+ const groups: ProcessGroup[] = [];
118
+ for (const [key, g] of members) {
119
+ if (g.rootPid !== null && ppmRoots.has(g.rootPid) && g.procs.some((p) => p.pid === selfPid)) {
120
+ g.label = "PPM (this server)";
121
+ }
122
+ g.procs.sort((a, b) => b.cpu - a.cpu || b.ramMB - a.ramMB || a.pid - b.pid);
123
+ groups.push({
124
+ key,
125
+ label: g.label,
126
+ rootPid: g.rootPid,
127
+ cpu: round1(g.procs.reduce((s, p) => s + p.cpu, 0)),
128
+ ramMB: round1(g.procs.reduce((s, p) => s + p.ramMB, 0)),
129
+ count: g.procs.length,
130
+ ppm: g.procs.some((p) => p.ppm),
131
+ pids: g.procs.map((p) => p.pid),
132
+ diskReadBps: sumOptional(g.procs, "diskReadBps"),
133
+ diskWriteBps: sumOptional(g.procs, "diskWriteBps"),
134
+ gpuPct: sumOptional(g.procs, "gpuPct"),
135
+ gpuMemMB: sumOptional(g.procs, "gpuMemMB"),
136
+ netInBps: sumOptional(g.procs, "netInBps"),
137
+ netOutBps: sumOptional(g.procs, "netOutBps"),
138
+ });
139
+ }
140
+ groups.sort((a, b) => b.cpu - a.cpu || b.ramMB - a.ramMB || a.label.localeCompare(b.label));
141
+ return groups;
142
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Per-process cumulative byte counters → bytes/second, shared by every OS.
3
+ *
4
+ * The whole-machine helper in `rate-delta.ts` cannot serve here: it works on a
5
+ * counter's OWN clock and corrects 32-bit wraps, whereas these counters are
6
+ * 64-bit per-process totals sampled on the tick's wall clock. So the identity
7
+ * rules are the same as the CPU delta's (`pid:startedAt` key, first observation
8
+ * is 0, dead keys dropped) and only the units differ.
9
+ *
10
+ * `undefined` in, `undefined` out: a field the OS refused (an access-denied
11
+ * `/proc/<pid>/io`, a Windows property that came back empty) must never become
12
+ * a confident 0.
13
+ */
14
+
15
+ export interface ProcIoCounters {
16
+ diskReadBytes?: number;
17
+ diskWriteBytes?: number;
18
+ netInBytes?: number;
19
+ netOutBytes?: number;
20
+ }
21
+
22
+ export interface ProcIoSample extends ProcIoCounters {
23
+ /** `${pid}:${startedAt}` — see `cpuSampleKey`. */
24
+ key: string;
25
+ }
26
+
27
+ export interface ProcIoRates {
28
+ diskReadBps?: number;
29
+ diskWriteBps?: number;
30
+ netInBps?: number;
31
+ netOutBps?: number;
32
+ }
33
+
34
+ export interface ProcIoDeltaState {
35
+ at: number;
36
+ byKey: Map<string, ProcIoCounters>;
37
+ }
38
+
39
+ /** Faster than any bus this code will meet; a delta implying more is a counter
40
+ * reset the OS did not flag, not a transfer. */
41
+ const MAX_PLAUSIBLE_BPS = 100 * 1024 ** 3;
42
+
43
+ export function computeProcIoRates(
44
+ prev: ProcIoDeltaState | null,
45
+ samples: readonly ProcIoSample[],
46
+ now: number,
47
+ ): { ratesByKey: Map<string, ProcIoRates>; next: ProcIoDeltaState } {
48
+ const ratesByKey = new Map<string, ProcIoRates>();
49
+ const nextByKey = new Map<string, ProcIoCounters>();
50
+ const wallSec = prev ? (now - prev.at) / 1000 : 0;
51
+ const usable = prev !== null && wallSec > 0;
52
+
53
+ for (const s of samples) {
54
+ const counters: ProcIoCounters = {
55
+ diskReadBytes: s.diskReadBytes,
56
+ diskWriteBytes: s.diskWriteBytes,
57
+ netInBytes: s.netInBytes,
58
+ netOutBytes: s.netOutBytes,
59
+ };
60
+ nextByKey.set(s.key, counters);
61
+ const before = usable ? prev!.byKey.get(s.key) : undefined;
62
+ ratesByKey.set(s.key, {
63
+ diskReadBps: bps(before?.diskReadBytes, s.diskReadBytes, wallSec),
64
+ diskWriteBps: bps(before?.diskWriteBytes, s.diskWriteBytes, wallSec),
65
+ netInBps: bps(before?.netInBytes, s.netInBytes, wallSec),
66
+ netOutBps: bps(before?.netOutBytes, s.netOutBytes, wallSec),
67
+ });
68
+ }
69
+
70
+ return { ratesByKey, next: { at: now, byKey: nextByKey } };
71
+ }
72
+
73
+ /**
74
+ * - counter not reported → `undefined` (unmeasurable, the UI shows "—")
75
+ * - no baseline yet, or the counter went backwards → 0
76
+ */
77
+ function bps(before: number | undefined, current: number | undefined, wallSec: number): number | undefined {
78
+ if (current === undefined || !Number.isFinite(current)) return undefined;
79
+ if (before === undefined || wallSec <= 0) return 0;
80
+ const delta = current - before;
81
+ if (!Number.isFinite(delta) || delta <= 0) return 0;
82
+ const rate = Math.round(delta / wallSec);
83
+ return rate > MAX_PLAUSIBLE_BPS ? 0 : rate;
84
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Per-process disk bytes on Linux from `/proc/<pid>/io` — no subprocess.
3
+ *
4
+ * `read_bytes`/`write_bytes` are the counters that actually reached the block
5
+ * layer, which is what a Task-Manager "Disk" column means; `rchar`/`wchar`
6
+ * would also count page-cache hits and make every process look busy.
7
+ *
8
+ * The file is PTRACE_MODE_READ-protected, so unprivileged PPM sees it only for
9
+ * its own uid: an EACCES is the NORMAL case for other users' processes and must
10
+ * leave those rows unmeasured (`undefined`) rather than 0 or an exception.
11
+ */
12
+ import { readFileSync } from "node:fs";
13
+
14
+ export interface ProcIoBytes {
15
+ readBytes: number;
16
+ writeBytes: number;
17
+ }
18
+
19
+ const FIELD = /^(read_bytes|write_bytes):\s+(\d+)$/;
20
+
21
+ /** Null when neither counter is present (a kernel thread reports zeros only in
22
+ * some kernels, and a truncated read must not be guessed at). */
23
+ export function parseProcIo(text: string): ProcIoBytes | null {
24
+ let read: number | undefined;
25
+ let write: number | undefined;
26
+ for (const line of text.split("\n")) {
27
+ const m = FIELD.exec(line.trim());
28
+ if (!m) continue;
29
+ const value = Number(m[2]);
30
+ if (!Number.isFinite(value)) continue;
31
+ if (m[1] === "read_bytes") read = value;
32
+ else write = value;
33
+ }
34
+ if (read === undefined && write === undefined) return null;
35
+ return { readBytes: read ?? 0, writeBytes: write ?? 0 };
36
+ }
37
+
38
+ /** Null on EACCES (another user's process), ENOENT (exited between readdir and
39
+ * read) or an unparseable file. Never throws. */
40
+ export function readProcIoBytes(pid: number): ProcIoBytes | null {
41
+ try {
42
+ return parseProcIo(readFileSync(`/proc/${pid}/io`, "utf-8"));
43
+ } catch {
44
+ return null;
45
+ }
46
+ }