@hienlh/ppm 0.18.8 → 0.18.10

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 (513) hide show
  1. package/.spike/group-protected-probe.ts +21 -0
  2. package/.spike/s.err +63 -0
  3. package/.spike/tunnel.err +22 -0
  4. package/.spike/w.err +28 -0
  5. package/CHANGELOG.md +21 -0
  6. package/CLAUDE.md +1 -0
  7. package/assets/skills/ppm/SKILL.md +1 -1
  8. package/assets/skills/ppm/references/cli-reference.md +4 -4
  9. package/assets/skills/ppm/references/http-api.md +4 -3
  10. package/dist/web/assets/{ai-resource-editor-BydGrxjb.js → ai-resource-editor-mdDKG-rw.js} +1 -1
  11. package/dist/web/assets/{angular-html-jfMqUuRd.js → angular-html-Ctz0zN01.js} +1 -1
  12. package/dist/web/assets/{angular-ts-wytn9PMm.js → angular-ts-QXHpgB1C.js} +1 -1
  13. package/dist/web/assets/{api-settings-DlcoR5QT.js → api-settings-nblja3Rk.js} +1 -1
  14. package/dist/web/assets/{apl-i-ahKx6O.js → apl-b9KVk-O4.js} +1 -1
  15. package/dist/web/assets/architecture-PBZL5I3N-C7ra20CE.js +1 -0
  16. package/dist/web/assets/{astro-DVBCJfG6.js → astro-BlFEeGYr.js} +1 -1
  17. package/dist/web/assets/{audio-preview-DzBGq9Lk.js → audio-preview-CZLmhf__.js} +1 -1
  18. package/dist/web/assets/{blade-BHlL8SqU.js → blade-CGkj2MUI.js} +1 -1
  19. package/dist/web/assets/{bsl-D-UOfR1F.js → bsl-CVsbb6ap.js} +1 -1
  20. package/dist/web/assets/button-BA_fJOtX.js +1 -0
  21. package/dist/web/assets/{cairo-Bn6rucli.js → cairo-BbIHl2iE.js} +1 -1
  22. package/dist/web/assets/chat-tab-C060A94y.js +15 -0
  23. package/dist/web/assets/circle-hjUGru6R.js +1 -0
  24. package/dist/web/assets/circle-question-mark-CzR7YRc-.js +1 -0
  25. package/dist/web/assets/{cobol-Byn9FYKu.js → cobol-BWSGjmWb.js} +1 -1
  26. package/dist/web/assets/code-editor-WELegzdp.js +10 -0
  27. package/dist/web/assets/{coffee-DjBl4gm-.js → coffee-CWGNOxds.js} +1 -1
  28. package/dist/web/assets/{conflict-editor-CRConSGG.js → conflict-editor-fRTU3f1o.js} +3 -3
  29. package/dist/web/assets/{context-menu-DkQdt6YA.js → context-menu-Cq0u3SK9.js} +1 -1
  30. package/dist/web/assets/{cpp-CKzic-3E.js → cpp-DHGV24J2.js} +1 -1
  31. package/dist/web/assets/{crystal-Bkg-Ly_g.js → crystal-Vlwf2UMP.js} +1 -1
  32. package/dist/web/assets/{csv-preview-BtCGfmrq.js → csv-preview-D1d0cxOJ.js} +1 -1
  33. package/dist/web/assets/{data-grid-overlay-editor-B1mTl3KS.js → data-grid-overlay-editor-D9il5DZS.js} +1 -1
  34. package/dist/web/assets/{database-viewer-2M5sKRqb.js → database-viewer-DevnWTV4.js} +1 -1
  35. package/dist/web/assets/{diff-viewer-BMr7vOvZ.js → diff-viewer-DGxVg1pD.js} +1 -1
  36. package/dist/web/assets/{docx-preview-BpG2kr_-.js → docx-preview-Cx-zLwAw.js} +1 -1
  37. package/dist/web/assets/{edge-DVbZnd3Y.js → edge-Bhqk64zS.js} +1 -1
  38. package/dist/web/assets/{edit-diff-preview-BivQwZMD.js → edit-diff-preview-gq6ALf2B.js} +1 -1
  39. package/dist/web/assets/{elixir-Dwi8Wu7W.js → elixir-D466WCFm.js} +1 -1
  40. package/dist/web/assets/{elm-DtIv-HXJ.js → elm-Bfs2qNPR.js} +1 -1
  41. package/dist/web/assets/{erb-D3HEDz1x.js → erb-WI7jUaB6.js} +1 -1
  42. package/dist/web/assets/{erlang-2MjTCzGz.js → erlang-BCBe8nCc.js} +1 -1
  43. package/dist/web/assets/{esm-CZ8B8Ba2.js → esm-CZs9WVDO.js} +1 -1
  44. package/dist/web/assets/{explorer-body-DXufyj-9.js → explorer-body-j_4hVc34.js} +2 -2
  45. package/dist/web/assets/{explorer-window-content-B3krk4G1.js → explorer-window-content-DdrGwk3w.js} +1 -1
  46. package/dist/web/assets/{extension-webview-12M45CGq.js → extension-webview-BH_mWYMe.js} +1 -1
  47. package/dist/web/assets/format-bytes-BE_W3UBg.js +1 -0
  48. package/dist/web/assets/{fortran-fixed-form-BLyAtyPM.js → fortran-fixed-form-CXLIv8Ox.js} +1 -1
  49. package/dist/web/assets/{fsharp-Bxbn_gbr.js → fsharp-CZsYmiw9.js} +1 -1
  50. package/dist/web/assets/{gdresource-sFMY4D2Q.js → gdresource-BGRvoWfC.js} +1 -1
  51. package/dist/web/assets/{git-commit-BzB9Lio5.js → git-commit-DH6mY3Km.js} +1 -1
  52. package/dist/web/assets/{git-log-panel-Cp4k3tX_.js → git-log-panel-CfpXRJcP.js} +1 -1
  53. package/dist/web/assets/{git-rebase-CKSVd848.js → git-rebase-C5Gql6Ma.js} +1 -1
  54. package/dist/web/assets/gitGraph-HDMCJU4V-D4hYLNJU.js +1 -0
  55. package/dist/web/assets/{glide-data-grid-B0BB0VDl.js → glide-data-grid-n4ox_uev.js} +7 -7
  56. package/dist/web/assets/{glimmer-js-BY8aExAJ.js → glimmer-js-1-6JMJlj.js} +1 -1
  57. package/dist/web/assets/{glimmer-ts-Bak54dBX.js → glimmer-ts-C_Njj0nK.js} +1 -1
  58. package/dist/web/assets/{glsl-nR2eaJQe.js → glsl-DbkxE1TN.js} +1 -1
  59. package/dist/web/assets/{graphql-CGPPFAU6.js → graphql-BK75fiXl.js} +1 -1
  60. package/dist/web/assets/group-chat-tab-dYuuknLN.js +1 -0
  61. package/dist/web/assets/{hack-CXIMX-Ol.js → hack-DG151vit.js} +1 -1
  62. package/dist/web/assets/{haml-tPY-9Pfm.js → haml-DKeIPQWM.js} +1 -1
  63. package/dist/web/assets/{handlebars-BuW1LT7T.js → handlebars-398uCI13.js} +1 -1
  64. package/dist/web/assets/{html-bgVcwZ-t.js → html-NLWdst5q.js} +1 -1
  65. package/dist/web/assets/{html-derivative-D6-IxTgn.js → html-derivative-CJf_Le2z.js} +1 -1
  66. package/dist/web/assets/{http-CJ1zyB-h.js → http-G1K2FozA.js} +1 -1
  67. package/dist/web/assets/{hurl-CmoT7l3T.js → hurl-WDC6sSBz.js} +1 -1
  68. package/dist/web/assets/{hxml-CztOsL8o.js → hxml-Dc3jBXuf.js} +1 -1
  69. package/dist/web/assets/{image-preview-3HfuxA0N.js → image-preview-Ss38ex8g.js} +1 -1
  70. package/dist/web/assets/index-BiTiXgBZ.css +2 -0
  71. package/dist/web/assets/index-Ch8l9de-.js +52 -0
  72. package/dist/web/assets/info-3K5VOQVL-lRlrTlkb.js +1 -0
  73. package/dist/web/assets/{jinja-B1pq3jJq.js → jinja-CWsQj2y0.js} +1 -1
  74. package/dist/web/assets/{jison-D8B5pCwA.js → jison-CciJg2NW.js} +1 -1
  75. package/dist/web/assets/{julia-D0K3bwpU.js → julia-IOQNJAB7.js} +1 -1
  76. package/dist/web/assets/{just-B9Jlddu-.js → just-BGdHchwS.js} +1 -1
  77. package/dist/web/assets/{keybindings-store-oMJmtpH4.js → keybindings-store-CDfTjwZX.js} +1 -1
  78. package/dist/web/assets/{latex-BPJSSE6j.js → latex-D6TOl-L2.js} +1 -1
  79. package/dist/web/assets/{liquid-lv10fo4U.js → liquid-CVSvu_Wn.js} +1 -1
  80. package/dist/web/assets/{lua-PNuaIBEF.js → lua-CcKiU6HW.js} +1 -1
  81. package/dist/web/assets/{markdown-renderer-DPcoPjmO.js → markdown-renderer-B317vEys.js} +3 -3
  82. package/dist/web/assets/markdown-renderer-CpRlpLHw.js +1 -0
  83. package/dist/web/assets/{marko-Du3frD6X.js → marko--UOicMGo.js} +1 -1
  84. package/dist/web/assets/{mdc-BeDVcFRl.js → mdc-D690aU2C.js} +1 -1
  85. package/dist/web/assets/{mobile-explorer-sheet-CEVcU964.js → mobile-explorer-sheet-D1Bv9UCT.js} +1 -1
  86. package/dist/web/assets/{nextflow-DkcXP71s.js → nextflow-DR8PhpF8.js} +1 -1
  87. package/dist/web/assets/{nginx-C5n8N_bt.js → nginx-Qb9pUk1g.js} +1 -1
  88. package/dist/web/assets/{nim-CIhyfs-A.js → nim-DLa8R3NS.js} +1 -1
  89. package/dist/web/assets/{notification-store-B8AqxwRT.js → notification-store-KwTAZT8b.js} +1 -1
  90. package/dist/web/assets/{number-overlay-editor-NgOsWJ7x.js → number-overlay-editor-D9SkFg1Y.js} +1 -1
  91. package/dist/web/assets/overview-panel-BxDohIEa.js +1 -0
  92. package/dist/web/assets/packet-RMMSAZCW-BIhk1mvp.js +1 -0
  93. package/dist/web/assets/{pdf-preview-BslNoDFw.js → pdf-preview-dwRe54ht.js} +1 -1
  94. package/dist/web/assets/{perl-Cf31sZYE.js → perl-AMNGIneF.js} +1 -1
  95. package/dist/web/assets/{php-Dzl_MDIW.js → php-CDsOOxXn.js} +1 -1
  96. package/dist/web/assets/pie-UPGHQEXC-SLS6i76l.js +1 -0
  97. package/dist/web/assets/{postgres-viewer-BtSXQ3S4.js → postgres-viewer-BWZLW7kI.js} +3 -3
  98. package/dist/web/assets/process-table-CI-fnVsy.js +1 -0
  99. package/dist/web/assets/{pug-CxSYHrB3.js → pug-C2kdkhQ6.js} +1 -1
  100. package/dist/web/assets/{qml-DlEjGhwN.js → qml-DRDkUp75.js} +1 -1
  101. package/dist/web/assets/radar-KQ55EAFF-JJ6O1Er_.js +1 -0
  102. package/dist/web/assets/{razor-KVt5uW14.js → razor-wY_6wUeC.js} +1 -1
  103. package/dist/web/assets/resolve-theme-B9ABAH_3.js +1 -0
  104. package/dist/web/assets/{rst-D5BwNTnw.js → rst-BRpofyNs.js} +1 -1
  105. package/dist/web/assets/{ruby-D5fejQwd.js → ruby-ieATBhWm.js} +1 -1
  106. package/dist/web/assets/{sas-Bj7B1CB2.js → sas-CoOOEbOO.js} +1 -1
  107. package/dist/web/assets/{scss-BB0CUoCL.js → scss-_nWV0bsb.js} +1 -1
  108. package/dist/web/assets/{settings-store-C9YT1Hir.js → settings-store-C20lqh0G.js} +2 -2
  109. package/dist/web/assets/settings-tab-mPxrKkfm.js +1 -0
  110. package/dist/web/assets/{shaderlab-BdjEZUMc.js → shaderlab-XkqfIfO8.js} +1 -1
  111. package/dist/web/assets/{shellsession-Bp1OA1rR.js → shellsession-BKBIqTlM.js} +1 -1
  112. package/dist/web/assets/{soy-DlYz3wsC.js → soy-oVDnPzzh.js} +1 -1
  113. package/dist/web/assets/{sparql-CdfII5Jd.js → sparql-N2VclEsF.js} +1 -1
  114. package/dist/web/assets/{sql-query-editor-CkvpmXyA.js → sql-query-editor-BwPjEaP9.js} +1 -1
  115. package/dist/web/assets/{sqlite-viewer-CJbP6ruh.js → sqlite-viewer-Cs-_D942.js} +1 -1
  116. package/dist/web/assets/{stata-BvUA6GUW.js → stata-BuuClVDg.js} +1 -1
  117. package/dist/web/assets/{surrealql--DLNbTyI.js → surrealql-DE5_63MS.js} +1 -1
  118. package/dist/web/assets/{svelte-CBfSsG4n.js → svelte--YWjlOrK.js} +1 -1
  119. package/dist/web/assets/system-monitor-body-CV7-0hZG.js +2 -0
  120. package/dist/web/assets/system-monitor-tab-Ce-8Axhh.js +1 -0
  121. package/dist/web/assets/system-monitor-window-content-CetwYOQy.js +1 -0
  122. package/dist/web/assets/team-member-sheet-CjgaQjsZ.js +2 -0
  123. package/dist/web/assets/{team-member-window-content-Cxh-HF2V.js → team-member-window-content-DNJiYWS7.js} +1 -1
  124. package/dist/web/assets/{templ-Dv8zpKZW.js → templ-MlpvJx4a.js} +1 -1
  125. package/dist/web/assets/{terminal-tab-gQCs_fyx.js → terminal-tab-DF7521sT.js} +3 -3
  126. package/dist/web/assets/{tex-CsrOiqh1.js → tex-0loAoXJG.js} +1 -1
  127. package/dist/web/assets/{tool-cards-BG2fz83z.js → tool-cards-DCAXGDJI.js} +5 -5
  128. package/dist/web/assets/treemap-KZPCXAKY-Be3KNmns.js +1 -0
  129. package/dist/web/assets/{ts-tags-3T98k4EJ.js → ts-tags-pt-Ug0hK.js} +1 -1
  130. package/dist/web/assets/{twig-u6QZ45FH.js → twig-DOePpLOL.js} +1 -1
  131. package/dist/web/assets/{use-monaco-theme-DaqI7O-a.js → use-monaco-theme-DSCdlrjO.js} +1 -1
  132. package/dist/web/assets/{use-open-team-member-DKpstvLS.js → use-open-team-member-H4k74HnV.js} +1 -1
  133. package/dist/web/assets/{use-websocket-KVhDtbwK.js → use-websocket-iJfc7EbK.js} +1 -1
  134. package/dist/web/assets/{vendor-mermaid-Bg4vE8QA.js → vendor-mermaid-DrwG0NYt.js} +1 -1
  135. package/dist/web/assets/{video-preview-CVEUDZBj.js → video-preview-B0ZWpX0F.js} +1 -1
  136. package/dist/web/assets/{vue-CxIsxtwn.js → vue-D6f-rprj.js} +1 -1
  137. package/dist/web/assets/{vue-html-BGL5qnuH.js → vue-html-DEYRkS1V.js} +1 -1
  138. package/dist/web/assets/{vue-vine-DHPh_gMr.js → vue-vine-CxSG2ojf.js} +1 -1
  139. package/dist/web/assets/{xml-C-vM2m7J.js → xml-DhrxbATj.js} +1 -1
  140. package/dist/web/assets/{xsl-DvTXNwuO.js → xsl-CU0ZndUO.js} +1 -1
  141. package/dist/web/index.html +18 -17
  142. package/dist/web/sw.js +1 -1
  143. package/docs/system-architecture.md +2 -2
  144. package/package.json +1 -1
  145. package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
  146. package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
  147. package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
  148. package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
  149. package/src/server/index.ts +2 -8
  150. package/src/server/routes/resources.ts +119 -73
  151. package/src/services/autostart-generator.ts +79 -7
  152. package/src/services/autostart-register.ts +15 -2
  153. package/src/services/edge-forwarder.ts +191 -191
  154. package/src/services/proc-table-linux.ts +4 -0
  155. package/src/services/redact-secrets.ts +33 -0
  156. package/src/services/system-metrics/cpu-memory-collector.ts +101 -0
  157. package/src/services/system-metrics/disk-net-collector-darwin.ts +75 -0
  158. package/src/services/system-metrics/disk-net-collector-linux.ts +88 -0
  159. package/src/services/system-metrics/disk-net-collector-windows.ts +57 -0
  160. package/src/services/system-metrics/gpu-collector-nvidia.ts +78 -0
  161. package/src/services/system-metrics/gpu-process-memory-nvidia.ts +66 -0
  162. package/src/services/system-metrics/gpu-process-usage-windows.ts +138 -0
  163. package/src/services/system-metrics/kill-executor.ts +85 -0
  164. package/src/services/system-metrics/kill-guard.ts +124 -0
  165. package/src/services/system-metrics/kill-identity-resolver.ts +72 -0
  166. package/src/services/system-metrics/kill-request-handler.ts +79 -0
  167. package/src/services/system-metrics/metrics-collector-lock.ts +36 -0
  168. package/src/services/system-metrics/metrics-poll-scheduler.ts +83 -0
  169. package/src/services/system-metrics/metrics-subscriber-registry.ts +85 -0
  170. package/src/services/system-metrics/powershell-session-bootstrap.ts +48 -0
  171. package/src/services/system-metrics/powershell-session.ts +182 -0
  172. package/src/services/system-metrics/ppm-process-ownership.ts +34 -0
  173. package/src/services/system-metrics/ppm-protected-pids.ts +84 -0
  174. package/src/services/system-metrics/process-collector-darwin.ts +141 -0
  175. package/src/services/system-metrics/process-collector-linux.ts +85 -0
  176. package/src/services/system-metrics/process-collector-types.ts +80 -0
  177. package/src/services/system-metrics/process-collector-windows-parse.ts +153 -0
  178. package/src/services/system-metrics/process-collector-windows.ts +136 -0
  179. package/src/services/system-metrics/process-cpu-delta.ts +61 -0
  180. package/src/services/system-metrics/process-grouping.ts +142 -0
  181. package/src/services/system-metrics/process-io-delta.ts +84 -0
  182. package/src/services/system-metrics/process-io-linux.ts +46 -0
  183. package/src/services/system-metrics/process-net-collector-darwin.ts +103 -0
  184. package/src/services/system-metrics/process-rows-builder.ts +111 -0
  185. package/src/services/system-metrics/rate-delta.ts +47 -0
  186. package/src/services/system-metrics/system-metrics-platform.ts +51 -0
  187. package/src/services/system-metrics/system-metrics-tick.ts +178 -0
  188. package/src/services/system-metrics/system-metrics.service.ts +212 -0
  189. package/src/services/windows-process-tree.ts +351 -351
  190. package/src/types/system-metrics.ts +199 -0
  191. package/src/web/components/floating-window/window-content-registry.ts +2 -0
  192. package/src/web/components/floating-window/window-persistence.ts +1 -1
  193. package/src/web/components/floating-window/window-store-types.ts +1 -1
  194. package/src/web/components/system/build-kill-request.ts +36 -0
  195. package/src/web/components/system/chart-scale.ts +28 -0
  196. package/src/web/components/system/cpu-core-bars.tsx +33 -0
  197. package/src/web/components/system/kill-confirm-dialog.tsx +105 -0
  198. package/src/web/components/system/metric-chart-canvas.tsx +107 -0
  199. package/src/web/components/system/overview-cards/cpu-card.tsx +39 -0
  200. package/src/web/components/system/overview-cards/disk-card.tsx +41 -0
  201. package/src/web/components/system/overview-cards/gpu-card.tsx +33 -0
  202. package/src/web/components/system/overview-cards/mem-card.tsx +32 -0
  203. package/src/web/components/system/overview-cards/net-card.tsx +41 -0
  204. package/src/web/components/system/overview-panel.tsx +97 -0
  205. package/src/web/components/system/process-columns-grid.ts +103 -0
  206. package/src/web/components/system/process-group-row.tsx +94 -0
  207. package/src/web/components/system/process-row-format.ts +56 -0
  208. package/src/web/components/system/process-row.tsx +81 -0
  209. package/src/web/components/system/process-table-model.ts +109 -0
  210. package/src/web/components/system/process-table-sort.ts +90 -0
  211. package/src/web/components/system/process-table-toolbar.tsx +159 -0
  212. package/src/web/components/system/process-table-totals.ts +49 -0
  213. package/src/web/components/system/process-table.tsx +146 -0
  214. package/src/web/components/system/resolve-open-system-monitor-action.ts +29 -0
  215. package/src/web/components/system/resource-status-bar.tsx +17 -16
  216. package/src/web/components/system/sortable-header.tsx +90 -0
  217. package/src/web/components/system/system-monitor-body.tsx +146 -0
  218. package/src/web/components/system/system-monitor-tab.tsx +2 -185
  219. package/src/web/components/system/system-monitor-window-content.tsx +18 -0
  220. package/src/web/components/system/use-column-widths.ts +91 -0
  221. package/src/web/components/system/use-open-system-monitor.ts +34 -0
  222. package/src/web/components/system/use-process-kill.ts +100 -0
  223. package/src/web/hooks/resource-monitor-lease.ts +55 -0
  224. package/src/web/hooks/use-element-width.ts +27 -0
  225. package/src/web/hooks/use-resource-monitor.ts +113 -35
  226. package/src/web/lib/format-bytes.ts +16 -0
  227. package/src/web/styles/globals.css +5 -3
  228. package/src/web/theme/builtin/aurora.ts +8 -5
  229. package/dist/web/assets/architecture-PBZL5I3N-Bs7wzj-W.js +0 -1
  230. package/dist/web/assets/arrow-right-DubGFkN8.js +0 -1
  231. package/dist/web/assets/button-B4MWPjWj.js +0 -1
  232. package/dist/web/assets/chat-tab-pBGQ9SCY.js +0 -15
  233. package/dist/web/assets/circle-question-mark-CENpx4oA.js +0 -1
  234. package/dist/web/assets/code-editor-XviNXdzi.js +0 -10
  235. package/dist/web/assets/gitGraph-HDMCJU4V-D7i54kbM.js +0 -1
  236. package/dist/web/assets/group-chat-tab-CcG_NXIS.js +0 -1
  237. package/dist/web/assets/index-BAVBuKmT.js +0 -52
  238. package/dist/web/assets/index-oxsyfDa0.css +0 -2
  239. package/dist/web/assets/info-3K5VOQVL-BV41AzR9.js +0 -1
  240. package/dist/web/assets/markdown-renderer-Dg5HE9Zq.js +0 -1
  241. package/dist/web/assets/packet-RMMSAZCW-CaJoP44m.js +0 -1
  242. package/dist/web/assets/pie-UPGHQEXC-DSGZmNw2.js +0 -1
  243. package/dist/web/assets/radar-KQ55EAFF-Be4VUTs0.js +0 -1
  244. package/dist/web/assets/resolve-theme-CJvkL8hU.js +0 -1
  245. package/dist/web/assets/settings-tab-COSUzGl8.js +0 -1
  246. package/dist/web/assets/system-monitor-tab-DThAFSd_.js +0 -1
  247. package/dist/web/assets/team-member-sheet-M83B4znI.js +0 -2
  248. package/dist/web/assets/treemap-KZPCXAKY-Cu2zgbxU.js +0 -1
  249. package/src/services/resource-monitor-utils.ts +0 -141
  250. package/src/services/resource-monitor.service.ts +0 -147
  251. package/src/web/components/system/sparkline-canvas.tsx +0 -64
  252. package/src/web/components/system/system-monitor-group-row.tsx +0 -153
  253. /package/dist/web/assets/{abap-C1K0-wzc.js → abap-MRbmsXOs.js} +0 -0
  254. /package/dist/web/assets/{actionscript-3-CJhQVjLA.js → actionscript-3-BDDHKqa4.js} +0 -0
  255. /package/dist/web/assets/{ada-Bt8r9fME.js → ada-DpuV9KwV.js} +0 -0
  256. /package/dist/web/assets/{andromeeda-DF1I8qi3.js → andromeeda-D6qUCKJo.js} +0 -0
  257. /package/dist/web/assets/{apache-CnlleE6P.js → apache-CX1NU_Tl.js} +0 -0
  258. /package/dist/web/assets/{apex-j0C6Xmk6.js → apex-B4-aoQ3K.js} +0 -0
  259. /package/dist/web/assets/{api-settings-DfNRPr1q.js → api-settings-kQHV6pYZ.js} +0 -0
  260. /package/dist/web/assets/{api-themes-8WTH6KpV.js → api-themes-CrK0tkW_.js} +0 -0
  261. /package/dist/web/assets/{applescript-DO7AnO8U.js → applescript-Dm9NI6KR.js} +0 -0
  262. /package/dist/web/assets/{apply-theme-CNj1iA-v.js → apply-theme-BH_d4amk.js} +0 -0
  263. /package/dist/web/assets/{ara-i83AydZj.js → ara-BGN8GAYn.js} +0 -0
  264. /package/dist/web/assets/{asciidoc-DbBA6-sF.js → asciidoc-s_yVuR3t.js} +0 -0
  265. /package/dist/web/assets/{asm-B5S47Rgr.js → asm-BzQdSvTe.js} +0 -0
  266. /package/dist/web/assets/{aurora-x-De_IaSKw.js → aurora-x-BJTLETG_.js} +0 -0
  267. /package/dist/web/assets/{awk-CfyLHXqS.js → awk-BQEGWxvX.js} +0 -0
  268. /package/dist/web/assets/{ayu-dark-DTLdZ1Si.js → ayu-dark-CpTORmLc.js} +0 -0
  269. /package/dist/web/assets/{ayu-light-DTOfkzhu.js → ayu-light-D8PVj-e6.js} +0 -0
  270. /package/dist/web/assets/{ayu-mirage-DsAECCMv.js → ayu-mirage-DyElQHtm.js} +0 -0
  271. /package/dist/web/assets/{ballerina-CumGp9A7.js → ballerina-C82NkRtj.js} +0 -0
  272. /package/dist/web/assets/{bat-Ca2SBbYN.js → bat-0X7DtGI-.js} +0 -0
  273. /package/dist/web/assets/{beancount-CqyXBwwF.js → beancount-Xgvy6YRl.js} +0 -0
  274. /package/dist/web/assets/{berry-yl-kJr_H.js → berry-CCT2pZcQ.js} +0 -0
  275. /package/dist/web/assets/{bibtex-DoFFszjV.js → bibtex-CpXgZ9M_.js} +0 -0
  276. /package/dist/web/assets/{bicep-CWPi4nfK.js → bicep-fkeSA62l.js} +0 -0
  277. /package/dist/web/assets/{bird2-DXew-ut0.js → bird2-Co7SeAI8.js} +0 -0
  278. /package/dist/web/assets/{c-clbySDvd.js → c-BpmrTvJh.js} +0 -0
  279. /package/dist/web/assets/{c3-B65jvSM1.js → c3-BZ_Z0RrR.js} +0 -0
  280. /package/dist/web/assets/{cadence-Cm8tQTHN.js → cadence-B0GBC8OF.js} +0 -0
  281. /package/dist/web/assets/{can-open-in-ppm-DXGOSUQc.js → can-open-in-ppm-omBzUBBq.js} +0 -0
  282. /package/dist/web/assets/{catppuccin-frappe-DLeGslh_.js → catppuccin-frappe-DIt_xR7m.js} +0 -0
  283. /package/dist/web/assets/{catppuccin-latte-CR5GeHws.js → catppuccin-latte-Dw40AcqA.js} +0 -0
  284. /package/dist/web/assets/{catppuccin-macchiato-p-XgjxhP.js → catppuccin-macchiato-BJ7DfVEF.js} +0 -0
  285. /package/dist/web/assets/{catppuccin-mocha-B8QOAZLl.js → catppuccin-mocha-NI2lfXzU.js} +0 -0
  286. /package/dist/web/assets/{clarity-DPulbvKH.js → clarity-F39L0xMJ.js} +0 -0
  287. /package/dist/web/assets/{clock-D493FU_D.js → clock-CvhF4DJP.js} +0 -0
  288. /package/dist/web/assets/{clojure-DFuWS20u.js → clojure-DloMkd8K.js} +0 -0
  289. /package/dist/web/assets/{cmake-DejCqcu4.js → cmake-CwerJun_.js} +0 -0
  290. /package/dist/web/assets/{code-CLF5x7KK.js → code-DDPoqVri.js} +0 -0
  291. /package/dist/web/assets/{codeowners-BwAyqWIH.js → codeowners-CQyVz4Qf.js} +0 -0
  292. /package/dist/web/assets/{codeql-DgSwFjqI.js → codeql-Bb229zuY.js} +0 -0
  293. /package/dist/web/assets/{common-lisp-CxIVJCtf.js → common-lisp-KMlIwq5I.js} +0 -0
  294. /package/dist/web/assets/{copy-BApI9v7Z.js → copy-DKn11Pye.js} +0 -0
  295. /package/dist/web/assets/{coq-DLSjSnmf.js → coq-DHX_3IIo.js} +0 -0
  296. /package/dist/web/assets/{csharp-C1HHzXBp.js → csharp-CEmCZv9Q.js} +0 -0
  297. /package/dist/web/assets/{css-VXsMY--y.js → css-CqZqBD05.js} +0 -0
  298. /package/dist/web/assets/{csv-BEbcJdHz.js → csv-l1g_V5MV.js} +0 -0
  299. /package/dist/web/assets/{csv-parser-BRtnJCfv.js → csv-parser-CnS0wqr6.js} +0 -0
  300. /package/dist/web/assets/{cue-BkDnFqUD.js → cue-BrxRmilg.js} +0 -0
  301. /package/dist/web/assets/{cypher-1cMqojSQ.js → cypher-rZkKwqZc.js} +0 -0
  302. /package/dist/web/assets/{d-BnYjRXtH.js → d-BALR-QuP.js} +0 -0
  303. /package/dist/web/assets/{dark-plus-XfbaH7kZ.js → dark-plus-Cj7rVwh-.js} +0 -0
  304. /package/dist/web/assets/{dart-Ca7s-8hK.js → dart-CWQcdkXk.js} +0 -0
  305. /package/dist/web/assets/{data-grid-types-BXwlFMzs.js → data-grid-types-CYvF-xK5.js} +0 -0
  306. /package/dist/web/assets/{database-B9okYLx6.js → database-BH0urvbs.js} +0 -0
  307. /package/dist/web/assets/{dax-CmuOw-mY.js → dax-BNHD-QBA.js} +0 -0
  308. /package/dist/web/assets/{desktop-C2gJ6Ovb.js → desktop-CN0IXPrP.js} +0 -0
  309. /package/dist/web/assets/{diff-BCEo1Ej7.js → diff-BtOXapES.js} +0 -0
  310. /package/dist/web/assets/{dist-CUPbqNnL.js → dist-DB1Oaqcc.js} +0 -0
  311. /package/dist/web/assets/{dist-DOlBnxFX.js → dist-Di6G_5jU.js} +0 -0
  312. /package/dist/web/assets/{docker-DN2jlyAh.js → docker-DNsAo_qO.js} +0 -0
  313. /package/dist/web/assets/{dotenv-NExMY2kS.js → dotenv-D6Pl6aOU.js} +0 -0
  314. /package/dist/web/assets/{download-D9UYwY0-.js → download-zCATy4x4.js} +0 -0
  315. /package/dist/web/assets/{dracula-B9lbE01y.js → dracula-C3m-w12D.js} +0 -0
  316. /package/dist/web/assets/{dracula-soft-CMBBfKF_.js → dracula-soft-BYqvXm6Z.js} +0 -0
  317. /package/dist/web/assets/{dream-maker-DEyDwFsd.js → dream-maker-DZAPbPTi.js} +0 -0
  318. /package/dist/web/assets/{emacs-lisp-D_qP2zS6.js → emacs-lisp-Ao5SW8ay.js} +0 -0
  319. /package/dist/web/assets/{everforest-dark-DbHa2U-p.js → everforest-dark-uC8QYotQ.js} +0 -0
  320. /package/dist/web/assets/{everforest-light-BISkJchP.js → everforest-light-CTgsVNMr.js} +0 -0
  321. /package/dist/web/assets/{fennel-6B22SfJR.js → fennel-WuBw6IR1.js} +0 -0
  322. /package/dist/web/assets/{file-exclamation-point-a8f3_w7a.js → file-exclamation-point-COAwgNGw.js} +0 -0
  323. /package/dist/web/assets/{fish-CubIIvJD.js → fish-Byy9dusu.js} +0 -0
  324. /package/dist/web/assets/{fluent-DF55zQ09.js → fluent-CDxb_sgw.js} +0 -0
  325. /package/dist/web/assets/{fortran-free-form-DvOu8jAt.js → fortran-free-form-DKWSTamT.js} +0 -0
  326. /package/dist/web/assets/{gdscript-DCPxdLpq.js → gdscript-prYHMgtD.js} +0 -0
  327. /package/dist/web/assets/{gdshader-CTZ381FO.js → gdshader-D-RM-SQk.js} +0 -0
  328. /package/dist/web/assets/{genie-C_QDtvgU.js → genie-CowkJhej.js} +0 -0
  329. /package/dist/web/assets/{gherkin-BcvK42tF.js → gherkin-CLFpoVYJ.js} +0 -0
  330. /package/dist/web/assets/{github-dark-default-CKGVrl3Z.js → github-dark-default-BK_1Qgb8.js} +0 -0
  331. /package/dist/web/assets/{github-dark-dimmed-C3dQZ_LC.js → github-dark-dimmed-Cv9lj6f-.js} +0 -0
  332. /package/dist/web/assets/{github-dark-high-contrast-DW78QukY.js → github-dark-high-contrast-CW5ZgIDh.js} +0 -0
  333. /package/dist/web/assets/{github-dark-C9afs_4w.js → github-dark-nW2F-RLd.js} +0 -0
  334. /package/dist/web/assets/{github-light-BnP2dznS.js → github-light-D4PqBHGZ.js} +0 -0
  335. /package/dist/web/assets/{github-light-default-C2fPZzPG.js → github-light-default-B-cHtJJV.js} +0 -0
  336. /package/dist/web/assets/{github-light-high-contrast-BzIuUFR2.js → github-light-high-contrast-Dt0HJq50.js} +0 -0
  337. /package/dist/web/assets/{gleam-BpeKwEIO.js → gleam-DwSyXJWP.js} +0 -0
  338. /package/dist/web/assets/{gn-nUb_Mit0.js → gn-Cv5WEzHc.js} +0 -0
  339. /package/dist/web/assets/{gnuplot-D7I0v20p.js → gnuplot-D7bRdY_M.js} +0 -0
  340. /package/dist/web/assets/{go-D7Qqska7.js → go-DiRVJ22U.js} +0 -0
  341. /package/dist/web/assets/{groovy-DS-pne5-.js → groovy-BHAgLTeO.js} +0 -0
  342. /package/dist/web/assets/{gruvbox-dark-hard-C0W01fsq.js → gruvbox-dark-hard-C8QZ3gzY.js} +0 -0
  343. /package/dist/web/assets/{gruvbox-dark-medium-Bqo6fQbg.js → gruvbox-dark-medium-Dp1eeid2.js} +0 -0
  344. /package/dist/web/assets/{gruvbox-dark-soft-D-XSM_fu.js → gruvbox-dark-soft-Cwq0dWVj.js} +0 -0
  345. /package/dist/web/assets/{gruvbox-light-hard-IVAwMJRl.js → gruvbox-light-hard-CLQCq2-w.js} +0 -0
  346. /package/dist/web/assets/{gruvbox-light-medium-38ATiG7i.js → gruvbox-light-medium-APHsh6Mo.js} +0 -0
  347. /package/dist/web/assets/{gruvbox-light-soft-DnZr3c_0.js → gruvbox-light-soft-CX-fYc64.js} +0 -0
  348. /package/dist/web/assets/{haskell-uQcywkDH.js → haskell-C4Tw-TDa.js} +0 -0
  349. /package/dist/web/assets/{haxe-c6bI4_GT.js → haxe-B7fSduTQ.js} +0 -0
  350. /package/dist/web/assets/{hcl-CQXTiEXq.js → hcl-Bi3ho6yC.js} +0 -0
  351. /package/dist/web/assets/{hjson-ChETf2bz.js → hjson-BXwae2M1.js} +0 -0
  352. /package/dist/web/assets/{hlsl-BMC4JGoE.js → hlsl-CRuQLBSa.js} +0 -0
  353. /package/dist/web/assets/{horizon-BusFlhLW.js → horizon-DtdQ6qjv.js} +0 -0
  354. /package/dist/web/assets/{horizon-bright-2oD0Mz7W.js → horizon-bright-BXSF_uKq.js} +0 -0
  355. /package/dist/web/assets/{houston-DdbbjqFg.js → houston-C6ASpUjT.js} +0 -0
  356. /package/dist/web/assets/{hy-D_SOuqw9.js → hy-BrWBHtHY.js} +0 -0
  357. /package/dist/web/assets/{image-gallery-CrM5fHKy.js → image-gallery-CGvlv8zR.js} +0 -0
  358. /package/dist/web/assets/{imba-BxLOHO5I.js → imba-C_JJXckG.js} +0 -0
  359. /package/dist/web/assets/{ini-ox-CFcg0.js → ini-DEE_vSHQ.js} +0 -0
  360. /package/dist/web/assets/{java-Bzo8yIal.js → java-CnmpcjcT.js} +0 -0
  361. /package/dist/web/assets/{javascript-DHuz9VXn.js → javascript-C-M7sa2e.js} +0 -0
  362. /package/dist/web/assets/{json-0_y80FD5.js → json-BjZ3dAk6.js} +0 -0
  363. /package/dist/web/assets/{json5-CEQ50pGM.js → json5-BQ2vpqjp.js} +0 -0
  364. /package/dist/web/assets/{jsonc-CfrLEAKA.js → jsonc-C5MjoWGx.js} +0 -0
  365. /package/dist/web/assets/{jsonl-fKbrANC2.js → jsonl-JvhrmQJI.js} +0 -0
  366. /package/dist/web/assets/{jsonnet-DKbkPaQ2.js → jsonnet-C5pdZVuo.js} +0 -0
  367. /package/dist/web/assets/{jssm-Dxxx1Hqu.js → jssm-Db17uybX.js} +0 -0
  368. /package/dist/web/assets/{jsx-DlJL-Oj3.js → jsx-tJp2Cyqu.js} +0 -0
  369. /package/dist/web/assets/{kanagawa-dragon-CwN4SV1c.js → kanagawa-dragon-BculT_Y1.js} +0 -0
  370. /package/dist/web/assets/{kanagawa-lotus-BHltayiE.js → kanagawa-lotus-yQgHUGwU.js} +0 -0
  371. /package/dist/web/assets/{kanagawa-wave-D-KXPjw6.js → kanagawa-wave-CyGoWN4d.js} +0 -0
  372. /package/dist/web/assets/{kdl-DvtoJdFo.js → kdl-Bn8R1REF.js} +0 -0
  373. /package/dist/web/assets/{kotlin-CTS4MLcx.js → kotlin-DWughK73.js} +0 -0
  374. /package/dist/web/assets/{kusto-HtSE_sKm.js → kusto--serPb0x.js} +0 -0
  375. /package/dist/web/assets/{laserwave-DaXZG9ge.js → laserwave-DfAPJ1tt.js} +0 -0
  376. /package/dist/web/assets/{lean-BYtGUfWx.js → lean-UAm1HOKl.js} +0 -0
  377. /package/dist/web/assets/{less-BoxmU_Mk.js → less-Xj6Ka0fF.js} +0 -0
  378. /package/dist/web/assets/{lib-B1clP4ai.js → lib-DgNcCtj3.js} +0 -0
  379. /package/dist/web/assets/{libesm-ah-mr-sh.js → libesm-CPh1Av0r.js} +0 -0
  380. /package/dist/web/assets/{light-plus-Bt5CyUuo.js → light-plus-BfS7gPcj.js} +0 -0
  381. /package/dist/web/assets/{llvm-CSdk9q9V.js → llvm-DvWiVwvU.js} +0 -0
  382. /package/dist/web/assets/{log-B-kp_3CL.js → log-Bo5z9bNz.js} +0 -0
  383. /package/dist/web/assets/{logo-DdIsXFDO.js → logo-CrIjcMZT.js} +0 -0
  384. /package/dist/web/assets/{luau-DUBpLlzQ.js → luau-C9TsYwNt.js} +0 -0
  385. /package/dist/web/assets/{make-B3JVjoW_.js → make-GYq4qVbx.js} +0 -0
  386. /package/dist/web/assets/{markdown-Seon0vHs.js → markdown-p5mNledS.js} +0 -0
  387. /package/dist/web/assets/{material-theme-Nq-ChX1P.js → material-theme-CWYOVxsP.js} +0 -0
  388. /package/dist/web/assets/{material-theme-darker-CPV4ayXJ.js → material-theme-darker-BDGty7YH.js} +0 -0
  389. /package/dist/web/assets/{material-theme-lighter-0kyjYqEd.js → material-theme-lighter-JbgOgV3n.js} +0 -0
  390. /package/dist/web/assets/{material-theme-ocean-DGpAp5co.js → material-theme-ocean-EMOpLpa2.js} +0 -0
  391. /package/dist/web/assets/{material-theme-palenight-B0AUn0NG.js → material-theme-palenight-CY5hgm7h.js} +0 -0
  392. /package/dist/web/assets/{matlab-C2waytxs.js → matlab-C-He_NTH.js} +0 -0
  393. /package/dist/web/assets/{mdx-DAis6R6I.js → mdx-Cr2TR5fj.js} +0 -0
  394. /package/dist/web/assets/{media-url-DlYsHq0S.js → media-url-CylYQld1.js} +0 -0
  395. /package/dist/web/assets/{mermaid-_rnT2YGD.js → mermaid-BYc0-B0U.js} +0 -0
  396. /package/dist/web/assets/{min-dark-BSSjchUB.js → min-dark-CMJwqJqB.js} +0 -0
  397. /package/dist/web/assets/{min-light-DomAFQsa.js → min-light-Cx6vFiEX.js} +0 -0
  398. /package/dist/web/assets/{mipsasm-bBgtvPyG.js → mipsasm-Bjer5HwK.js} +0 -0
  399. /package/dist/web/assets/{mobile-bottom-sheet-CS3XMwFw.js → mobile-bottom-sheet-BUOJgiaZ.js} +0 -0
  400. /package/dist/web/assets/{mojo-Cp9BayW0.js → mojo-t90PR-Y2.js} +0 -0
  401. /package/dist/web/assets/{monokai-CL_9gbmn.js → monokai-dci_PdCm.js} +0 -0
  402. /package/dist/web/assets/{moonbit-BS_fcr-P.js → moonbit-AAzI-Hd-.js} +0 -0
  403. /package/dist/web/assets/{move-C79AH45U.js → move-kwBhnhrG.js} +0 -0
  404. /package/dist/web/assets/{narrat-CJ5s3BDf.js → narrat-CXww2YQL.js} +0 -0
  405. /package/dist/web/assets/{nextflow-groovy-ZHa4JrPJ.js → nextflow-groovy-CJXsuXGB.js} +0 -0
  406. /package/dist/web/assets/{night-owl-Jkf9zFQK.js → night-owl-_GD204Wr.js} +0 -0
  407. /package/dist/web/assets/{night-owl-light-DRPeaG5J.js → night-owl-light-DNgkw3kl.js} +0 -0
  408. /package/dist/web/assets/{nix-D2Jet9DN.js → nix-BgiorKFd.js} +0 -0
  409. /package/dist/web/assets/{nord-CREVs22j.js → nord-CaBmcxFC.js} +0 -0
  410. /package/dist/web/assets/{nushell-CAiDi_mR.js → nushell-DUh4UGx1.js} +0 -0
  411. /package/dist/web/assets/{objective-c-CVkmJkC1.js → objective-c-Cl9KU86S.js} +0 -0
  412. /package/dist/web/assets/{objective-cpp-DIKDO1Ly.js → objective-cpp-DVkIA8A0.js} +0 -0
  413. /package/dist/web/assets/{ocaml-R9qtGQhs.js → ocaml-vvoHTak0.js} +0 -0
  414. /package/dist/web/assets/{odin-DTYNQqVr.js → odin-Cyjw8woZ.js} +0 -0
  415. /package/dist/web/assets/{one-dark-pro-BSLWUJn5.js → one-dark-pro-B1cviILi.js} +0 -0
  416. /package/dist/web/assets/{one-light-DbkRXG3t.js → one-light-BPGUJeYI.js} +0 -0
  417. /package/dist/web/assets/{openscad-BlPcSnmT.js → openscad-BLMdTUU8.js} +0 -0
  418. /package/dist/web/assets/{pascal-B1Y46ZZB.js → pascal-i5niy3e7.js} +0 -0
  419. /package/dist/web/assets/{pkl-BhJSJbFv.js → pkl-CuOV7SsU.js} +0 -0
  420. /package/dist/web/assets/{plastic-BzxsCTpi.js → plastic-Bf_zE5KL.js} +0 -0
  421. /package/dist/web/assets/{plsql-DBba7dyP.js → plsql-cfqEtMD3.js} +0 -0
  422. /package/dist/web/assets/{plus-DmjC2iRB.js → plus-BM-Ty0fp.js} +0 -0
  423. /package/dist/web/assets/{po-BvgLlnNo.js → po-CFJcWgjr.js} +0 -0
  424. /package/dist/web/assets/{poimandres-DUaI_1JP.js → poimandres-G5YoaIFf.js} +0 -0
  425. /package/dist/web/assets/{polar-C7uILwJn.js → polar-rcjs3i9R.js} +0 -0
  426. /package/dist/web/assets/{postcss-BgJlpFdw.js → postcss-CBKY1FTZ.js} +0 -0
  427. /package/dist/web/assets/{powerquery-Dn1MIpZu.js → powerquery-Db7SXLbO.js} +0 -0
  428. /package/dist/web/assets/{powershell-Bo-DYzOS.js → powershell-LFy3MUTP.js} +0 -0
  429. /package/dist/web/assets/{prisma-CTLs5IdT.js → prisma-BE8GR1lH.js} +0 -0
  430. /package/dist/web/assets/{prolog-QRGun3eG.js → prolog-DOn5lR1e.js} +0 -0
  431. /package/dist/web/assets/{proto-B7PI7apn.js → proto-wr-TpAK_.js} +0 -0
  432. /package/dist/web/assets/{puppet-CBq0tLrP.js → puppet-D2Dkv62u.js} +0 -0
  433. /package/dist/web/assets/{purescript-DFewOQb2.js → purescript-DvgJgPdy.js} +0 -0
  434. /package/dist/web/assets/{python-iWuxKXvT.js → python-C7TlkHhK.js} +0 -0
  435. /package/dist/web/assets/{qmldir-cXiW3AsF.js → qmldir-CtZMwhcW.js} +0 -0
  436. /package/dist/web/assets/{qss-DASwAbBL.js → qss-dNZ2btnl.js} +0 -0
  437. /package/dist/web/assets/{r-TU2eaIPw.js → r-BlqnNkHS.js} +0 -0
  438. /package/dist/web/assets/{racket-SkRKqrLY.js → racket-CzRQrGc4.js} +0 -0
  439. /package/dist/web/assets/{raku-D31lthkZ.js → raku-BwutWhBF.js} +0 -0
  440. /package/dist/web/assets/{red-CTcQZevb.js → red-BMXMywmL.js} +0 -0
  441. /package/dist/web/assets/{reg-D8YAsTGf.js → reg-BqOKrIOw.js} +0 -0
  442. /package/dist/web/assets/{regexp-CD2uvAWx.js → regexp-Bero1BN2.js} +0 -0
  443. /package/dist/web/assets/{rel-CAaI-1fg.js → rel-BXKWIElA.js} +0 -0
  444. /package/dist/web/assets/{riscv-DR-hJVIj.js → riscv-BbbBYJBo.js} +0 -0
  445. /package/dist/web/assets/{ron-CuUCJ0n4.js → ron-BtVTWW4b.js} +0 -0
  446. /package/dist/web/assets/{rose-pine-dawn-Bqz2sBRY.js → rose-pine-dawn-D7lwhUei.js} +0 -0
  447. /package/dist/web/assets/{rose-pine-aFHxW48i.js → rose-pine-hvkvQzvU.js} +0 -0
  448. /package/dist/web/assets/{rose-pine-moon-wqyh0an4.js → rose-pine-moon-CoHDmsIw.js} +0 -0
  449. /package/dist/web/assets/{rosmsg-CI1ywimO.js → rosmsg-CdaZFgI8.js} +0 -0
  450. /package/dist/web/assets/{run-in-terminal-CGW6o37_.js → run-in-terminal-CyS5Itj-.js} +0 -0
  451. /package/dist/web/assets/{rust-p7Imk4G_.js → rust-Dy2qsphD.js} +0 -0
  452. /package/dist/web/assets/{sass-C8JfaqCV.js → sass-Bz7NVxDb.js} +0 -0
  453. /package/dist/web/assets/{save-DRPrDfTt.js → save-C4z1p51e.js} +0 -0
  454. /package/dist/web/assets/{scala-DNxCW1By.js → scala-sXSwsNyq.js} +0 -0
  455. /package/dist/web/assets/{scheme-BYuUPJoL.js → scheme-DS7TUbN7.js} +0 -0
  456. /package/dist/web/assets/{sdbl-DbPeJPUr.js → sdbl-iISFvIep.js} +0 -0
  457. /package/dist/web/assets/{send-to-chat-YXHdAyLG.js → send-to-chat-BcO39BDR.js} +0 -0
  458. /package/dist/web/assets/{shellscript-DMiHlR3q.js → shellscript-BkIl4ApC.js} +0 -0
  459. /package/dist/web/assets/{shield-check-8GObuUAn.js → shield-check-C5laObJv.js} +0 -0
  460. /package/dist/web/assets/{shield-off-egKAZEwR.js → shield-off-DULFtyLS.js} +0 -0
  461. /package/dist/web/assets/{slack-dark-C4xGcQXI.js → slack-dark-B1eg0_m2.js} +0 -0
  462. /package/dist/web/assets/{slack-ochin-BzgRt_wm.js → slack-ochin-mdkc1ldu.js} +0 -0
  463. /package/dist/web/assets/{smalltalk-LDeL9PYH.js → smalltalk-CORtd03t.js} +0 -0
  464. /package/dist/web/assets/{snazzy-light-CXE7a5j_.js → snazzy-light-Bc6Q2G89.js} +0 -0
  465. /package/dist/web/assets/{solarized-dark-DgUhY74x.js → solarized-dark-CF83zRXM.js} +0 -0
  466. /package/dist/web/assets/{solarized-light-DD9C-H-9.js → solarized-light-BoKQZaYU.js} +0 -0
  467. /package/dist/web/assets/{solidity-CAbDB4D4.js → solidity-DOgi1N4w.js} +0 -0
  468. /package/dist/web/assets/{sparkles-n1hzh65o.js → sparkles-Dqsf3hq6.js} +0 -0
  469. /package/dist/web/assets/{splunk-kQREPfIc.js → splunk-BXfw5ZLy.js} +0 -0
  470. /package/dist/web/assets/{sql-CBzeNAD8.js → sql-BcVs-eX4.js} +0 -0
  471. /package/dist/web/assets/{ssh-config-L1euxrsM.js → ssh-config-CLCtNkkd.js} +0 -0
  472. /package/dist/web/assets/{stylus-DvBnYniP.js → stylus-DdP992aO.js} +0 -0
  473. /package/dist/web/assets/{swift-DF5NDQp6.js → swift-BnGb6Lgc.js} +0 -0
  474. /package/dist/web/assets/{synthwave-84-DbBhB_Hq.js → synthwave-84-cg9264l9.js} +0 -0
  475. /package/dist/web/assets/{system-verilog-D8s2ZW_k.js → system-verilog-GbHpszs3.js} +0 -0
  476. /package/dist/web/assets/{systemd-a5-XZJsG.js → systemd-Dz-bNsDQ.js} +0 -0
  477. /package/dist/web/assets/{table-BX2ZrJfM.js → table-CHmxuh6M.js} +0 -0
  478. /package/dist/web/assets/{talonscript-BLa0URTW.js → talonscript-CFIidoBA.js} +0 -0
  479. /package/dist/web/assets/{tasl-DIoV4XcC.js → tasl-Cu-TRTKx.js} +0 -0
  480. /package/dist/web/assets/{tcl-ztYAdXfQ.js → tcl-DwCHCB1K.js} +0 -0
  481. /package/dist/web/assets/{terraform-DvpCCiOZ.js → terraform-BzZw4T1z.js} +0 -0
  482. /package/dist/web/assets/{tokyo-night-BkHlYUv0.js → tokyo-night-RKsj2-tv.js} +0 -0
  483. /package/dist/web/assets/{toml-acIrxos6.js → toml-CirbOgDP.js} +0 -0
  484. /package/dist/web/assets/{tsv-BJB5EVCT.js → tsv-CraRcWdU.js} +0 -0
  485. /package/dist/web/assets/{tsx-B1MmXGT3.js → tsx-CjFg0lgw.js} +0 -0
  486. /package/dist/web/assets/{turtle-DFceTiqd.js → turtle-B-WBIOa6.js} +0 -0
  487. /package/dist/web/assets/{typescript-Dz9wU5Y1.js → typescript-MpLarYn1.js} +0 -0
  488. /package/dist/web/assets/{typespec-CPuYZijj.js → typespec-B7QlHMZ_.js} +0 -0
  489. /package/dist/web/assets/{typst-CfsCIYv8.js → typst-CcHSKFZj.js} +0 -0
  490. /package/dist/web/assets/{use-blob-url-BmlYYZ8L.js → use-blob-url-BKyVxOZw.js} +0 -0
  491. /package/dist/web/assets/{use-is-mobile-B8FA4kQf.js → use-is-mobile-BXGVvczu.js} +0 -0
  492. /package/dist/web/assets/{v-CGo0jcXA.js → v-xTGhWZuD.js} +0 -0
  493. /package/dist/web/assets/{vala-AsSR0hrb.js → vala-DwebjH3H.js} +0 -0
  494. /package/dist/web/assets/{vb-C7tvbXv1.js → vb-BxJT2RAy.js} +0 -0
  495. /package/dist/web/assets/{vendor-xterm-C1diXHJl.js → vendor-xterm-CU6zIYMB.js} +0 -0
  496. /package/dist/web/assets/{verilog--a33ND-p.js → verilog-CvV6RHPD.js} +0 -0
  497. /package/dist/web/assets/{vesper-B_Z0h4pn.js → vesper-CY3qd7E_.js} +0 -0
  498. /package/dist/web/assets/{vhdl-CWL5dZPN.js → vhdl-B9ZX-sUL.js} +0 -0
  499. /package/dist/web/assets/{viml-BglmT14Y.js → viml-Y42h_ExQ.js} +0 -0
  500. /package/dist/web/assets/{vitesse-black-RKFsSqQI.js → vitesse-black-DkXP6Sv-.js} +0 -0
  501. /package/dist/web/assets/{vitesse-dark-D7zDWNmc.js → vitesse-dark-B9CkIB6r.js} +0 -0
  502. /package/dist/web/assets/{vitesse-light-MAp87W5b.js → vitesse-light-C7DHrJCK.js} +0 -0
  503. /package/dist/web/assets/{vyper-CgCBYg1G.js → vyper-Cnd9s5j-.js} +0 -0
  504. /package/dist/web/assets/{wasm-Bwl4txwp.js → wasm-DQE71XTB.js} +0 -0
  505. /package/dist/web/assets/{wasm-BOG7ZeTT.js → wasm-iWe7Fzjc.js} +0 -0
  506. /package/dist/web/assets/{wenyan-DpShPKXZ.js → wenyan-Bc5Pnm9l.js} +0 -0
  507. /package/dist/web/assets/{wgsl-BakcCblK.js → wgsl-D-YUAWkP.js} +0 -0
  508. /package/dist/web/assets/{wikitext-NroRWVAO.js → wikitext-DYQDUYf2.js} +0 -0
  509. /package/dist/web/assets/{wit-B5CM2pg6.js → wit-P6u7mfwy.js} +0 -0
  510. /package/dist/web/assets/{wolfram-7MTFBJpR.js → wolfram-6SXLUqao.js} +0 -0
  511. /package/dist/web/assets/{yaml-Bwr01G2K.js → yaml-CQiMLVcZ.js} +0 -0
  512. /package/dist/web/assets/{zenscript-Dj8GATvi.js → zenscript-DFMywo_P.js} +0 -0
  513. /package/dist/web/assets/{zig-LAE-fbS-.js → zig-CtAjaIiF.js} +0 -0
