@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.
- package/.spike/s.err +63 -0
- package/.spike/tunnel.err +42 -0
- package/.spike/w.err +96 -0
- package/CHANGELOG.md +16 -0
- package/CLAUDE.md +1 -0
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/http-api.md +5 -3
- package/dist/web/assets/{ai-resource-editor-DZQUyrsU.js → ai-resource-editor-DFCuNe-P.js} +1 -1
- package/dist/web/assets/{angular-html-jfMqUuRd.js → angular-html-Ctz0zN01.js} +1 -1
- package/dist/web/assets/{angular-ts-wytn9PMm.js → angular-ts-QXHpgB1C.js} +1 -1
- package/dist/web/assets/{api-settings-DlcoR5QT.js → api-settings-nblja3Rk.js} +1 -1
- package/dist/web/assets/{apl-i-ahKx6O.js → apl-b9KVk-O4.js} +1 -1
- package/dist/web/assets/architecture-PBZL5I3N-C7ra20CE.js +1 -0
- package/dist/web/assets/{astro-DVBCJfG6.js → astro-BlFEeGYr.js} +1 -1
- package/dist/web/assets/{audio-preview-GGksv6U8.js → audio-preview-CZLmhf__.js} +1 -1
- package/dist/web/assets/{blade-BHlL8SqU.js → blade-CGkj2MUI.js} +1 -1
- package/dist/web/assets/{bsl-D-UOfR1F.js → bsl-CVsbb6ap.js} +1 -1
- package/dist/web/assets/button-BA_fJOtX.js +1 -0
- package/dist/web/assets/{cairo-Bn6rucli.js → cairo-BbIHl2iE.js} +1 -1
- package/dist/web/assets/chat-tab-flMPLoKb.js +15 -0
- package/dist/web/assets/circle-hjUGru6R.js +1 -0
- package/dist/web/assets/circle-question-mark-CzR7YRc-.js +1 -0
- package/dist/web/assets/{cobol-Byn9FYKu.js → cobol-BWSGjmWb.js} +1 -1
- package/dist/web/assets/code-editor-C2VQbXzw.js +10 -0
- package/dist/web/assets/{coffee-DjBl4gm-.js → coffee-CWGNOxds.js} +1 -1
- package/dist/web/assets/{conflict-editor-Dg_JIcKq.js → conflict-editor-CdH_h0vD.js} +3 -3
- package/dist/web/assets/{context-menu-DkQdt6YA.js → context-menu-Cq0u3SK9.js} +1 -1
- package/dist/web/assets/{cpp-CKzic-3E.js → cpp-DHGV24J2.js} +1 -1
- package/dist/web/assets/{crystal-Bkg-Ly_g.js → crystal-Vlwf2UMP.js} +1 -1
- package/dist/web/assets/{csv-preview-DsJ_a2Op.js → csv-preview-CY_454vd.js} +1 -1
- package/dist/web/assets/{data-grid-overlay-editor-B1mTl3KS.js → data-grid-overlay-editor-D9il5DZS.js} +1 -1
- package/dist/web/assets/{database-viewer-CzjnrnMz.js → database-viewer-BCZOTrPT.js} +1 -1
- package/dist/web/assets/{diff-viewer-DUNkO-ll.js → diff-viewer-BwfMN-nW.js} +1 -1
- package/dist/web/assets/{docx-preview-DujpUDkE.js → docx-preview-D3Sdh_aT.js} +1 -1
- package/dist/web/assets/{edge-DVbZnd3Y.js → edge-Bhqk64zS.js} +1 -1
- package/dist/web/assets/{edit-diff-preview-BivQwZMD.js → edit-diff-preview-gq6ALf2B.js} +1 -1
- package/dist/web/assets/{elixir-Dwi8Wu7W.js → elixir-D466WCFm.js} +1 -1
- package/dist/web/assets/{elm-DtIv-HXJ.js → elm-Bfs2qNPR.js} +1 -1
- package/dist/web/assets/{erb-D3HEDz1x.js → erb-WI7jUaB6.js} +1 -1
- package/dist/web/assets/{erlang-2MjTCzGz.js → erlang-BCBe8nCc.js} +1 -1
- package/dist/web/assets/{esm-CZ8B8Ba2.js → esm-CZs9WVDO.js} +1 -1
- package/dist/web/assets/{explorer-body-DSDJUQs7.js → explorer-body-BKOMM566.js} +2 -2
- package/dist/web/assets/{explorer-window-content-CWYBapkj.js → explorer-window-content-Bbzijk8t.js} +1 -1
- package/dist/web/assets/{extension-webview-DBTFznQp.js → extension-webview-CuOQrHIS.js} +1 -1
- package/dist/web/assets/format-bytes-Dk7B73B7.js +1 -0
- package/dist/web/assets/{fortran-fixed-form-BLyAtyPM.js → fortran-fixed-form-CXLIv8Ox.js} +1 -1
- package/dist/web/assets/{fsharp-Bxbn_gbr.js → fsharp-CZsYmiw9.js} +1 -1
- package/dist/web/assets/{gdresource-sFMY4D2Q.js → gdresource-BGRvoWfC.js} +1 -1
- package/dist/web/assets/{git-commit-BzB9Lio5.js → git-commit-DH6mY3Km.js} +1 -1
- package/dist/web/assets/{git-log-panel-D8ZQdoYl.js → git-log-panel-DcV7PhqW.js} +1 -1
- package/dist/web/assets/{git-rebase-CKSVd848.js → git-rebase-C5Gql6Ma.js} +1 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-D4hYLNJU.js +1 -0
- package/dist/web/assets/{glide-data-grid-uIjdTT7c.js → glide-data-grid-Cehfgrzc.js} +7 -7
- package/dist/web/assets/{glimmer-js-BY8aExAJ.js → glimmer-js-1-6JMJlj.js} +1 -1
- package/dist/web/assets/{glimmer-ts-Bak54dBX.js → glimmer-ts-C_Njj0nK.js} +1 -1
- package/dist/web/assets/{glsl-nR2eaJQe.js → glsl-DbkxE1TN.js} +1 -1
- package/dist/web/assets/{graphql-CGPPFAU6.js → graphql-BK75fiXl.js} +1 -1
- package/dist/web/assets/group-chat-tab-BVPYxjz-.js +1 -0
- package/dist/web/assets/{hack-CXIMX-Ol.js → hack-DG151vit.js} +1 -1
- package/dist/web/assets/{haml-tPY-9Pfm.js → haml-DKeIPQWM.js} +1 -1
- package/dist/web/assets/{handlebars-BuW1LT7T.js → handlebars-398uCI13.js} +1 -1
- package/dist/web/assets/{html-bgVcwZ-t.js → html-NLWdst5q.js} +1 -1
- package/dist/web/assets/{html-derivative-D6-IxTgn.js → html-derivative-CJf_Le2z.js} +1 -1
- package/dist/web/assets/{http-CJ1zyB-h.js → http-G1K2FozA.js} +1 -1
- package/dist/web/assets/{hurl-CmoT7l3T.js → hurl-WDC6sSBz.js} +1 -1
- package/dist/web/assets/{hxml-CztOsL8o.js → hxml-Dc3jBXuf.js} +1 -1
- package/dist/web/assets/{image-preview-B0VXSpYu.js → image-preview-D-Ok10eZ.js} +1 -1
- package/dist/web/assets/index-CerSxGdf.js +52 -0
- package/dist/web/assets/index-DRA_OpWY.css +2 -0
- package/dist/web/assets/info-3K5VOQVL-lRlrTlkb.js +1 -0
- package/dist/web/assets/{jinja-B1pq3jJq.js → jinja-CWsQj2y0.js} +1 -1
- package/dist/web/assets/{jison-D8B5pCwA.js → jison-CciJg2NW.js} +1 -1
- package/dist/web/assets/{julia-D0K3bwpU.js → julia-IOQNJAB7.js} +1 -1
- package/dist/web/assets/{just-B9Jlddu-.js → just-BGdHchwS.js} +1 -1
- package/dist/web/assets/{keybindings-store-FyolpNND.js → keybindings-store-aIY40k2o.js} +1 -1
- package/dist/web/assets/{latex-BPJSSE6j.js → latex-D6TOl-L2.js} +1 -1
- package/dist/web/assets/{liquid-lv10fo4U.js → liquid-CVSvu_Wn.js} +1 -1
- package/dist/web/assets/{lua-PNuaIBEF.js → lua-CcKiU6HW.js} +1 -1
- package/dist/web/assets/markdown-renderer-I89kyQhe.js +1 -0
- package/dist/web/assets/{markdown-renderer-BaBQ6Wm6.js → markdown-renderer-pVzBdkpl.js} +3 -3
- package/dist/web/assets/{marko-Du3frD6X.js → marko--UOicMGo.js} +1 -1
- package/dist/web/assets/{mdc-BeDVcFRl.js → mdc-D690aU2C.js} +1 -1
- package/dist/web/assets/media-url-CylYQld1.js +1 -0
- package/dist/web/assets/{mobile-explorer-sheet-Zxjl-e4c.js → mobile-explorer-sheet-5Uj9ZMM9.js} +1 -1
- package/dist/web/assets/{nextflow-DkcXP71s.js → nextflow-DR8PhpF8.js} +1 -1
- package/dist/web/assets/{nginx-C5n8N_bt.js → nginx-Qb9pUk1g.js} +1 -1
- package/dist/web/assets/{nim-CIhyfs-A.js → nim-DLa8R3NS.js} +1 -1
- package/dist/web/assets/{notification-store-DnGpxgkF.js → notification-store-DJ-OtAG3.js} +1 -1
- package/dist/web/assets/{number-overlay-editor-NgOsWJ7x.js → number-overlay-editor-D9SkFg1Y.js} +1 -1
- package/dist/web/assets/overview-panel-Cgi3UPY1.js +1 -0
- package/dist/web/assets/packet-RMMSAZCW-BIhk1mvp.js +1 -0
- package/dist/web/assets/{pdf-preview-xzAA4-kD.js → pdf-preview-Di5xHFyT.js} +1 -1
- package/dist/web/assets/{perl-Cf31sZYE.js → perl-AMNGIneF.js} +1 -1
- package/dist/web/assets/{php-Dzl_MDIW.js → php-CDsOOxXn.js} +1 -1
- package/dist/web/assets/pie-UPGHQEXC-SLS6i76l.js +1 -0
- package/dist/web/assets/{postgres-viewer-Dkec6GyK.js → postgres-viewer-CR6VpTrX.js} +3 -3
- package/dist/web/assets/process-table-DL6shbzt.js +1 -0
- package/dist/web/assets/{pug-CxSYHrB3.js → pug-C2kdkhQ6.js} +1 -1
- package/dist/web/assets/{qml-DlEjGhwN.js → qml-DRDkUp75.js} +1 -1
- package/dist/web/assets/radar-KQ55EAFF-JJ6O1Er_.js +1 -0
- package/dist/web/assets/{razor-KVt5uW14.js → razor-wY_6wUeC.js} +1 -1
- package/dist/web/assets/{rst-D5BwNTnw.js → rst-BRpofyNs.js} +1 -1
- package/dist/web/assets/{ruby-D5fejQwd.js → ruby-ieATBhWm.js} +1 -1
- package/dist/web/assets/{sas-Bj7B1CB2.js → sas-CoOOEbOO.js} +1 -1
- package/dist/web/assets/{scss-BB0CUoCL.js → scss-_nWV0bsb.js} +1 -1
- package/dist/web/assets/{settings-store-C9YT1Hir.js → settings-store-C20lqh0G.js} +2 -2
- package/dist/web/assets/settings-tab-jbiQwozX.js +1 -0
- package/dist/web/assets/{shaderlab-BdjEZUMc.js → shaderlab-XkqfIfO8.js} +1 -1
- package/dist/web/assets/{shellsession-Bp1OA1rR.js → shellsession-BKBIqTlM.js} +1 -1
- package/dist/web/assets/{soy-DlYz3wsC.js → soy-oVDnPzzh.js} +1 -1
- package/dist/web/assets/{sparql-CdfII5Jd.js → sparql-N2VclEsF.js} +1 -1
- package/dist/web/assets/{sql-query-editor-Bz1XrUqI.js → sql-query-editor-BPYsJDsn.js} +1 -1
- package/dist/web/assets/{sqlite-viewer-D5-NZw6b.js → sqlite-viewer-Bq9ZJA2y.js} +1 -1
- package/dist/web/assets/{stata-BvUA6GUW.js → stata-BuuClVDg.js} +1 -1
- package/dist/web/assets/{surrealql--DLNbTyI.js → surrealql-DE5_63MS.js} +1 -1
- package/dist/web/assets/{svelte-CBfSsG4n.js → svelte--YWjlOrK.js} +1 -1
- package/dist/web/assets/system-monitor-body-CKEYWyN9.js +2 -0
- package/dist/web/assets/system-monitor-tab-WjhFFHyM.js +1 -0
- package/dist/web/assets/system-monitor-window-content-CMiISeoC.js +1 -0
- package/dist/web/assets/team-member-sheet-oY5EkH53.js +2 -0
- package/dist/web/assets/{team-member-window-content-DSpZ2zhL.js → team-member-window-content-yCBeI_5X.js} +1 -1
- package/dist/web/assets/{templ-Dv8zpKZW.js → templ-MlpvJx4a.js} +1 -1
- package/dist/web/assets/{terminal-tab-DXazqejW.js → terminal-tab-BxHtMR7h.js} +3 -3
- package/dist/web/assets/{tex-CsrOiqh1.js → tex-0loAoXJG.js} +1 -1
- package/dist/web/assets/{tool-cards-Bgp8iceS.js → tool-cards-BcGrk1zk.js} +5 -5
- package/dist/web/assets/treemap-KZPCXAKY-Be3KNmns.js +1 -0
- package/dist/web/assets/{ts-tags-3T98k4EJ.js → ts-tags-pt-Ug0hK.js} +1 -1
- package/dist/web/assets/{twig-u6QZ45FH.js → twig-DOePpLOL.js} +1 -1
- package/dist/web/assets/{use-monaco-theme-CpF3A7JL.js → use-monaco-theme-CGucu3fb.js} +1 -1
- package/dist/web/assets/{use-open-team-member-CUvV02fA.js → use-open-team-member-DdrRXj-M.js} +1 -1
- package/dist/web/assets/{use-websocket-TnL2I1io.js → use-websocket-C-Rxv8JN.js} +1 -1
- package/dist/web/assets/{vendor-mermaid-Bg4vE8QA.js → vendor-mermaid-DrwG0NYt.js} +1 -1
- package/dist/web/assets/video-preview-DYAbbmd0.js +1 -0
- package/dist/web/assets/{vue-CxIsxtwn.js → vue-D6f-rprj.js} +1 -1
- package/dist/web/assets/{vue-html-BGL5qnuH.js → vue-html-DEYRkS1V.js} +1 -1
- package/dist/web/assets/{vue-vine-DHPh_gMr.js → vue-vine-CxSG2ojf.js} +1 -1
- package/dist/web/assets/{xml-C-vM2m7J.js → xml-DhrxbATj.js} +1 -1
- package/dist/web/assets/{xsl-DvTXNwuO.js → xsl-CU0ZndUO.js} +1 -1
- package/dist/web/index.html +18 -17
- package/dist/web/sw.js +1 -1
- package/docs/system-architecture.md +2 -2
- package/package.json +1 -1
- package/src/server/helpers/media-route-handlers.ts +22 -3
- package/src/server/index.ts +2 -8
- package/src/server/routes/files.ts +5 -2
- package/src/server/routes/fs-browse.ts +5 -2
- package/src/server/routes/resources.ts +119 -73
- package/src/services/autostart-generator.ts +79 -7
- package/src/services/autostart-register.ts +15 -2
- package/src/services/fs-path-guard.service.ts +17 -1
- package/src/services/media-transcode/transcode-stream.ts +27 -5
- package/src/services/proc-table-linux.ts +4 -0
- package/src/services/redact-secrets.ts +33 -0
- package/src/services/system-metrics/cpu-memory-collector.ts +101 -0
- package/src/services/system-metrics/disk-net-collector-darwin.ts +75 -0
- package/src/services/system-metrics/disk-net-collector-linux.ts +88 -0
- package/src/services/system-metrics/disk-net-collector-windows.ts +57 -0
- package/src/services/system-metrics/gpu-collector-nvidia.ts +78 -0
- package/src/services/system-metrics/gpu-process-memory-nvidia.ts +66 -0
- package/src/services/system-metrics/gpu-process-usage-windows.ts +138 -0
- package/src/services/system-metrics/kill-executor.ts +85 -0
- package/src/services/system-metrics/kill-guard.ts +124 -0
- package/src/services/system-metrics/kill-identity-resolver.ts +72 -0
- package/src/services/system-metrics/kill-request-handler.ts +79 -0
- package/src/services/system-metrics/metrics-collector-lock.ts +36 -0
- package/src/services/system-metrics/metrics-poll-scheduler.ts +83 -0
- package/src/services/system-metrics/metrics-subscriber-registry.ts +85 -0
- package/src/services/system-metrics/powershell-session-bootstrap.ts +48 -0
- package/src/services/system-metrics/powershell-session.ts +182 -0
- package/src/services/system-metrics/ppm-process-ownership.ts +34 -0
- package/src/services/system-metrics/ppm-protected-pids.ts +84 -0
- package/src/services/system-metrics/process-collector-darwin.ts +141 -0
- package/src/services/system-metrics/process-collector-linux.ts +85 -0
- package/src/services/system-metrics/process-collector-types.ts +80 -0
- package/src/services/system-metrics/process-collector-windows-parse.ts +153 -0
- package/src/services/system-metrics/process-collector-windows.ts +136 -0
- package/src/services/system-metrics/process-cpu-delta.ts +61 -0
- package/src/services/system-metrics/process-grouping.ts +142 -0
- package/src/services/system-metrics/process-io-delta.ts +84 -0
- package/src/services/system-metrics/process-io-linux.ts +46 -0
- package/src/services/system-metrics/process-net-collector-darwin.ts +103 -0
- package/src/services/system-metrics/process-rows-builder.ts +111 -0
- package/src/services/system-metrics/rate-delta.ts +47 -0
- package/src/services/system-metrics/system-metrics-platform.ts +51 -0
- package/src/services/system-metrics/system-metrics-tick.ts +178 -0
- package/src/services/system-metrics/system-metrics.service.ts +212 -0
- package/src/types/system-metrics.ts +199 -0
- package/src/web/components/editor/video-player/video-player.tsx +54 -22
- package/src/web/components/floating-window/window-content-registry.ts +2 -0
- package/src/web/components/floating-window/window-persistence.ts +1 -1
- package/src/web/components/floating-window/window-store-types.ts +1 -1
- package/src/web/components/system/build-kill-request.ts +9 -0
- package/src/web/components/system/chart-scale.ts +28 -0
- package/src/web/components/system/cpu-core-bars.tsx +33 -0
- package/src/web/components/system/kill-confirm-dialog.tsx +89 -0
- package/src/web/components/system/metric-chart-canvas.tsx +108 -0
- package/src/web/components/system/overview-cards/cpu-card.tsx +39 -0
- package/src/web/components/system/overview-cards/disk-card.tsx +41 -0
- package/src/web/components/system/overview-cards/gpu-card.tsx +33 -0
- package/src/web/components/system/overview-cards/mem-card.tsx +32 -0
- package/src/web/components/system/overview-cards/net-card.tsx +41 -0
- package/src/web/components/system/overview-panel.tsx +97 -0
- package/src/web/components/system/process-columns-grid.ts +93 -0
- package/src/web/components/system/process-group-row.tsx +71 -0
- package/src/web/components/system/process-row-format.ts +56 -0
- package/src/web/components/system/process-row.tsx +82 -0
- package/src/web/components/system/process-table-model.ts +127 -0
- package/src/web/components/system/process-table-sort.ts +90 -0
- package/src/web/components/system/process-table-toolbar.tsx +190 -0
- package/src/web/components/system/process-table-totals.ts +49 -0
- package/src/web/components/system/process-table.tsx +187 -0
- package/src/web/components/system/resolve-open-system-monitor-action.ts +29 -0
- package/src/web/components/system/resource-status-bar.tsx +17 -16
- package/src/web/components/system/sortable-header.tsx +65 -0
- package/src/web/components/system/sparkline-canvas.tsx +8 -9
- package/src/web/components/system/system-monitor-body.tsx +146 -0
- package/src/web/components/system/system-monitor-tab.tsx +2 -185
- package/src/web/components/system/system-monitor-window-content.tsx +18 -0
- package/src/web/components/system/use-open-system-monitor.ts +34 -0
- package/src/web/hooks/resource-monitor-lease.ts +55 -0
- package/src/web/hooks/use-element-width.ts +27 -0
- package/src/web/hooks/use-resource-monitor.ts +113 -35
- package/src/web/lib/format-bytes.ts +16 -0
- package/src/web/lib/media-url.ts +30 -4
- package/.release-run.sh +0 -5
- package/dist/web/assets/architecture-PBZL5I3N-Bs7wzj-W.js +0 -1
- package/dist/web/assets/arrow-right-DubGFkN8.js +0 -1
- package/dist/web/assets/button-B4MWPjWj.js +0 -1
- package/dist/web/assets/chat-tab-Xd2WMjdX.js +0 -15
- package/dist/web/assets/circle-question-mark-CENpx4oA.js +0 -1
- package/dist/web/assets/code-editor-DqXYJWAB.js +0 -10
- package/dist/web/assets/gitGraph-HDMCJU4V-D7i54kbM.js +0 -1
- package/dist/web/assets/group-chat-tab-B3sryFdA.js +0 -1
- package/dist/web/assets/index-DgbOF3xa.js +0 -52
- package/dist/web/assets/index-oxsyfDa0.css +0 -2
- package/dist/web/assets/info-3K5VOQVL-BV41AzR9.js +0 -1
- package/dist/web/assets/markdown-renderer-feiuhJ9n.js +0 -1
- package/dist/web/assets/media-url-CUpN5vI1.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-CaJoP44m.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-DSGZmNw2.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-Be4VUTs0.js +0 -1
- package/dist/web/assets/settings-tab-Bd8e6iqY.js +0 -1
- package/dist/web/assets/system-monitor-tab-A0jvt5Qw.js +0 -1
- package/dist/web/assets/team-member-sheet-5Oaqm8I_.js +0 -2
- package/dist/web/assets/treemap-KZPCXAKY-Cu2zgbxU.js +0 -1
- package/dist/web/assets/video-preview-CwtLPELG.js +0 -1
- package/src/services/resource-monitor-utils.ts +0 -141
- package/src/services/resource-monitor.service.ts +0 -147
- package/src/web/components/system/system-monitor-group-row.tsx +0 -153
- /package/dist/web/assets/{abap-C1K0-wzc.js → abap-MRbmsXOs.js} +0 -0
- /package/dist/web/assets/{actionscript-3-CJhQVjLA.js → actionscript-3-BDDHKqa4.js} +0 -0
- /package/dist/web/assets/{ada-Bt8r9fME.js → ada-DpuV9KwV.js} +0 -0
- /package/dist/web/assets/{andromeeda-DF1I8qi3.js → andromeeda-D6qUCKJo.js} +0 -0
- /package/dist/web/assets/{apache-CnlleE6P.js → apache-CX1NU_Tl.js} +0 -0
- /package/dist/web/assets/{apex-j0C6Xmk6.js → apex-B4-aoQ3K.js} +0 -0
- /package/dist/web/assets/{api-settings-DfNRPr1q.js → api-settings-kQHV6pYZ.js} +0 -0
- /package/dist/web/assets/{api-themes-8WTH6KpV.js → api-themes-CrK0tkW_.js} +0 -0
- /package/dist/web/assets/{applescript-DO7AnO8U.js → applescript-Dm9NI6KR.js} +0 -0
- /package/dist/web/assets/{apply-theme-CNj1iA-v.js → apply-theme-BH_d4amk.js} +0 -0
- /package/dist/web/assets/{ara-i83AydZj.js → ara-BGN8GAYn.js} +0 -0
- /package/dist/web/assets/{asciidoc-DbBA6-sF.js → asciidoc-s_yVuR3t.js} +0 -0
- /package/dist/web/assets/{asm-B5S47Rgr.js → asm-BzQdSvTe.js} +0 -0
- /package/dist/web/assets/{aurora-x-De_IaSKw.js → aurora-x-BJTLETG_.js} +0 -0
- /package/dist/web/assets/{awk-CfyLHXqS.js → awk-BQEGWxvX.js} +0 -0
- /package/dist/web/assets/{ayu-dark-DTLdZ1Si.js → ayu-dark-CpTORmLc.js} +0 -0
- /package/dist/web/assets/{ayu-light-DTOfkzhu.js → ayu-light-D8PVj-e6.js} +0 -0
- /package/dist/web/assets/{ayu-mirage-DsAECCMv.js → ayu-mirage-DyElQHtm.js} +0 -0
- /package/dist/web/assets/{ballerina-CumGp9A7.js → ballerina-C82NkRtj.js} +0 -0
- /package/dist/web/assets/{bat-Ca2SBbYN.js → bat-0X7DtGI-.js} +0 -0
- /package/dist/web/assets/{beancount-CqyXBwwF.js → beancount-Xgvy6YRl.js} +0 -0
- /package/dist/web/assets/{berry-yl-kJr_H.js → berry-CCT2pZcQ.js} +0 -0
- /package/dist/web/assets/{bibtex-DoFFszjV.js → bibtex-CpXgZ9M_.js} +0 -0
- /package/dist/web/assets/{bicep-CWPi4nfK.js → bicep-fkeSA62l.js} +0 -0
- /package/dist/web/assets/{bird2-DXew-ut0.js → bird2-Co7SeAI8.js} +0 -0
- /package/dist/web/assets/{c-clbySDvd.js → c-BpmrTvJh.js} +0 -0
- /package/dist/web/assets/{c3-B65jvSM1.js → c3-BZ_Z0RrR.js} +0 -0
- /package/dist/web/assets/{cadence-Cm8tQTHN.js → cadence-B0GBC8OF.js} +0 -0
- /package/dist/web/assets/{can-open-in-ppm-DXGOSUQc.js → can-open-in-ppm-omBzUBBq.js} +0 -0
- /package/dist/web/assets/{catppuccin-frappe-DLeGslh_.js → catppuccin-frappe-DIt_xR7m.js} +0 -0
- /package/dist/web/assets/{catppuccin-latte-CR5GeHws.js → catppuccin-latte-Dw40AcqA.js} +0 -0
- /package/dist/web/assets/{catppuccin-macchiato-p-XgjxhP.js → catppuccin-macchiato-BJ7DfVEF.js} +0 -0
- /package/dist/web/assets/{catppuccin-mocha-B8QOAZLl.js → catppuccin-mocha-NI2lfXzU.js} +0 -0
- /package/dist/web/assets/{clarity-DPulbvKH.js → clarity-F39L0xMJ.js} +0 -0
- /package/dist/web/assets/{clock-D493FU_D.js → clock-CvhF4DJP.js} +0 -0
- /package/dist/web/assets/{clojure-DFuWS20u.js → clojure-DloMkd8K.js} +0 -0
- /package/dist/web/assets/{cmake-DejCqcu4.js → cmake-CwerJun_.js} +0 -0
- /package/dist/web/assets/{code-CLF5x7KK.js → code-DDPoqVri.js} +0 -0
- /package/dist/web/assets/{codeowners-BwAyqWIH.js → codeowners-CQyVz4Qf.js} +0 -0
- /package/dist/web/assets/{codeql-DgSwFjqI.js → codeql-Bb229zuY.js} +0 -0
- /package/dist/web/assets/{common-lisp-CxIVJCtf.js → common-lisp-KMlIwq5I.js} +0 -0
- /package/dist/web/assets/{copy-BApI9v7Z.js → copy-DKn11Pye.js} +0 -0
- /package/dist/web/assets/{coq-DLSjSnmf.js → coq-DHX_3IIo.js} +0 -0
- /package/dist/web/assets/{csharp-C1HHzXBp.js → csharp-CEmCZv9Q.js} +0 -0
- /package/dist/web/assets/{css-VXsMY--y.js → css-CqZqBD05.js} +0 -0
- /package/dist/web/assets/{csv-BEbcJdHz.js → csv-l1g_V5MV.js} +0 -0
- /package/dist/web/assets/{csv-parser-BRtnJCfv.js → csv-parser-CnS0wqr6.js} +0 -0
- /package/dist/web/assets/{cue-BkDnFqUD.js → cue-BrxRmilg.js} +0 -0
- /package/dist/web/assets/{cypher-1cMqojSQ.js → cypher-rZkKwqZc.js} +0 -0
- /package/dist/web/assets/{d-BnYjRXtH.js → d-BALR-QuP.js} +0 -0
- /package/dist/web/assets/{dark-plus-XfbaH7kZ.js → dark-plus-Cj7rVwh-.js} +0 -0
- /package/dist/web/assets/{dart-Ca7s-8hK.js → dart-CWQcdkXk.js} +0 -0
- /package/dist/web/assets/{data-grid-types-BXwlFMzs.js → data-grid-types-CYvF-xK5.js} +0 -0
- /package/dist/web/assets/{database-B9okYLx6.js → database-BH0urvbs.js} +0 -0
- /package/dist/web/assets/{dax-CmuOw-mY.js → dax-BNHD-QBA.js} +0 -0
- /package/dist/web/assets/{desktop-C2gJ6Ovb.js → desktop-CN0IXPrP.js} +0 -0
- /package/dist/web/assets/{diff-BCEo1Ej7.js → diff-BtOXapES.js} +0 -0
- /package/dist/web/assets/{dist-CUPbqNnL.js → dist-DB1Oaqcc.js} +0 -0
- /package/dist/web/assets/{dist-DOlBnxFX.js → dist-Di6G_5jU.js} +0 -0
- /package/dist/web/assets/{docker-DN2jlyAh.js → docker-DNsAo_qO.js} +0 -0
- /package/dist/web/assets/{dotenv-NExMY2kS.js → dotenv-D6Pl6aOU.js} +0 -0
- /package/dist/web/assets/{download-D9UYwY0-.js → download-zCATy4x4.js} +0 -0
- /package/dist/web/assets/{dracula-B9lbE01y.js → dracula-C3m-w12D.js} +0 -0
- /package/dist/web/assets/{dracula-soft-CMBBfKF_.js → dracula-soft-BYqvXm6Z.js} +0 -0
- /package/dist/web/assets/{dream-maker-DEyDwFsd.js → dream-maker-DZAPbPTi.js} +0 -0
- /package/dist/web/assets/{emacs-lisp-D_qP2zS6.js → emacs-lisp-Ao5SW8ay.js} +0 -0
- /package/dist/web/assets/{everforest-dark-DbHa2U-p.js → everforest-dark-uC8QYotQ.js} +0 -0
- /package/dist/web/assets/{everforest-light-BISkJchP.js → everforest-light-CTgsVNMr.js} +0 -0
- /package/dist/web/assets/{fennel-6B22SfJR.js → fennel-WuBw6IR1.js} +0 -0
- /package/dist/web/assets/{file-exclamation-point-a8f3_w7a.js → file-exclamation-point-COAwgNGw.js} +0 -0
- /package/dist/web/assets/{fish-CubIIvJD.js → fish-Byy9dusu.js} +0 -0
- /package/dist/web/assets/{fluent-DF55zQ09.js → fluent-CDxb_sgw.js} +0 -0
- /package/dist/web/assets/{fortran-free-form-DvOu8jAt.js → fortran-free-form-DKWSTamT.js} +0 -0
- /package/dist/web/assets/{gdscript-DCPxdLpq.js → gdscript-prYHMgtD.js} +0 -0
- /package/dist/web/assets/{gdshader-CTZ381FO.js → gdshader-D-RM-SQk.js} +0 -0
- /package/dist/web/assets/{genie-C_QDtvgU.js → genie-CowkJhej.js} +0 -0
- /package/dist/web/assets/{gherkin-BcvK42tF.js → gherkin-CLFpoVYJ.js} +0 -0
- /package/dist/web/assets/{github-dark-default-CKGVrl3Z.js → github-dark-default-BK_1Qgb8.js} +0 -0
- /package/dist/web/assets/{github-dark-dimmed-C3dQZ_LC.js → github-dark-dimmed-Cv9lj6f-.js} +0 -0
- /package/dist/web/assets/{github-dark-high-contrast-DW78QukY.js → github-dark-high-contrast-CW5ZgIDh.js} +0 -0
- /package/dist/web/assets/{github-dark-C9afs_4w.js → github-dark-nW2F-RLd.js} +0 -0
- /package/dist/web/assets/{github-light-BnP2dznS.js → github-light-D4PqBHGZ.js} +0 -0
- /package/dist/web/assets/{github-light-default-C2fPZzPG.js → github-light-default-B-cHtJJV.js} +0 -0
- /package/dist/web/assets/{github-light-high-contrast-BzIuUFR2.js → github-light-high-contrast-Dt0HJq50.js} +0 -0
- /package/dist/web/assets/{gleam-BpeKwEIO.js → gleam-DwSyXJWP.js} +0 -0
- /package/dist/web/assets/{gn-nUb_Mit0.js → gn-Cv5WEzHc.js} +0 -0
- /package/dist/web/assets/{gnuplot-D7I0v20p.js → gnuplot-D7bRdY_M.js} +0 -0
- /package/dist/web/assets/{go-D7Qqska7.js → go-DiRVJ22U.js} +0 -0
- /package/dist/web/assets/{groovy-DS-pne5-.js → groovy-BHAgLTeO.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-hard-C0W01fsq.js → gruvbox-dark-hard-C8QZ3gzY.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-medium-Bqo6fQbg.js → gruvbox-dark-medium-Dp1eeid2.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-soft-D-XSM_fu.js → gruvbox-dark-soft-Cwq0dWVj.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-hard-IVAwMJRl.js → gruvbox-light-hard-CLQCq2-w.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-medium-38ATiG7i.js → gruvbox-light-medium-APHsh6Mo.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-soft-DnZr3c_0.js → gruvbox-light-soft-CX-fYc64.js} +0 -0
- /package/dist/web/assets/{haskell-uQcywkDH.js → haskell-C4Tw-TDa.js} +0 -0
- /package/dist/web/assets/{haxe-c6bI4_GT.js → haxe-B7fSduTQ.js} +0 -0
- /package/dist/web/assets/{hcl-CQXTiEXq.js → hcl-Bi3ho6yC.js} +0 -0
- /package/dist/web/assets/{hjson-ChETf2bz.js → hjson-BXwae2M1.js} +0 -0
- /package/dist/web/assets/{hlsl-BMC4JGoE.js → hlsl-CRuQLBSa.js} +0 -0
- /package/dist/web/assets/{horizon-BusFlhLW.js → horizon-DtdQ6qjv.js} +0 -0
- /package/dist/web/assets/{horizon-bright-2oD0Mz7W.js → horizon-bright-BXSF_uKq.js} +0 -0
- /package/dist/web/assets/{houston-DdbbjqFg.js → houston-C6ASpUjT.js} +0 -0
- /package/dist/web/assets/{hy-D_SOuqw9.js → hy-BrWBHtHY.js} +0 -0
- /package/dist/web/assets/{image-gallery-CrM5fHKy.js → image-gallery-CGvlv8zR.js} +0 -0
- /package/dist/web/assets/{imba-BxLOHO5I.js → imba-C_JJXckG.js} +0 -0
- /package/dist/web/assets/{ini-ox-CFcg0.js → ini-DEE_vSHQ.js} +0 -0
- /package/dist/web/assets/{java-Bzo8yIal.js → java-CnmpcjcT.js} +0 -0
- /package/dist/web/assets/{javascript-DHuz9VXn.js → javascript-C-M7sa2e.js} +0 -0
- /package/dist/web/assets/{json-0_y80FD5.js → json-BjZ3dAk6.js} +0 -0
- /package/dist/web/assets/{json5-CEQ50pGM.js → json5-BQ2vpqjp.js} +0 -0
- /package/dist/web/assets/{jsonc-CfrLEAKA.js → jsonc-C5MjoWGx.js} +0 -0
- /package/dist/web/assets/{jsonl-fKbrANC2.js → jsonl-JvhrmQJI.js} +0 -0
- /package/dist/web/assets/{jsonnet-DKbkPaQ2.js → jsonnet-C5pdZVuo.js} +0 -0
- /package/dist/web/assets/{jssm-Dxxx1Hqu.js → jssm-Db17uybX.js} +0 -0
- /package/dist/web/assets/{jsx-DlJL-Oj3.js → jsx-tJp2Cyqu.js} +0 -0
- /package/dist/web/assets/{kanagawa-dragon-CwN4SV1c.js → kanagawa-dragon-BculT_Y1.js} +0 -0
- /package/dist/web/assets/{kanagawa-lotus-BHltayiE.js → kanagawa-lotus-yQgHUGwU.js} +0 -0
- /package/dist/web/assets/{kanagawa-wave-D-KXPjw6.js → kanagawa-wave-CyGoWN4d.js} +0 -0
- /package/dist/web/assets/{kdl-DvtoJdFo.js → kdl-Bn8R1REF.js} +0 -0
- /package/dist/web/assets/{kotlin-CTS4MLcx.js → kotlin-DWughK73.js} +0 -0
- /package/dist/web/assets/{kusto-HtSE_sKm.js → kusto--serPb0x.js} +0 -0
- /package/dist/web/assets/{laserwave-DaXZG9ge.js → laserwave-DfAPJ1tt.js} +0 -0
- /package/dist/web/assets/{lean-BYtGUfWx.js → lean-UAm1HOKl.js} +0 -0
- /package/dist/web/assets/{less-BoxmU_Mk.js → less-Xj6Ka0fF.js} +0 -0
- /package/dist/web/assets/{lib-B1clP4ai.js → lib-DgNcCtj3.js} +0 -0
- /package/dist/web/assets/{libesm-ah-mr-sh.js → libesm-CPh1Av0r.js} +0 -0
- /package/dist/web/assets/{light-plus-Bt5CyUuo.js → light-plus-BfS7gPcj.js} +0 -0
- /package/dist/web/assets/{llvm-CSdk9q9V.js → llvm-DvWiVwvU.js} +0 -0
- /package/dist/web/assets/{log-B-kp_3CL.js → log-Bo5z9bNz.js} +0 -0
- /package/dist/web/assets/{logo-DdIsXFDO.js → logo-CrIjcMZT.js} +0 -0
- /package/dist/web/assets/{luau-DUBpLlzQ.js → luau-C9TsYwNt.js} +0 -0
- /package/dist/web/assets/{make-B3JVjoW_.js → make-GYq4qVbx.js} +0 -0
- /package/dist/web/assets/{markdown-Seon0vHs.js → markdown-p5mNledS.js} +0 -0
- /package/dist/web/assets/{material-theme-Nq-ChX1P.js → material-theme-CWYOVxsP.js} +0 -0
- /package/dist/web/assets/{material-theme-darker-CPV4ayXJ.js → material-theme-darker-BDGty7YH.js} +0 -0
- /package/dist/web/assets/{material-theme-lighter-0kyjYqEd.js → material-theme-lighter-JbgOgV3n.js} +0 -0
- /package/dist/web/assets/{material-theme-ocean-DGpAp5co.js → material-theme-ocean-EMOpLpa2.js} +0 -0
- /package/dist/web/assets/{material-theme-palenight-B0AUn0NG.js → material-theme-palenight-CY5hgm7h.js} +0 -0
- /package/dist/web/assets/{matlab-C2waytxs.js → matlab-C-He_NTH.js} +0 -0
- /package/dist/web/assets/{mdx-DAis6R6I.js → mdx-Cr2TR5fj.js} +0 -0
- /package/dist/web/assets/{mermaid-_rnT2YGD.js → mermaid-BYc0-B0U.js} +0 -0
- /package/dist/web/assets/{min-dark-BSSjchUB.js → min-dark-CMJwqJqB.js} +0 -0
- /package/dist/web/assets/{min-light-DomAFQsa.js → min-light-Cx6vFiEX.js} +0 -0
- /package/dist/web/assets/{mipsasm-bBgtvPyG.js → mipsasm-Bjer5HwK.js} +0 -0
- /package/dist/web/assets/{mobile-bottom-sheet-CS3XMwFw.js → mobile-bottom-sheet-BUOJgiaZ.js} +0 -0
- /package/dist/web/assets/{mojo-Cp9BayW0.js → mojo-t90PR-Y2.js} +0 -0
- /package/dist/web/assets/{monokai-CL_9gbmn.js → monokai-dci_PdCm.js} +0 -0
- /package/dist/web/assets/{moonbit-BS_fcr-P.js → moonbit-AAzI-Hd-.js} +0 -0
- /package/dist/web/assets/{move-C79AH45U.js → move-kwBhnhrG.js} +0 -0
- /package/dist/web/assets/{narrat-CJ5s3BDf.js → narrat-CXww2YQL.js} +0 -0
- /package/dist/web/assets/{nextflow-groovy-ZHa4JrPJ.js → nextflow-groovy-CJXsuXGB.js} +0 -0
- /package/dist/web/assets/{night-owl-Jkf9zFQK.js → night-owl-_GD204Wr.js} +0 -0
- /package/dist/web/assets/{night-owl-light-DRPeaG5J.js → night-owl-light-DNgkw3kl.js} +0 -0
- /package/dist/web/assets/{nix-D2Jet9DN.js → nix-BgiorKFd.js} +0 -0
- /package/dist/web/assets/{nord-CREVs22j.js → nord-CaBmcxFC.js} +0 -0
- /package/dist/web/assets/{nushell-CAiDi_mR.js → nushell-DUh4UGx1.js} +0 -0
- /package/dist/web/assets/{objective-c-CVkmJkC1.js → objective-c-Cl9KU86S.js} +0 -0
- /package/dist/web/assets/{objective-cpp-DIKDO1Ly.js → objective-cpp-DVkIA8A0.js} +0 -0
- /package/dist/web/assets/{ocaml-R9qtGQhs.js → ocaml-vvoHTak0.js} +0 -0
- /package/dist/web/assets/{odin-DTYNQqVr.js → odin-Cyjw8woZ.js} +0 -0
- /package/dist/web/assets/{one-dark-pro-BSLWUJn5.js → one-dark-pro-B1cviILi.js} +0 -0
- /package/dist/web/assets/{one-light-DbkRXG3t.js → one-light-BPGUJeYI.js} +0 -0
- /package/dist/web/assets/{openscad-BlPcSnmT.js → openscad-BLMdTUU8.js} +0 -0
- /package/dist/web/assets/{pascal-B1Y46ZZB.js → pascal-i5niy3e7.js} +0 -0
- /package/dist/web/assets/{pkl-BhJSJbFv.js → pkl-CuOV7SsU.js} +0 -0
- /package/dist/web/assets/{plastic-BzxsCTpi.js → plastic-Bf_zE5KL.js} +0 -0
- /package/dist/web/assets/{plsql-DBba7dyP.js → plsql-cfqEtMD3.js} +0 -0
- /package/dist/web/assets/{plus-DmjC2iRB.js → plus-BM-Ty0fp.js} +0 -0
- /package/dist/web/assets/{po-BvgLlnNo.js → po-CFJcWgjr.js} +0 -0
- /package/dist/web/assets/{poimandres-DUaI_1JP.js → poimandres-G5YoaIFf.js} +0 -0
- /package/dist/web/assets/{polar-C7uILwJn.js → polar-rcjs3i9R.js} +0 -0
- /package/dist/web/assets/{postcss-BgJlpFdw.js → postcss-CBKY1FTZ.js} +0 -0
- /package/dist/web/assets/{powerquery-Dn1MIpZu.js → powerquery-Db7SXLbO.js} +0 -0
- /package/dist/web/assets/{powershell-Bo-DYzOS.js → powershell-LFy3MUTP.js} +0 -0
- /package/dist/web/assets/{prisma-CTLs5IdT.js → prisma-BE8GR1lH.js} +0 -0
- /package/dist/web/assets/{prolog-QRGun3eG.js → prolog-DOn5lR1e.js} +0 -0
- /package/dist/web/assets/{proto-B7PI7apn.js → proto-wr-TpAK_.js} +0 -0
- /package/dist/web/assets/{puppet-CBq0tLrP.js → puppet-D2Dkv62u.js} +0 -0
- /package/dist/web/assets/{purescript-DFewOQb2.js → purescript-DvgJgPdy.js} +0 -0
- /package/dist/web/assets/{python-iWuxKXvT.js → python-C7TlkHhK.js} +0 -0
- /package/dist/web/assets/{qmldir-cXiW3AsF.js → qmldir-CtZMwhcW.js} +0 -0
- /package/dist/web/assets/{qss-DASwAbBL.js → qss-dNZ2btnl.js} +0 -0
- /package/dist/web/assets/{r-TU2eaIPw.js → r-BlqnNkHS.js} +0 -0
- /package/dist/web/assets/{racket-SkRKqrLY.js → racket-CzRQrGc4.js} +0 -0
- /package/dist/web/assets/{raku-D31lthkZ.js → raku-BwutWhBF.js} +0 -0
- /package/dist/web/assets/{red-CTcQZevb.js → red-BMXMywmL.js} +0 -0
- /package/dist/web/assets/{reg-D8YAsTGf.js → reg-BqOKrIOw.js} +0 -0
- /package/dist/web/assets/{regexp-CD2uvAWx.js → regexp-Bero1BN2.js} +0 -0
- /package/dist/web/assets/{rel-CAaI-1fg.js → rel-BXKWIElA.js} +0 -0
- /package/dist/web/assets/{resolve-theme-CJvkL8hU.js → resolve-theme-IdhSR-gx.js} +0 -0
- /package/dist/web/assets/{riscv-DR-hJVIj.js → riscv-BbbBYJBo.js} +0 -0
- /package/dist/web/assets/{ron-CuUCJ0n4.js → ron-BtVTWW4b.js} +0 -0
- /package/dist/web/assets/{rose-pine-dawn-Bqz2sBRY.js → rose-pine-dawn-D7lwhUei.js} +0 -0
- /package/dist/web/assets/{rose-pine-aFHxW48i.js → rose-pine-hvkvQzvU.js} +0 -0
- /package/dist/web/assets/{rose-pine-moon-wqyh0an4.js → rose-pine-moon-CoHDmsIw.js} +0 -0
- /package/dist/web/assets/{rosmsg-CI1ywimO.js → rosmsg-CdaZFgI8.js} +0 -0
- /package/dist/web/assets/{run-in-terminal-CGW6o37_.js → run-in-terminal-CyS5Itj-.js} +0 -0
- /package/dist/web/assets/{rust-p7Imk4G_.js → rust-Dy2qsphD.js} +0 -0
- /package/dist/web/assets/{sass-C8JfaqCV.js → sass-Bz7NVxDb.js} +0 -0
- /package/dist/web/assets/{save-DRPrDfTt.js → save-C4z1p51e.js} +0 -0
- /package/dist/web/assets/{scala-DNxCW1By.js → scala-sXSwsNyq.js} +0 -0
- /package/dist/web/assets/{scheme-BYuUPJoL.js → scheme-DS7TUbN7.js} +0 -0
- /package/dist/web/assets/{sdbl-DbPeJPUr.js → sdbl-iISFvIep.js} +0 -0
- /package/dist/web/assets/{send-to-chat-YXHdAyLG.js → send-to-chat-BcO39BDR.js} +0 -0
- /package/dist/web/assets/{shellscript-DMiHlR3q.js → shellscript-BkIl4ApC.js} +0 -0
- /package/dist/web/assets/{shield-check-8GObuUAn.js → shield-check-C5laObJv.js} +0 -0
- /package/dist/web/assets/{shield-off-egKAZEwR.js → shield-off-DULFtyLS.js} +0 -0
- /package/dist/web/assets/{slack-dark-C4xGcQXI.js → slack-dark-B1eg0_m2.js} +0 -0
- /package/dist/web/assets/{slack-ochin-BzgRt_wm.js → slack-ochin-mdkc1ldu.js} +0 -0
- /package/dist/web/assets/{smalltalk-LDeL9PYH.js → smalltalk-CORtd03t.js} +0 -0
- /package/dist/web/assets/{snazzy-light-CXE7a5j_.js → snazzy-light-Bc6Q2G89.js} +0 -0
- /package/dist/web/assets/{solarized-dark-DgUhY74x.js → solarized-dark-CF83zRXM.js} +0 -0
- /package/dist/web/assets/{solarized-light-DD9C-H-9.js → solarized-light-BoKQZaYU.js} +0 -0
- /package/dist/web/assets/{solidity-CAbDB4D4.js → solidity-DOgi1N4w.js} +0 -0
- /package/dist/web/assets/{sparkles-n1hzh65o.js → sparkles-Dqsf3hq6.js} +0 -0
- /package/dist/web/assets/{splunk-kQREPfIc.js → splunk-BXfw5ZLy.js} +0 -0
- /package/dist/web/assets/{sql-CBzeNAD8.js → sql-BcVs-eX4.js} +0 -0
- /package/dist/web/assets/{ssh-config-L1euxrsM.js → ssh-config-CLCtNkkd.js} +0 -0
- /package/dist/web/assets/{stylus-DvBnYniP.js → stylus-DdP992aO.js} +0 -0
- /package/dist/web/assets/{swift-DF5NDQp6.js → swift-BnGb6Lgc.js} +0 -0
- /package/dist/web/assets/{synthwave-84-DbBhB_Hq.js → synthwave-84-cg9264l9.js} +0 -0
- /package/dist/web/assets/{system-verilog-D8s2ZW_k.js → system-verilog-GbHpszs3.js} +0 -0
- /package/dist/web/assets/{systemd-a5-XZJsG.js → systemd-Dz-bNsDQ.js} +0 -0
- /package/dist/web/assets/{table-BX2ZrJfM.js → table-CHmxuh6M.js} +0 -0
- /package/dist/web/assets/{talonscript-BLa0URTW.js → talonscript-CFIidoBA.js} +0 -0
- /package/dist/web/assets/{tasl-DIoV4XcC.js → tasl-Cu-TRTKx.js} +0 -0
- /package/dist/web/assets/{tcl-ztYAdXfQ.js → tcl-DwCHCB1K.js} +0 -0
- /package/dist/web/assets/{terraform-DvpCCiOZ.js → terraform-BzZw4T1z.js} +0 -0
- /package/dist/web/assets/{tokyo-night-BkHlYUv0.js → tokyo-night-RKsj2-tv.js} +0 -0
- /package/dist/web/assets/{toml-acIrxos6.js → toml-CirbOgDP.js} +0 -0
- /package/dist/web/assets/{tsv-BJB5EVCT.js → tsv-CraRcWdU.js} +0 -0
- /package/dist/web/assets/{tsx-B1MmXGT3.js → tsx-CjFg0lgw.js} +0 -0
- /package/dist/web/assets/{turtle-DFceTiqd.js → turtle-B-WBIOa6.js} +0 -0
- /package/dist/web/assets/{typescript-Dz9wU5Y1.js → typescript-MpLarYn1.js} +0 -0
- /package/dist/web/assets/{typespec-CPuYZijj.js → typespec-B7QlHMZ_.js} +0 -0
- /package/dist/web/assets/{typst-CfsCIYv8.js → typst-CcHSKFZj.js} +0 -0
- /package/dist/web/assets/{use-blob-url-BmlYYZ8L.js → use-blob-url-BKyVxOZw.js} +0 -0
- /package/dist/web/assets/{use-is-mobile-B8FA4kQf.js → use-is-mobile-BXGVvczu.js} +0 -0
- /package/dist/web/assets/{v-CGo0jcXA.js → v-xTGhWZuD.js} +0 -0
- /package/dist/web/assets/{vala-AsSR0hrb.js → vala-DwebjH3H.js} +0 -0
- /package/dist/web/assets/{vb-C7tvbXv1.js → vb-BxJT2RAy.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-C1diXHJl.js → vendor-xterm-CU6zIYMB.js} +0 -0
- /package/dist/web/assets/{verilog--a33ND-p.js → verilog-CvV6RHPD.js} +0 -0
- /package/dist/web/assets/{vesper-B_Z0h4pn.js → vesper-CY3qd7E_.js} +0 -0
- /package/dist/web/assets/{vhdl-CWL5dZPN.js → vhdl-B9ZX-sUL.js} +0 -0
- /package/dist/web/assets/{viml-BglmT14Y.js → viml-Y42h_ExQ.js} +0 -0
- /package/dist/web/assets/{vitesse-black-RKFsSqQI.js → vitesse-black-DkXP6Sv-.js} +0 -0
- /package/dist/web/assets/{vitesse-dark-D7zDWNmc.js → vitesse-dark-B9CkIB6r.js} +0 -0
- /package/dist/web/assets/{vitesse-light-MAp87W5b.js → vitesse-light-C7DHrJCK.js} +0 -0
- /package/dist/web/assets/{vyper-CgCBYg1G.js → vyper-Cnd9s5j-.js} +0 -0
- /package/dist/web/assets/{wasm-Bwl4txwp.js → wasm-DQE71XTB.js} +0 -0
- /package/dist/web/assets/{wasm-BOG7ZeTT.js → wasm-iWe7Fzjc.js} +0 -0
- /package/dist/web/assets/{wenyan-DpShPKXZ.js → wenyan-Bc5Pnm9l.js} +0 -0
- /package/dist/web/assets/{wgsl-BakcCblK.js → wgsl-D-YUAWkP.js} +0 -0
- /package/dist/web/assets/{wikitext-NroRWVAO.js → wikitext-DYQDUYf2.js} +0 -0
- /package/dist/web/assets/{wit-B5CM2pg6.js → wit-P6u7mfwy.js} +0 -0
- /package/dist/web/assets/{wolfram-7MTFBJpR.js → wolfram-6SXLUqao.js} +0 -0
- /package/dist/web/assets/{yaml-Bwr01G2K.js → yaml-CQiMLVcZ.js} +0 -0
- /package/dist/web/assets/{zenscript-Dj8GATvi.js → zenscript-DFMywo_P.js} +0 -0
- /package/dist/web/assets/{zig-LAE-fbS-.js → zig-CtAjaIiF.js} +0 -0
|
@@ -1,186 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
Server, Monitor, Bot, Hammer, HelpCircle,
|
|
4
|
-
Wifi, WifiOff,
|
|
5
|
-
} from "lucide-react";
|
|
6
|
-
import { useResourceMonitor, type ResourceGroup } from "@/hooks/use-resource-monitor";
|
|
7
|
-
import { useIsMobile } from "@/hooks/use-is-mobile";
|
|
8
|
-
import { api } from "@/lib/api-client";
|
|
9
|
-
import { toast } from "sonner";
|
|
10
|
-
import { cn } from "@/lib/utils";
|
|
11
|
-
import {
|
|
12
|
-
GroupRow, SortableHeader, cpuColor, formatRam,
|
|
13
|
-
type SortKey, type SortDir,
|
|
14
|
-
} from "./system-monitor-group-row";
|
|
1
|
+
import { SystemMonitorBody } from "./system-monitor-body";
|
|
15
2
|
|
|
16
|
-
const
|
|
17
|
-
server: Server,
|
|
18
|
-
terminal: Monitor,
|
|
19
|
-
"ai-tool": Bot,
|
|
20
|
-
build: Hammer,
|
|
21
|
-
unknown: HelpCircle,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const SPARKLINE_POINTS = 200;
|
|
25
|
-
|
|
26
|
-
function toggleSort(
|
|
27
|
-
current: SortKey, dir: SortDir, clicked: "cpu" | "ram",
|
|
28
|
-
): [SortKey, SortDir] {
|
|
29
|
-
if (current !== clicked) return [clicked, "desc"];
|
|
30
|
-
if (dir === "desc") return [clicked, "asc"];
|
|
31
|
-
return [null, "desc"]; // third click resets
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function sortGroups(groups: ResourceGroup[], key: SortKey, dir: SortDir) {
|
|
35
|
-
if (!key) return groups;
|
|
36
|
-
const sorted = [...groups].sort((a, b) => {
|
|
37
|
-
const av = key === "cpu" ? a.cpu : a.ramMB;
|
|
38
|
-
const bv = key === "cpu" ? b.cpu : b.ramMB;
|
|
39
|
-
return dir === "asc" ? av - bv : bv - av;
|
|
40
|
-
});
|
|
41
|
-
return sorted;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export const SystemMonitorTab = memo(function SystemMonitorTab() {
|
|
45
|
-
const { latest, history, isConnected } = useResourceMonitor();
|
|
46
|
-
const [expanded, setExpanded] = useState<Set<string>>(() => new Set(["server"]));
|
|
47
|
-
const [sortKey, setSortKey] = useState<SortKey>(null);
|
|
48
|
-
const [sortDir, setSortDir] = useState<SortDir>("desc");
|
|
49
|
-
const isMobile = useIsMobile();
|
|
50
|
-
|
|
51
|
-
const groupSparklines = useMemo(() => {
|
|
52
|
-
const map = new Map<string, number[]>();
|
|
53
|
-
const recentHistory = history.slice(-SPARKLINE_POINTS);
|
|
54
|
-
for (const snap of recentHistory) {
|
|
55
|
-
for (const group of snap.groups) {
|
|
56
|
-
const key = `${group.type}:${group.label}`;
|
|
57
|
-
const arr = map.get(key) ?? [];
|
|
58
|
-
arr.push(group.cpu);
|
|
59
|
-
map.set(key, arr);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return map;
|
|
63
|
-
}, [history]);
|
|
64
|
-
|
|
65
|
-
const sortedGroups = useMemo(() => {
|
|
66
|
-
if (!latest) return [];
|
|
67
|
-
return sortGroups(latest.groups, sortKey, sortDir);
|
|
68
|
-
}, [latest, sortKey, sortDir]);
|
|
69
|
-
|
|
70
|
-
const killProcess = useCallback(async (pid: number) => {
|
|
71
|
-
try {
|
|
72
|
-
await api.post(`/api/system/resources/kill/${pid}`);
|
|
73
|
-
toast.success(`Sent SIGTERM to PID ${pid}`);
|
|
74
|
-
} catch (e: any) {
|
|
75
|
-
toast.error(e.message || `Failed to kill PID ${pid}`);
|
|
76
|
-
}
|
|
77
|
-
}, []);
|
|
78
|
-
|
|
79
|
-
const toggle = (key: string) => {
|
|
80
|
-
setExpanded((prev) => {
|
|
81
|
-
const next = new Set(prev);
|
|
82
|
-
if (next.has(key)) next.delete(key);
|
|
83
|
-
else next.add(key);
|
|
84
|
-
return next;
|
|
85
|
-
});
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const handleSort = (clicked: "cpu" | "ram") => {
|
|
89
|
-
const [newKey, newDir] = toggleSort(sortKey, sortDir, clicked);
|
|
90
|
-
setSortKey(newKey);
|
|
91
|
-
setSortDir(newDir);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
if (!latest) {
|
|
95
|
-
return (
|
|
96
|
-
<div className="flex items-center justify-center h-full text-text-subtle text-sm">
|
|
97
|
-
{isConnected ? "Waiting for data..." : "Connecting to resource monitor..."}
|
|
98
|
-
</div>
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const elapsed = Math.round((Date.now() - latest.timestamp) / 1000);
|
|
103
|
-
|
|
104
|
-
return (
|
|
105
|
-
<div className="h-full flex flex-col overflow-hidden">
|
|
106
|
-
{/* Header */}
|
|
107
|
-
<div className="flex items-center justify-between px-3 py-2 border-b border-border shrink-0">
|
|
108
|
-
<h2 className="text-sm font-medium">System Monitor</h2>
|
|
109
|
-
<div className="flex items-center gap-1.5 text-[10px] text-text-subtle">
|
|
110
|
-
{isConnected
|
|
111
|
-
? <Wifi className="size-3 text-success" />
|
|
112
|
-
: <WifiOff className="size-3 text-error" />}
|
|
113
|
-
<span>{isConnected ? `Updated ${elapsed}s ago` : "Disconnected"}</span>
|
|
114
|
-
</div>
|
|
115
|
-
</div>
|
|
116
|
-
|
|
117
|
-
{/* Group list */}
|
|
118
|
-
<div className="flex-1 overflow-y-auto min-h-0">
|
|
119
|
-
<table className="w-full text-xs">
|
|
120
|
-
<thead>
|
|
121
|
-
<tr className="text-text-subtle border-b border-border">
|
|
122
|
-
<th className="text-left py-1.5 px-3 font-medium">Process</th>
|
|
123
|
-
<SortableHeader
|
|
124
|
-
label="CPU"
|
|
125
|
-
field="cpu"
|
|
126
|
-
activeKey={sortKey}
|
|
127
|
-
activeDir={sortDir}
|
|
128
|
-
onClick={handleSort}
|
|
129
|
-
className="w-16"
|
|
130
|
-
/>
|
|
131
|
-
<SortableHeader
|
|
132
|
-
label="RAM"
|
|
133
|
-
field="ram"
|
|
134
|
-
activeKey={sortKey}
|
|
135
|
-
activeDir={sortDir}
|
|
136
|
-
onClick={handleSort}
|
|
137
|
-
className="w-20"
|
|
138
|
-
/>
|
|
139
|
-
{!isMobile && (
|
|
140
|
-
<th className="py-1.5 px-2 font-medium w-[130px]">Trend / Age</th>
|
|
141
|
-
)}
|
|
142
|
-
</tr>
|
|
143
|
-
</thead>
|
|
144
|
-
<tbody>
|
|
145
|
-
{sortedGroups.map((group) => {
|
|
146
|
-
const key = `${group.type}:${group.label}`;
|
|
147
|
-
const Icon = GROUP_ICONS[group.type] ?? HelpCircle;
|
|
148
|
-
const isExpanded = expanded.has(key);
|
|
149
|
-
const sparkData = groupSparklines.get(key) ?? [];
|
|
150
|
-
|
|
151
|
-
return (
|
|
152
|
-
<GroupRow
|
|
153
|
-
key={key}
|
|
154
|
-
group={group}
|
|
155
|
-
Icon={Icon}
|
|
156
|
-
isExpanded={isExpanded}
|
|
157
|
-
sparkData={sparkData}
|
|
158
|
-
isMobile={isMobile}
|
|
159
|
-
sortKey={sortKey}
|
|
160
|
-
sortDir={sortDir}
|
|
161
|
-
onToggle={() => toggle(key)}
|
|
162
|
-
onKill={killProcess}
|
|
163
|
-
/>
|
|
164
|
-
);
|
|
165
|
-
})}
|
|
166
|
-
</tbody>
|
|
167
|
-
{/* Total row */}
|
|
168
|
-
<tfoot>
|
|
169
|
-
<tr className="border-t border-border font-medium">
|
|
170
|
-
<td className="py-1.5 px-3">
|
|
171
|
-
Total ({latest.total.processCount} processes)
|
|
172
|
-
</td>
|
|
173
|
-
<td className={cn("text-right py-1.5 px-2", cpuColor(latest.total.cpu))}>
|
|
174
|
-
{latest.total.cpu.toFixed(1)}%
|
|
175
|
-
</td>
|
|
176
|
-
<td className="text-right py-1.5 px-2 text-text-secondary">
|
|
177
|
-
{formatRam(latest.total.ramMB)}
|
|
178
|
-
</td>
|
|
179
|
-
{!isMobile && <td />}
|
|
180
|
-
</tr>
|
|
181
|
-
</tfoot>
|
|
182
|
-
</table>
|
|
183
|
-
</div>
|
|
184
|
-
</div>
|
|
185
|
-
);
|
|
186
|
-
});
|
|
3
|
+
export const SystemMonitorTab = () => <SystemMonitorBody />;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Floating-window body for the System Monitor. Persists the active sub-tab on the
|
|
2
|
+
* window's payload so a reload restores it. */
|
|
3
|
+
import { useWindowStore } from "@/components/floating-window/window-store";
|
|
4
|
+
import type { WindowContentProps } from "@/components/floating-window/window-content-registry";
|
|
5
|
+
import { SystemMonitorBody } from "./system-monitor-body";
|
|
6
|
+
|
|
7
|
+
export default function SystemMonitorWindowContent({ id, payload }: WindowContentProps) {
|
|
8
|
+
const setPayload = useWindowStore((s) => s.setPayload);
|
|
9
|
+
const initialTab = payload?.tab === "processes" ? "processes" : "overview";
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<SystemMonitorBody
|
|
13
|
+
initialTab={initialTab}
|
|
14
|
+
onTabChange={(tab) => setPayload(id, { tab })}
|
|
15
|
+
variant="window"
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opening the System Monitor on whichever presentation the device has.
|
|
3
|
+
*
|
|
4
|
+
* `WindowLayer` renders nothing below the `md` breakpoint, so `openWindow("system-monitor")`
|
|
5
|
+
* would be a silent no-op on a phone. Desktop gets the floating window; mobile gets the
|
|
6
|
+
* existing `system-monitor` tab route — both host the same `SystemMonitorBody`. On
|
|
7
|
+
* desktop, a second click focuses the already-open window rather than stacking a
|
|
8
|
+
* duplicate — there is only one machine to monitor, so a repeat open is never a
|
|
9
|
+
* distinct instance.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { useCallback } from "react";
|
|
13
|
+
import { useIsMobile } from "@/hooks/use-is-mobile";
|
|
14
|
+
import { useWindowStore } from "@/components/floating-window/window-store";
|
|
15
|
+
import { useTabStore } from "@/stores/tab-store";
|
|
16
|
+
import { resolveOpenSystemMonitorAction } from "./resolve-open-system-monitor-action";
|
|
17
|
+
|
|
18
|
+
/** Callback that opens the System Monitor the right way for this viewport. */
|
|
19
|
+
export function useOpenSystemMonitor(): () => void {
|
|
20
|
+
const isMobile = useIsMobile();
|
|
21
|
+
const openWindow = useWindowStore((s) => s.open);
|
|
22
|
+
const focusWindow = useWindowStore((s) => s.focus);
|
|
23
|
+
const openTab = useTabStore((s) => s.openTab);
|
|
24
|
+
|
|
25
|
+
return useCallback(() => {
|
|
26
|
+
const existing = Object.values(useWindowStore.getState().windows).find(
|
|
27
|
+
(w) => w.kind === "system-monitor",
|
|
28
|
+
);
|
|
29
|
+
const action = resolveOpenSystemMonitorAction(isMobile, existing?.id ?? null);
|
|
30
|
+
if (action.kind === "tab") openTab(action.tab);
|
|
31
|
+
else if (action.kind === "focus") focusWindow(action.id);
|
|
32
|
+
else openWindow("system-monitor");
|
|
33
|
+
}, [isMobile, openWindow, focusWindow, openTab]);
|
|
34
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** Pure/network helpers for `use-resource-monitor.ts`'s subscriber lease and history
|
|
2
|
+
* retention — split out to keep that file under the repo's 200-line guideline and so
|
|
3
|
+
* the lease request shape and retention rule are unit-testable in isolation. */
|
|
4
|
+
import { getAuthToken } from "@/lib/api-client";
|
|
5
|
+
import type { MetricsHistoryPoint } from "../../types/system-metrics";
|
|
6
|
+
|
|
7
|
+
/** Group aggregates are only ever read for the last 60 points (process-table-model's
|
|
8
|
+
* sparklines); retaining them for the full 900-point/30-min history window wastes
|
|
9
|
+
* tens of MB of small objects on a phone for data nothing reads. System aggregates
|
|
10
|
+
* keep the full window. */
|
|
11
|
+
export const GROUPS_RETENTION = 60;
|
|
12
|
+
|
|
13
|
+
/** Same bearer the kill request uses — every route under `/api/*` requires it, and the
|
|
14
|
+
* lease endpoints have no `?token=` fallback (that exists only for the GET-based SSE
|
|
15
|
+
* stream itself, which cannot set headers). Without this, ping/DELETE 401 silently,
|
|
16
|
+
* the server reaps the lease at 30s, and the client reconnects forever. */
|
|
17
|
+
export function authHeaders(): Record<string, string> {
|
|
18
|
+
const token = getAuthToken();
|
|
19
|
+
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Fire-and-forget ping keeping the subscriber lease alive — a missed one just costs
|
|
23
|
+
* one server-side reap cycle. */
|
|
24
|
+
export async function pingLease(sid: string): Promise<void> {
|
|
25
|
+
await fetch(`/api/system/resources/stream/${encodeURIComponent(sid)}/ping`, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
headers: authHeaders(),
|
|
28
|
+
}).catch(() => {});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Best-effort lease teardown — the server-side 30s reap is the real backstop (a proxy
|
|
32
|
+
* can buffer this DELETE away exactly when the client actually disconnected). */
|
|
33
|
+
export async function deleteLease(sid: string): Promise<void> {
|
|
34
|
+
await fetch(`/api/system/resources/stream/${encodeURIComponent(sid)}`, {
|
|
35
|
+
method: "DELETE",
|
|
36
|
+
headers: authHeaders(),
|
|
37
|
+
}).catch(() => {});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Drops `groups` from every history point older than the last `retain` entries.
|
|
41
|
+
* Pure so the retention behaviour is unit-testable without a live EventSource. */
|
|
42
|
+
export function withGroupsRetention(
|
|
43
|
+
history: MetricsHistoryPoint[],
|
|
44
|
+
retain: number,
|
|
45
|
+
): MetricsHistoryPoint[] {
|
|
46
|
+
const cutoff = history.length - retain;
|
|
47
|
+
if (cutoff <= 0) return history;
|
|
48
|
+
let changed = false;
|
|
49
|
+
const next = history.map((point, i) => {
|
|
50
|
+
if (i >= cutoff || Object.keys(point.groups).length === 0) return point;
|
|
51
|
+
changed = true;
|
|
52
|
+
return { ...point, groups: {} };
|
|
53
|
+
});
|
|
54
|
+
return changed ? next : history;
|
|
55
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useEffect, useState, type RefObject } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Live `clientWidth` of an element, tracked through `ResizeObserver`.
|
|
5
|
+
*
|
|
6
|
+
* Canvas charts cannot size themselves with CSS alone — the bitmap needs a pixel
|
|
7
|
+
* width — so a chart inside a resizable card or floating window has to be told how
|
|
8
|
+
* wide its box currently is. Returns 0 until the first measurement.
|
|
9
|
+
*/
|
|
10
|
+
export function useElementWidth(ref: RefObject<HTMLElement | null>): number {
|
|
11
|
+
const [width, setWidth] = useState(0);
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const el = ref.current;
|
|
15
|
+
if (!el) return;
|
|
16
|
+
setWidth(el.clientWidth);
|
|
17
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
18
|
+
const observer = new ResizeObserver((entries) => {
|
|
19
|
+
const next = Math.floor(entries[0]?.contentRect.width ?? el.clientWidth);
|
|
20
|
+
setWidth((prev) => (prev === next ? prev : next));
|
|
21
|
+
});
|
|
22
|
+
observer.observe(el);
|
|
23
|
+
return () => observer.disconnect();
|
|
24
|
+
}, [ref]);
|
|
25
|
+
|
|
26
|
+
return width;
|
|
27
|
+
}
|
|
@@ -1,67 +1,115 @@
|
|
|
1
1
|
import { useEffect, useRef, useState, useCallback } from "react";
|
|
2
2
|
import { getAuthToken } from "@/lib/api-client";
|
|
3
|
+
import type { MetricsHistoryPoint, MetricsSnapshot } from "../../types/system-metrics";
|
|
4
|
+
import { METRICS_HISTORY_MAX, METRICS_PING_INTERVAL_MS } from "../../types/system-metrics";
|
|
5
|
+
import { GROUPS_RETENTION, pingLease, deleteLease, withGroupsRetention } from "./resource-monitor-lease";
|
|
3
6
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export interface ResourceGroup {
|
|
7
|
-
type: "server" | "terminal" | "ai-tool" | "build" | "unknown";
|
|
8
|
-
label: string;
|
|
9
|
-
cpu: number;
|
|
10
|
-
ramMB: number;
|
|
11
|
-
processes: { pid: number; cpu: number; ramMB: number; startedAt?: number; command: string }[];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface ResourceSnapshot {
|
|
15
|
-
timestamp: number;
|
|
16
|
-
server: { pid: number; cpu: number; ramMB: number };
|
|
17
|
-
total: { cpu: number; ramMB: number; processCount: number };
|
|
18
|
-
groups: ResourceGroup[];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const HISTORY_MAX = 600;
|
|
7
|
+
export { authHeaders, pingLease, deleteLease, withGroupsRetention } from "./resource-monitor-lease";
|
|
22
8
|
|
|
23
9
|
// ── Shared singleton state (multiple components share one EventSource) ─
|
|
10
|
+
//
|
|
11
|
+
// Two ref-counts drive one connection: `refCount` (anyone watching at all) and
|
|
12
|
+
// `processesRefCount` (anyone who opted into the full tier). The *desired* URL is
|
|
13
|
+
// derived from whether the latter is > 0; a mount/unmount that doesn't change that
|
|
14
|
+
// desire is a no-op reconnect-wise — only a change to the desired URL tears down and
|
|
15
|
+
// reconnects the EventSource.
|
|
24
16
|
|
|
25
17
|
let sharedEs: EventSource | null = null;
|
|
26
18
|
let refCount = 0;
|
|
27
|
-
let
|
|
28
|
-
let
|
|
19
|
+
let processesRefCount = 0;
|
|
20
|
+
let connectedProcesses = false; // which URL the live sharedEs was opened with
|
|
21
|
+
let sharedLatest: MetricsSnapshot | null = null;
|
|
22
|
+
let sharedHistory: MetricsHistoryPoint[] = [];
|
|
29
23
|
let sharedConnected = false;
|
|
24
|
+
let sharedSid: string | null = null;
|
|
25
|
+
let sharedTickCount = 0; // snapshot frames received since the current connection opened
|
|
26
|
+
let pingTimer: ReturnType<typeof setInterval> | null = null;
|
|
30
27
|
const listeners = new Set<() => void>();
|
|
31
28
|
|
|
32
29
|
function notify() {
|
|
33
30
|
for (const cb of listeners) cb();
|
|
34
31
|
}
|
|
35
32
|
|
|
36
|
-
function
|
|
37
|
-
if (
|
|
33
|
+
function stopLease() {
|
|
34
|
+
if (pingTimer) {
|
|
35
|
+
clearInterval(pingTimer);
|
|
36
|
+
pingTimer = null;
|
|
37
|
+
}
|
|
38
|
+
const sid = sharedSid;
|
|
39
|
+
sharedSid = null;
|
|
40
|
+
if (sid) void deleteLease(sid);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function startLease(sid: string) {
|
|
44
|
+
sharedSid = sid;
|
|
45
|
+
if (pingTimer) clearInterval(pingTimer);
|
|
46
|
+
pingTimer = setInterval(() => {
|
|
47
|
+
const currentSid = sharedSid;
|
|
48
|
+
if (currentSid) void pingLease(currentSid);
|
|
49
|
+
}, METRICS_PING_INTERVAL_MS);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function desiredUrl(wantProcesses: boolean): string {
|
|
38
53
|
const token = getAuthToken();
|
|
39
|
-
const params =
|
|
40
|
-
|
|
54
|
+
const params = new URLSearchParams();
|
|
55
|
+
if (token) params.set("token", token);
|
|
56
|
+
if (wantProcesses) params.set("processes", "1");
|
|
57
|
+
const qs = params.toString();
|
|
58
|
+
return `/api/system/resources/stream${qs ? `?${qs}` : ""}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function connect(wantProcesses: boolean) {
|
|
62
|
+
if (sharedEs) return;
|
|
63
|
+
sharedTickCount = 0;
|
|
64
|
+
const es = new EventSource(desiredUrl(wantProcesses));
|
|
65
|
+
connectedProcesses = wantProcesses;
|
|
66
|
+
|
|
67
|
+
es.addEventListener("session", (e) => {
|
|
68
|
+
try {
|
|
69
|
+
const session: { sid: string } = JSON.parse((e as MessageEvent).data);
|
|
70
|
+
if (session.sid) startLease(session.sid);
|
|
71
|
+
} catch {
|
|
72
|
+
/* an old-shaped or malformed session frame — the snapshot listener is the source of truth */
|
|
73
|
+
}
|
|
74
|
+
});
|
|
41
75
|
|
|
42
76
|
es.addEventListener("snapshot", (e) => {
|
|
43
77
|
try {
|
|
44
|
-
const snapshot:
|
|
78
|
+
const snapshot: MetricsSnapshot = JSON.parse((e as MessageEvent).data);
|
|
45
79
|
sharedLatest = snapshot;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
80
|
+
const point: MetricsHistoryPoint = {
|
|
81
|
+
ts: snapshot.ts,
|
|
82
|
+
system: snapshot.system,
|
|
83
|
+
groups: Object.fromEntries(
|
|
84
|
+
snapshot.groups.map((g) => [g.key, { cpu: g.cpu, ramMB: g.ramMB }]),
|
|
85
|
+
),
|
|
86
|
+
};
|
|
87
|
+
sharedHistory = [...sharedHistory, point];
|
|
88
|
+
if (sharedHistory.length > METRICS_HISTORY_MAX) {
|
|
89
|
+
sharedHistory = sharedHistory.slice(-METRICS_HISTORY_MAX);
|
|
49
90
|
}
|
|
91
|
+
sharedHistory = withGroupsRetention(sharedHistory, GROUPS_RETENTION);
|
|
92
|
+
sharedTickCount++;
|
|
50
93
|
sharedConnected = true;
|
|
51
94
|
notify();
|
|
52
|
-
} catch {
|
|
95
|
+
} catch {
|
|
96
|
+
/* malformed frame — skip this tick, keep the connection */
|
|
97
|
+
}
|
|
53
98
|
});
|
|
54
99
|
|
|
55
100
|
es.onerror = () => {
|
|
56
101
|
sharedConnected = false;
|
|
57
|
-
|
|
102
|
+
stopLease();
|
|
58
103
|
if (sharedEs) {
|
|
59
104
|
sharedEs.close();
|
|
60
105
|
sharedEs = null;
|
|
61
106
|
}
|
|
62
107
|
notify();
|
|
63
108
|
if (refCount > 0) {
|
|
64
|
-
|
|
109
|
+
const wanted = processesRefCount > 0;
|
|
110
|
+
setTimeout(() => {
|
|
111
|
+
if (!sharedEs && refCount > 0) connect(wanted);
|
|
112
|
+
}, 5000);
|
|
65
113
|
}
|
|
66
114
|
};
|
|
67
115
|
|
|
@@ -74,6 +122,7 @@ function connect() {
|
|
|
74
122
|
}
|
|
75
123
|
|
|
76
124
|
function disconnect() {
|
|
125
|
+
stopLease();
|
|
77
126
|
if (sharedEs) {
|
|
78
127
|
sharedEs.close();
|
|
79
128
|
sharedEs = null;
|
|
@@ -82,11 +131,34 @@ function disconnect() {
|
|
|
82
131
|
}
|
|
83
132
|
}
|
|
84
133
|
|
|
134
|
+
/** Reconnect only when the desired tier actually differs from the live connection. */
|
|
135
|
+
function reconcile() {
|
|
136
|
+
const wanted = processesRefCount > 0;
|
|
137
|
+
if (refCount === 0) {
|
|
138
|
+
disconnect();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (!sharedEs) {
|
|
142
|
+
connect(wanted);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (connectedProcesses !== wanted) {
|
|
146
|
+
disconnect();
|
|
147
|
+
connect(wanted);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
85
151
|
// ── Hook ───────────────────────────────────────────────────────────────
|
|
86
152
|
|
|
87
|
-
export
|
|
153
|
+
export interface UseResourceMonitorOptions {
|
|
154
|
+
/** Opt into the full tier: process rows + groups, at the cost of a heavier stream. */
|
|
155
|
+
processes?: boolean;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function useResourceMonitor(opts: UseResourceMonitorOptions = {}) {
|
|
88
159
|
const [, forceUpdate] = useState(0);
|
|
89
160
|
const mounted = useRef(true);
|
|
161
|
+
const wantProcesses = !!opts.processes;
|
|
90
162
|
|
|
91
163
|
const rerender = useCallback(() => {
|
|
92
164
|
if (mounted.current) forceUpdate((n) => n + 1);
|
|
@@ -96,19 +168,25 @@ export function useResourceMonitor() {
|
|
|
96
168
|
mounted.current = true;
|
|
97
169
|
listeners.add(rerender);
|
|
98
170
|
refCount++;
|
|
99
|
-
if (
|
|
171
|
+
if (wantProcesses) processesRefCount++;
|
|
172
|
+
reconcile();
|
|
100
173
|
|
|
101
174
|
return () => {
|
|
102
175
|
mounted.current = false;
|
|
103
176
|
listeners.delete(rerender);
|
|
104
177
|
refCount--;
|
|
105
|
-
if (
|
|
178
|
+
if (wantProcesses) processesRefCount--;
|
|
179
|
+
reconcile();
|
|
106
180
|
};
|
|
107
|
-
|
|
181
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- reconcile reads live module state, not this closure
|
|
182
|
+
}, [rerender, wantProcesses]);
|
|
108
183
|
|
|
109
184
|
return {
|
|
110
185
|
latest: sharedLatest,
|
|
111
186
|
history: sharedHistory,
|
|
112
187
|
isConnected: sharedConnected,
|
|
188
|
+
/** Snapshot frames received since the current connection opened — lets a
|
|
189
|
+
* consumer (or an e2e script) wait past the always-0.0%/n/a first tick. */
|
|
190
|
+
tickCount: sharedTickCount,
|
|
113
191
|
};
|
|
114
192
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Shared byte/rate formatters for the System Monitor. */
|
|
2
|
+
|
|
3
|
+
/** Same rounding rule as the deleted `system-monitor-group-row.tsx`. */
|
|
4
|
+
export function formatRam(mb: number): string {
|
|
5
|
+
return mb < 1024 ? `${mb.toFixed(0)} MB` : `${(mb / 1024).toFixed(1)} GB`;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** Bytes/second → human-readable rate, 1 decimal past B/s. */
|
|
9
|
+
export function formatBps(bytesPerSec: number): string {
|
|
10
|
+
if (bytesPerSec < 1024) return `${bytesPerSec.toFixed(0)} B/s`;
|
|
11
|
+
const kb = bytesPerSec / 1024;
|
|
12
|
+
if (kb < 1024) return `${kb.toFixed(1)} KB/s`;
|
|
13
|
+
const mb = kb / 1024;
|
|
14
|
+
if (mb < 1024) return `${mb.toFixed(1)} MB/s`;
|
|
15
|
+
return `${(mb / 1024).toFixed(1)} GB/s`;
|
|
16
|
+
}
|
package/src/web/lib/media-url.ts
CHANGED
|
@@ -30,10 +30,36 @@ export function rawMediaUrl(filePath: string, projectName: string): string {
|
|
|
30
30
|
return withToken(mediaBase("raw", filePath, projectName));
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Live ffmpeg → fragmented-MP4 stream starting at `start` seconds.
|
|
35
|
+
* `sessionId` identifies the player instance: the server kills that player's previous
|
|
36
|
+
* job before starting this one, so a seek never leaves an orphaned ffmpeg behind —
|
|
37
|
+
* even through proxies (Cloudflare Tunnel) that do not propagate client disconnects.
|
|
38
|
+
*/
|
|
39
|
+
export function transcodeMediaUrl(filePath: string, projectName: string, start = 0, sessionId?: string): string {
|
|
40
|
+
let url = mediaBase("transcode", filePath, projectName);
|
|
41
|
+
if (start > 0) url += `&start=${start.toFixed(3)}`;
|
|
42
|
+
if (sessionId) url += `&sid=${encodeURIComponent(sessionId)}`;
|
|
43
|
+
return withToken(url);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Tell the server the player is gone so its ffmpeg job stops now. `keepalive` lets the
|
|
48
|
+
* request complete even when fired from a page that is unloading.
|
|
49
|
+
*/
|
|
50
|
+
export function stopTranscode(filePath: string, projectName: string, sessionId: string): void {
|
|
51
|
+
const prefix = isExternalPath(filePath) ? "/api/fs" : `${projectUrl(projectName)}/files`;
|
|
52
|
+
const token = getAuthToken();
|
|
53
|
+
void fetch(`${prefix}/transcode?sid=${encodeURIComponent(sessionId)}`, {
|
|
54
|
+
method: "DELETE",
|
|
55
|
+
keepalive: true,
|
|
56
|
+
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
|
57
|
+
}).catch(() => {});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Short random id for one mounted player. */
|
|
61
|
+
export function newMediaSessionId(): string {
|
|
62
|
+
return Math.random().toString(36).slice(2, 10) + Date.now().toString(36);
|
|
37
63
|
}
|
|
38
64
|
|
|
39
65
|
export interface MediaProbeInfo {
|
package/.release-run.sh
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{K as e}from"./vendor-mermaid-Bg4vE8QA.js";export{e as createArchitectureServices};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./createLucideIcon-D8pyde1A.js";var t=e(`arrow-right`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]);export{t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{S as t,x as n}from"./vendor-markdown-Ls5AcU91.js";import{dt as r}from"./vendor-ui-CaeeFO0B.js";import{t as i}from"./createLucideIcon-D8pyde1A.js";import{i as a,n as o}from"./utils-DoY4yTP-.js";var s=i(`circle`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}]]),c=e=>typeof e==`boolean`?`${e}`:e===0?`0`:e,l=a,u=(e,t)=>n=>{if(t?.variants==null)return l(e,n?.class,n?.className);let{variants:r,defaultVariants:i}=t,a=Object.keys(r).map(e=>{let t=n?.[e],a=i?.[e];if(t===null)return null;let o=c(t)||c(a);return r[e][o]}),o=n&&Object.entries(n).reduce((e,t)=>{let[n,r]=t;return r===void 0||(e[n]=r),e},{});return l(e,a,t?.compoundVariants?.reduce((e,t)=>{let{class:n,className:r,...a}=t;return Object.entries(a).every(e=>{let[t,n]=e;return Array.isArray(n)?n.includes({...i,...o}[t]):{...i,...o}[t]===n})?[...e,n,r]:e},[]),n?.class,n?.className)};e(t(),1);var d=n(),f=u(`inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,{variants:{variant:{default:`bg-primary text-primary-foreground hover:bg-primary/90`,destructive:`bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40`,outline:`border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50`,secondary:`bg-secondary text-secondary-foreground hover:bg-secondary/80`,ghost:`hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50`,link:`text-primary underline-offset-4 hover:underline`},size:{default:`h-9 px-4 py-2 has-[>svg]:px-3`,xs:`h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3`,sm:`h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5`,lg:`h-10 rounded-md px-6 has-[>svg]:px-4`,icon:`size-9`,"icon-xs":`size-6 rounded-md [&_svg:not([class*='size-'])]:size-3`,"icon-sm":`size-8`,"icon-lg":`size-10`}},defaultVariants:{variant:`default`,size:`default`}});function p({className:e,variant:t=`default`,size:n=`default`,asChild:i=!1,...a}){return(0,d.jsx)(i?r:`button`,{"data-slot":`button`,"data-variant":t,"data-size":n,className:o(f({variant:t,size:n,className:e})),...a})}export{u as n,s as r,p as t};
|