@@ -0,0 +1,90 @@
1
+ /** Sort comparator for the process table, split out of `process-table-model.ts`
2
+ * to keep that file under the repo's 200-line guideline once Disk/GPU/Net sort
3
+ * keys were added. No React, no I/O — pure so it's directly unit-testable. */
4
+ import type { SortDir, SortKey } from "../../../types/system-metrics";
5
+
6
+ /** Fields the comparator can read from either a `ProcessInfo` or a `ProcessGroup`
7
+ * roll-up — both carry the same six optional metric names per the contract.
8
+ * Optional metrics stay optional here: the "undefined sorts last, regardless of
9
+ * direction" rule below depends on being able to tell "unmeasured" from "0". */
10
+ export interface SortableFields {
11
+ cpu: number;
12
+ ramMB: number;
13
+ name: string;
14
+ diskReadBps?: number;
15
+ diskWriteBps?: number;
16
+ gpuPct?: number;
17
+ gpuMemMB?: number;
18
+ netInBps?: number;
19
+ netOutBps?: number;
20
+ }
21
+
22
+ /** Maps a `ProcessInfo` or `ProcessGroup` into `SortableFields` — only `name`
23
+ * differs between the two shapes (process `name` vs. group `label`), so one
24
+ * function covers both sort inputs. */
25
+ export function sortFields(m: {
26
+ cpu: number;
27
+ ramMB: number;
28
+ diskReadBps?: number;
29
+ diskWriteBps?: number;
30
+ gpuPct?: number;
31
+ gpuMemMB?: number;
32
+ netInBps?: number;
33
+ netOutBps?: number;
34
+ }, name: string): SortableFields {
35
+ return {
36
+ cpu: m.cpu,
37
+ ramMB: m.ramMB,
38
+ name,
39
+ diskReadBps: m.diskReadBps,
40
+ diskWriteBps: m.diskWriteBps,
41
+ gpuPct: m.gpuPct,
42
+ gpuMemMB: m.gpuMemMB,
43
+ netInBps: m.netInBps,
44
+ netOutBps: m.netOutBps,
45
+ };
46
+ }
47
+
48
+ /** `undefined` when neither side of the pair is measured — matches the
49
+ * ProcessInfo/ProcessGroup contract ("undefined when NO member has a value"). */
50
+ function sumPair(a?: number, b?: number): number | undefined {
51
+ if (a === undefined && b === undefined) return undefined;
52
+ return (a ?? 0) + (b ?? 0);
53
+ }
54
+
55
+ function optionalValueFor(key: "disk" | "gpu" | "gpuMem" | "net", f: SortableFields): number | undefined {
56
+ if (key === "disk") return sumPair(f.diskReadBps, f.diskWriteBps);
57
+ if (key === "net") return sumPair(f.netInBps, f.netOutBps);
58
+ if (key === "gpu") return f.gpuPct;
59
+ return f.gpuMemMB;
60
+ }
61
+
62
+ function isOptionalSortKey(key: SortKey): key is "disk" | "gpu" | "gpuMem" | "net" {
63
+ return key === "disk" || key === "gpu" || key === "gpuMem" || key === "net";
64
+ }
65
+
66
+ export function sortByKey<T>(items: T[], key: SortKey, dir: SortDir, get: (item: T) => SortableFields): T[] {
67
+ if (!key) return items;
68
+ return [...items].sort((a, b) => {
69
+ const av = get(a);
70
+ const bv = get(b);
71
+ if (key === "name") {
72
+ const cmp = av.name.localeCompare(bv.name);
73
+ return dir === "asc" ? cmp : -cmp;
74
+ }
75
+ if (key === "cpu") return dir === "asc" ? av.cpu - bv.cpu : bv.cpu - av.cpu;
76
+ if (key === "ram") return dir === "asc" ? av.ramMB - bv.ramMB : bv.ramMB - av.ramMB;
77
+
78
+ // disk/gpu/gpuMem/net: optional metrics. Undefined always sorts last, in
79
+ // EITHER direction — it means "unmeasurable", not "smallest value".
80
+ if (isOptionalSortKey(key)) {
81
+ const aVal = optionalValueFor(key, av);
82
+ const bVal = optionalValueFor(key, bv);
83
+ if (aVal === undefined && bVal === undefined) return 0;
84
+ if (aVal === undefined) return 1;
85
+ if (bVal === undefined) return -1;
86
+ return dir === "asc" ? aVal - bVal : bVal - aVal;
87
+ }
88
+ return 0;
89
+ });
90
+ }
@@ -0,0 +1,159 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import { Search } from "lucide-react";
3
+ import { cn } from "@/lib/utils";
4
+ import { formatRam } from "@/lib/format-bytes";
5
+ import { cpuColor, formatDiskCell, formatGpuCell, formatNetCell } from "./process-row-format";
6
+ import { optionalCellClassName, PROCESS_ROW_GRID_CLASS, type ProcessGridResult } from "./process-columns-grid";
7
+ import type { Totals } from "./process-table-totals";
8
+ import { SortableHeader, type ColumnResizeHandlers } from "./sortable-header";
9
+ import type { SortDir, SortKey } from "../../../types/system-metrics";
10
+
11
+ const SEARCH_DEBOUNCE_MS = 150;
12
+
13
+ export interface ProcessTableToolbarProps {
14
+ mode: "grouped" | "flat";
15
+ onModeChange: (mode: "grouped" | "flat") => void;
16
+ ppmOnly: boolean;
17
+ onPpmOnlyChange: (v: boolean) => void;
18
+ onQueryChange: (query: string) => void;
19
+ }
20
+
21
+ /** Search/mode/PPM controls. Debounces the query locally so typing does not rebuild
22
+ * up to 1000 rows on every keystroke. */
23
+ export function ProcessTableToolbar({
24
+ mode,
25
+ onModeChange,
26
+ ppmOnly,
27
+ onPpmOnlyChange,
28
+ onQueryChange,
29
+ }: ProcessTableToolbarProps) {
30
+ const [draft, setDraft] = useState("");
31
+ const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
32
+
33
+ useEffect(() => {
34
+ if (timer.current) clearTimeout(timer.current);
35
+ timer.current = setTimeout(() => onQueryChange(draft), SEARCH_DEBOUNCE_MS);
36
+ return () => {
37
+ if (timer.current) clearTimeout(timer.current);
38
+ };
39
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- onQueryChange identity may churn; only `draft` should retrigger
40
+ }, [draft]);
41
+
42
+ return (
43
+ <div className="flex flex-wrap items-center gap-2 p-2 border-b border-border shrink-0">
44
+ <div className="relative flex-1 min-w-[140px]">
45
+ <Search className="absolute left-2 top-1/2 -translate-y-1/2 size-3.5 text-text-subtle" />
46
+ <input
47
+ type="text"
48
+ value={draft}
49
+ onChange={(e) => setDraft(e.target.value)}
50
+ placeholder="Search processes"
51
+ aria-label="Search processes"
52
+ data-testid="sysmon-process-search"
53
+ className="w-full min-h-11 md:min-h-8 pl-7 pr-2 text-sm rounded-md border border-border bg-transparent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
54
+ />
55
+ </div>
56
+ <button
57
+ type="button"
58
+ onClick={() => onModeChange(mode === "grouped" ? "flat" : "grouped")}
59
+ aria-pressed={mode === "flat"}
60
+ data-testid="sysmon-toggle-flat"
61
+ className="min-h-11 md:min-h-8 px-3 text-xs rounded-md border border-border hover:bg-surface-hover transition-colors"
62
+ >
63
+ {mode === "flat" ? "Flat" : "Grouped"}
64
+ </button>
65
+ <button
66
+ type="button"
67
+ onClick={() => onPpmOnlyChange(!ppmOnly)}
68
+ aria-pressed={ppmOnly}
69
+ data-testid="sysmon-filter-ppm"
70
+ className={cn(
71
+ "min-h-11 md:min-h-8 px-3 text-xs rounded-md border transition-colors",
72
+ ppmOnly ? "border-primary bg-primary/10 text-primary" : "border-border hover:bg-surface-hover",
73
+ )}
74
+ >
75
+ PPM only
76
+ </button>
77
+ </div>
78
+ );
79
+ }
80
+
81
+ export interface ProcessTableHeaderProps {
82
+ sortKey: SortKey;
83
+ sortDir: SortDir;
84
+ grid: ProcessGridResult;
85
+ onSort: (field: Exclude<SortKey, null>) => void;
86
+ resize: ColumnResizeHandlers;
87
+ }
88
+
89
+ /** Sticky column header row, grid-aligned with the rows below it. Disk/GPU/Net
90
+ * headers only render when the host reported that column as measurable
91
+ * (`grid.columns.<x>`); below `@lg` only the one currently sorted survives. Every
92
+ * fixed-width column carries a drag handle on its right edge. */
93
+ export function ProcessTableHeader({ sortKey, sortDir, grid, onSort, resize }: ProcessTableHeaderProps) {
94
+ const common = { activeKey: sortKey, activeDir: sortDir, onClick: onSort, resize };
95
+ return (
96
+ <div
97
+ role="row"
98
+ className={cn(
99
+ "grid gap-1 px-3 py-1.5 text-[11px] text-text-subtle border-b border-border sticky top-0 bg-background z-10",
100
+ PROCESS_ROW_GRID_CLASS,
101
+ )}
102
+ >
103
+ <SortableHeader label="Process" field="name" {...common} resize={undefined} align="left" testId="sysmon-sort-name" />
104
+ <SortableHeader label="CPU" field="cpu" {...common} resizeKey="cpu" testId="sysmon-sort-cpu" />
105
+ <SortableHeader label="RAM" field="ram" {...common} resizeKey="ram" testId="sysmon-sort-ram" />
106
+ {grid.columns.disk && (
107
+ <SortableHeader label="Disk" field="disk" {...common} resizeKey="disk" testId="sysmon-col-disk" className={optionalCellClassName(grid, "disk")} />
108
+ )}
109
+ {grid.columns.gpu && (
110
+ <SortableHeader label="GPU" field="gpu" {...common} resizeKey="gpu" testId="sysmon-col-gpu" className={optionalCellClassName(grid, "gpu")} />
111
+ )}
112
+ {grid.columns.net && (
113
+ <SortableHeader label="Net" field="net" {...common} resizeKey="net" testId="sysmon-col-net" className={optionalCellClassName(grid, "net")} />
114
+ )}
115
+ <span />
116
+ </div>
117
+ );
118
+ }
119
+
120
+ export interface ProcessTableFooterProps {
121
+ totals: Totals;
122
+ grid: ProcessGridResult;
123
+ /** `system.gpus[0]?.utilPercent` — a whole-machine reading, not a sum of the
124
+ * visible rows' `gpuPct` (per-process GPU% can double-count shared engines). */
125
+ gpuUtilPercent?: number;
126
+ }
127
+
128
+ export function ProcessTableFooter({ totals, grid, gpuUtilPercent }: ProcessTableFooterProps) {
129
+ return (
130
+ <div
131
+ className={cn(
132
+ "grid gap-1 px-3 py-1.5 text-xs font-medium border-t border-border shrink-0",
133
+ PROCESS_ROW_GRID_CLASS,
134
+ )}
135
+ data-testid="sysmon-total"
136
+ data-process-count={totals.count}
137
+ >
138
+ <span className="truncate">Total ({totals.count} processes)</span>
139
+ <span className={cn("text-right", cpuColor(totals.cpu))}>{totals.cpu.toFixed(1)}%</span>
140
+ <span className="text-right text-text-secondary">{formatRam(totals.ramMB)}</span>
141
+ {grid.columns.disk && (
142
+ <span className={cn("text-right text-text-secondary tabular-nums truncate", optionalCellClassName(grid, "disk"))}>
143
+ {formatDiskCell(totals.diskReadBps, totals.diskWriteBps)}
144
+ </span>
145
+ )}
146
+ {grid.columns.gpu && (
147
+ <span className={cn("text-right text-text-secondary tabular-nums truncate", optionalCellClassName(grid, "gpu"))}>
148
+ {formatGpuCell(gpuUtilPercent, totals.gpuMemMB)}
149
+ </span>
150
+ )}
151
+ {grid.columns.net && (
152
+ <span className={cn("text-right text-text-secondary tabular-nums truncate", optionalCellClassName(grid, "net"))}>
153
+ {formatNetCell(totals.netInBps, totals.netOutBps)}
154
+ </span>
155
+ )}
156
+ <span />
157
+ </div>
158
+ );
159
+ }
@@ -0,0 +1,49 @@
1
+ /** Footer totals accumulator, split out of `process-table-model.ts` to keep
2
+ * that file under the repo's 200-line guideline. Pure, no React/I/O. */
3
+
4
+ export interface Totals {
5
+ cpu: number;
6
+ ramMB: number;
7
+ count: number;
8
+ /** Sums over rows with a defined value; `undefined` when NO visible row measured
9
+ * that metric — mirrors the "undefined = host can't measure" rule on ProcessInfo. */
10
+ diskReadBps?: number;
11
+ diskWriteBps?: number;
12
+ gpuMemMB?: number;
13
+ netInBps?: number;
14
+ netOutBps?: number;
15
+ }
16
+
17
+ export const EMPTY_TOTALS: Totals = { cpu: 0, ramMB: 0, count: 0 };
18
+
19
+ /** Adds an optional metric into a running total; stays `undefined` until at
20
+ * least one contributor has a defined value (mirrors the roll-up rule). */
21
+ function addOptional(sum: number | undefined, value: number | undefined): number | undefined {
22
+ if (value === undefined) return sum;
23
+ return (sum ?? 0) + value;
24
+ }
25
+
26
+ export function accumulateTotals(
27
+ acc: Totals,
28
+ item: {
29
+ cpu: number;
30
+ ramMB: number;
31
+ diskReadBps?: number;
32
+ diskWriteBps?: number;
33
+ gpuMemMB?: number;
34
+ netInBps?: number;
35
+ netOutBps?: number;
36
+ },
37
+ countDelta: number,
38
+ ): Totals {
39
+ return {
40
+ cpu: acc.cpu + item.cpu,
41
+ ramMB: acc.ramMB + item.ramMB,
42
+ count: acc.count + countDelta,
43
+ diskReadBps: addOptional(acc.diskReadBps, item.diskReadBps),
44
+ diskWriteBps: addOptional(acc.diskWriteBps, item.diskWriteBps),
45
+ gpuMemMB: addOptional(acc.gpuMemMB, item.gpuMemMB),
46
+ netInBps: addOptional(acc.netInBps, item.netInBps),
47
+ netOutBps: addOptional(acc.netOutBps, item.netOutBps),
48
+ };
49
+ }
@@ -0,0 +1,146 @@
1
+ import { useCallback, useMemo, useRef, useState } from "react";
2
+ import { useVirtualizer } from "@tanstack/react-virtual";
3
+ import { useIsMobile } from "@/hooks/use-is-mobile";
4
+ import { buildRows, toggleSort } from "./process-table-model";
5
+ import { buildProcessGrid, gridCssVars } from "./process-columns-grid";
6
+ import { ProcessTableToolbar, ProcessTableHeader, ProcessTableFooter } from "./process-table-toolbar";
7
+ import { ProcessGroupRow } from "./process-group-row";
8
+ import { ProcessRow } from "./process-row";
9
+ import { KillConfirmDialog } from "./kill-confirm-dialog";
10
+ import { useProcessKill } from "./use-process-kill";
11
+ import { useColumnWidths } from "./use-column-widths";
12
+ import type { MetricsSnapshot, SortDir, SortKey } from "../../../types/system-metrics";
13
+
14
+ /** Older cached bundles/snapshots (mid-rollout) predate `processColumns` — default
15
+ * every optional column off rather than let a missing field throw. */
16
+ const NO_OPTIONAL_COLUMNS = { disk: false, gpu: false, net: false };
17
+
18
+ export interface ProcessTableProps {
19
+ snapshot: MetricsSnapshot;
20
+ }
21
+
22
+ export function ProcessTable({ snapshot }: ProcessTableProps) {
23
+ const isMobile = useIsMobile();
24
+ const parentRef = useRef<HTMLDivElement>(null);
25
+
26
+ const [mode, setMode] = useState<"grouped" | "flat">("grouped");
27
+ const [ppmOnly, setPpmOnly] = useState(false);
28
+ const [query, setQuery] = useState("");
29
+ const [sortKey, setSortKey] = useState<SortKey>(null);
30
+ const [sortDir, setSortDir] = useState<SortDir>("desc");
31
+ const [expanded, setExpanded] = useState<Set<string>>(() => new Set());
32
+ const { pendingKill, groupProtected, requestKillProcess, requestKillGroup, confirmKill, cancelKill } =
33
+ useProcessKill(snapshot);
34
+ const { widths, begin: onResizeStart, reset: onResizeReset } = useColumnWidths();
35
+
36
+ const { rows, totals } = useMemo(
37
+ () =>
38
+ buildRows({
39
+ processes: snapshot.processes,
40
+ groups: snapshot.groups,
41
+ mode,
42
+ ppmOnly,
43
+ query,
44
+ sortKey,
45
+ sortDir,
46
+ expanded,
47
+ }),
48
+ [snapshot.processes, snapshot.groups, mode, ppmOnly, query, sortKey, sortDir, expanded],
49
+ );
50
+
51
+ const columns = snapshot.processColumns ?? NO_OPTIONAL_COLUMNS;
52
+ const grid = useMemo(() => buildProcessGrid(columns, sortKey, widths), [columns, sortKey, widths]);
53
+ const gpuUtilPercent = snapshot.system.gpus[0]?.utilPercent;
54
+
55
+ const virtualizer = useVirtualizer({
56
+ count: rows.length,
57
+ getScrollElement: () => parentRef.current,
58
+ estimateSize: () => (isMobile ? 44 : 28),
59
+ overscan: 12,
60
+ });
61
+
62
+ const handleSort = useCallback(
63
+ (field: Exclude<SortKey, null>) => {
64
+ const [nextKey, nextDir] = toggleSort(sortKey, sortDir, field);
65
+ setSortKey(nextKey);
66
+ setSortDir(nextDir);
67
+ },
68
+ [sortKey, sortDir],
69
+ );
70
+
71
+ const handleToggleGroup = useCallback((key: string) => {
72
+ setExpanded((prev) => {
73
+ const next = new Set(prev);
74
+ if (next.has(key)) next.delete(key);
75
+ else next.add(key);
76
+ return next;
77
+ });
78
+ }, []);
79
+
80
+ // `@container`: the trend/age track is toggled on the table's own width, not the
81
+ // viewport — a floating window is routinely narrower than the screen it sits on.
82
+ // `gridCssVars` sets `--sysmon-grid-n`/`--sysmon-grid-w` once here; CSS custom
83
+ // properties inherit to every row/header/footer below without re-passing style.
84
+ return (
85
+ <div
86
+ className="h-full flex flex-col min-h-0 @container"
87
+ style={gridCssVars(grid)}
88
+ data-testid="sysmon-processes"
89
+ data-row-count={rows.length}
90
+ >
91
+ <ProcessTableToolbar
92
+ mode={mode}
93
+ onModeChange={setMode}
94
+ ppmOnly={ppmOnly}
95
+ onPpmOnlyChange={setPpmOnly}
96
+ onQueryChange={setQuery}
97
+ />
98
+ <ProcessTableHeader
99
+ sortKey={sortKey}
100
+ sortDir={sortDir}
101
+ grid={grid}
102
+ onSort={handleSort}
103
+ resize={{ onResizeStart, onResizeReset }}
104
+ />
105
+ <div ref={parentRef} className="flex-1 min-h-0 overflow-y-auto">
106
+ <div style={{ height: virtualizer.getTotalSize(), position: "relative" }}>
107
+ {virtualizer.getVirtualItems().map((item) => {
108
+ const row = rows[item.index];
109
+ if (!row) return null;
110
+ return (
111
+ <div
112
+ key={row.kind === "group" ? row.group.key : `p:${row.proc.pid}`}
113
+ style={{
114
+ position: "absolute",
115
+ top: 0,
116
+ left: 0,
117
+ right: 0,
118
+ transform: `translateY(${item.start}px)`,
119
+ }}
120
+ >
121
+ {row.kind === "group" ? (
122
+ <ProcessGroupRow
123
+ group={row.group}
124
+ expanded={row.expanded}
125
+ grid={grid}
126
+ killProtected={groupProtected.get(row.group.key) ?? true}
127
+ onToggle={handleToggleGroup}
128
+ onKillClick={requestKillGroup}
129
+ />
130
+ ) : (
131
+ <ProcessRow proc={row.proc} indent={row.indent} grid={grid} onKillClick={requestKillProcess} />
132
+ )}
133
+ </div>
134
+ );
135
+ })}
136
+ </div>
137
+ </div>
138
+ <ProcessTableFooter totals={totals} grid={grid} gpuUtilPercent={gpuUtilPercent} />
139
+ <KillConfirmDialog
140
+ target={pendingKill}
141
+ onConfirm={confirmKill}
142
+ onCancel={cancelKill}
143
+ />
144
+ </div>
145
+ );
146
+ }
@@ -0,0 +1,29 @@
1
+ /** Pure viewport-routing decision for the System Monitor open-hook — split out from
2
+ * `use-open-system-monitor.ts` so it has zero runtime imports (only a type-only one,
3
+ * fully erased) and is unit-testable without mounting zustand stores. */
4
+ import type { Tab } from "@/stores/tab-store";
5
+
6
+ export type OpenSystemMonitorAction =
7
+ | { kind: "tab"; tab: Omit<Tab, "id"> }
8
+ | { kind: "window" }
9
+ | { kind: "focus"; id: string };
10
+
11
+ /**
12
+ * There is exactly one machine, so unlike `"explorer"`/`"team-member"` (legitimately
13
+ * multi-instance — different payload, different folder/teammate), a second
14
+ * `"system-monitor"` window is never a distinct instance, only a duplicate. When one
15
+ * is already open, focus it instead of spawning another.
16
+ */
17
+ export function resolveOpenSystemMonitorAction(
18
+ isMobile: boolean,
19
+ existingWindowId: string | null,
20
+ ): OpenSystemMonitorAction {
21
+ if (isMobile) {
22
+ return {
23
+ kind: "tab",
24
+ tab: { type: "system-monitor", title: "System Monitor", projectId: null, closable: true },
25
+ };
26
+ }
27
+ if (existingWindowId) return { kind: "focus", id: existingWindowId };
28
+ return { kind: "window" };
29
+ }
@@ -1,9 +1,9 @@
1
1
  import { memo } from "react";
2
2
  import { Cpu } from "lucide-react";
3
3
  import { useResourceMonitor } from "@/hooks/use-resource-monitor";
4
- import { useTabStore } from "@/stores/tab-store";
5
4
  import { useIsMobile } from "@/hooks/use-is-mobile";
6
5
  import { cn } from "@/lib/utils";
6
+ import { useOpenSystemMonitor } from "./use-open-system-monitor";
7
7
 
8
8
  function cpuColor(cpu: number) {
9
9
  if (cpu > 80) return "text-error";
@@ -11,26 +11,21 @@ function cpuColor(cpu: number) {
11
11
  return "text-success";
12
12
  }
13
13
 
14
- /** `compact` renders inline for the 22px status bar (no full-width button, CPU+MEM only). */
14
+ /** `compact` renders inline for the 22px status bar (no full-width button, CPU+MEM only).
15
+ * Stays on the light SSE tier — never opts into `{processes:true}` — so it never pays
16
+ * for the full collector just to render two numbers. */
15
17
  export const ResourceStatusBar = memo(function ResourceStatusBar({ compact = false }: { compact?: boolean }) {
16
18
  const { latest, isConnected } = useResourceMonitor();
17
- const openTab = useTabStore((s) => s.openTab);
19
+ const openSystemMonitor = useOpenSystemMonitor();
18
20
  const isMobile = useIsMobile();
19
21
 
20
- const handleClick = () => {
21
- openTab({
22
- type: "system-monitor",
23
- title: "System Monitor",
24
- projectId: null,
25
- closable: true,
26
- });
27
- };
28
-
29
22
  if (!isConnected || !latest) {
30
23
  if (compact) return null; // stay silent in the status bar until connected
31
24
  return (
32
25
  <button
33
- onClick={handleClick}
26
+ onClick={openSystemMonitor}
27
+ data-testid="status-bar-resources"
28
+ aria-label="Open System Monitor"
34
29
  className="flex items-center gap-1.5 px-2 py-1 text-[10px] text-text-subtle hover:text-text-secondary transition-colors w-full"
35
30
  >
36
31
  <Cpu className="size-3 opacity-50" />
@@ -39,14 +34,18 @@ export const ResourceStatusBar = memo(function ResourceStatusBar({ compact = fal
39
34
  );
40
35
  }
41
36
 
42
- const { cpu, ramMB, processCount } = latest.total;
37
+ const cpu = latest.system.cpu.total;
38
+ const ramMB = latest.system.mem.usedMB;
39
+ const processCount = latest.system.processCount;
43
40
  const mem = ramMB < 1024 ? `${ramMB.toFixed(0)}M` : `${(ramMB / 1024).toFixed(1)}G`;
44
41
 
45
42
  if (compact) {
46
43
  // Inline segment for the 22px status bar: CPU % · MEM (handoff B2 right cluster).
47
44
  return (
48
45
  <button
49
- onClick={handleClick}
46
+ onClick={openSystemMonitor}
47
+ data-testid="status-bar-resources"
48
+ aria-label="Open System Monitor"
50
49
  className="flex items-center gap-2 px-1 rounded-sm hover:bg-accent/15 transition-colors cursor-pointer"
51
50
  title="Open System Monitor"
52
51
  >
@@ -58,7 +57,9 @@ export const ResourceStatusBar = memo(function ResourceStatusBar({ compact = fal
58
57
 
59
58
  return (
60
59
  <button
61
- onClick={handleClick}
60
+ onClick={openSystemMonitor}
61
+ data-testid="status-bar-resources"
62
+ aria-label="Open System Monitor"
62
63
  className="flex items-center gap-1.5 px-2 py-1 text-[10px] hover:bg-surface-hover transition-colors w-full cursor-pointer"
63
64
  title="Open System Monitor"
64
65
  >
@@ -0,0 +1,90 @@
1
+ import { ArrowUp, ArrowDown } from "lucide-react";
2
+ import { cn } from "@/lib/utils";
3
+ import type { SortDir, SortKey } from "../../../types/system-metrics";
4
+ import type { ResizableColumnKey } from "./process-columns-grid";
5
+
6
+ export interface ColumnResizeHandlers {
7
+ onResizeStart: (key: ResizableColumnKey, e: { clientX: number; preventDefault: () => void }) => void;
8
+ onResizeReset: (key: ResizableColumnKey) => void;
9
+ }
10
+
11
+ /** Sortable column header shared by the process table toolbar. Renders as a
12
+ * `columnheader` `<div>`, not a `<th>` — the parent row is a CSS-grid
13
+ * `<div role="row">`, and a `<th>` inside a non-table ancestor both triggers React's
14
+ * DOM-nesting warning and makes `aria-sort` meaningless to assistive tech outside
15
+ * an actual table. */
16
+ export function SortableHeader({
17
+ label,
18
+ field,
19
+ activeKey,
20
+ activeDir,
21
+ onClick,
22
+ align = "right",
23
+ testId,
24
+ className,
25
+ resizeKey,
26
+ resize,
27
+ }: {
28
+ label: string;
29
+ field: Exclude<SortKey, null>;
30
+ activeKey: SortKey;
31
+ activeDir: SortDir;
32
+ onClick: (field: Exclude<SortKey, null>) => void;
33
+ /** Text/justify alignment — the "Process" column is left-aligned over the name
34
+ * cell, every numeric column stays right-aligned. */
35
+ align?: "left" | "right";
36
+ testId?: string;
37
+ /** Extra classes on the outer `columnheader` — e.g. the `hidden @lg:block`
38
+ * visibility rule an optional (Disk/GPU/Net) column needs below `@lg`. */
39
+ className?: string;
40
+ /** Present for fixed-width columns: renders the drag handle on the right edge. */
41
+ resizeKey?: ResizableColumnKey;
42
+ resize?: ColumnResizeHandlers;
43
+ }) {
44
+ const isActive = activeKey === field;
45
+ const Arrow = isActive ? (activeDir === "asc" ? ArrowUp : ArrowDown) : null;
46
+ const ariaSort = isActive ? (activeDir === "asc" ? "ascending" : "descending") : "none";
47
+
48
+ return (
49
+ <div
50
+ role="columnheader"
51
+ aria-sort={ariaSort}
52
+ className={cn(
53
+ "relative py-1.5 px-2 font-medium select-none",
54
+ align === "left" ? "text-left" : "text-right",
55
+ className,
56
+ )}
57
+ >
58
+ {/* The test id sits on the interactive element: a synthetic `click()` on the
59
+ wrapper never reaches the button (events bubble up, not down), so a harness
60
+ targeting the div would silently not sort. */}
61
+ <button
62
+ type="button"
63
+ data-testid={testId}
64
+ onClick={() => onClick(field)}
65
+ className={cn(
66
+ "flex items-center gap-0.5 w-full min-h-11 md:min-h-0 cursor-pointer hover:text-text-primary transition-colors",
67
+ align === "left" ? "justify-start" : "justify-end",
68
+ isActive && "text-text-primary",
69
+ )}
70
+ >
71
+ <span className="truncate">{label}</span>
72
+ {Arrow && <Arrow className="size-3 shrink-0" />}
73
+ </button>
74
+ {/* Drag handle: pointer-only (hidden below `md`, where the table is a
75
+ single narrow column set and there is nothing worth resizing). Double-click
76
+ returns the column to its default width. */}
77
+ {resizeKey && resize && (
78
+ <div
79
+ role="separator"
80
+ aria-orientation="vertical"
81
+ aria-label={`Resize ${label} column`}
82
+ data-testid={testId ? `${testId}-resize` : undefined}
83
+ onPointerDown={(e) => resize.onResizeStart(resizeKey, e)}
84
+ onDoubleClick={() => resize.onResizeReset(resizeKey)}
85
+ className="hidden md:block absolute top-0 -right-1 h-full w-2 cursor-col-resize hover:bg-primary/40 active:bg-primary/60"
86
+ />
87
+ )}
88
+ </div>
89
+ );
90
+ }