@hienlh/ppm 0.23.6 → 0.23.7
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/CHANGELOG.md +84 -0
- package/CLAUDE.md +21 -1
- package/Dockerfile.test +8 -1
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/cli-reference.md +4 -4
- package/assets/skills/ppm/references/http-api.md +29 -1
- package/dist/web/assets/accounts-settings-section-BYWnY9hH.js +1 -0
- package/dist/web/assets/accounts-settings-section-BYWnY9hH.js.br +0 -0
- package/dist/web/assets/accounts-settings-section-BYWnY9hH.js.gz +0 -0
- package/dist/web/assets/{ai-resource-editor-Dn_wB-o5.js → ai-resource-editor-CY4n_Ccv.js} +1 -1
- package/dist/web/assets/ai-resource-editor-CY4n_Ccv.js.br +0 -0
- package/dist/web/assets/ai-resource-editor-CY4n_Ccv.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-Bs3iUW4j.js +1 -0
- package/dist/web/assets/ai-settings-section-Bs3iUW4j.js.br +0 -0
- package/dist/web/assets/ai-settings-section-Bs3iUW4j.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-DDs11XV4.js +1 -0
- package/dist/web/assets/api-client-CJPnCOG-.js +1 -0
- package/dist/web/assets/{api-client-c8YOpTlT.js → api-client-D-SMbdiH.js} +1 -1
- package/dist/web/assets/api-client-D-SMbdiH.js.br +0 -0
- package/dist/web/assets/api-client-D-SMbdiH.js.gz +0 -0
- package/dist/web/assets/api-settings-BDkkhFMq.js +1 -0
- package/dist/web/assets/{api-settings-BmvNoCbn.js → api-settings-Bv9mLCty.js} +1 -1
- package/dist/web/assets/api-settings-Bv9mLCty.js.br +0 -0
- package/dist/web/assets/api-settings-Bv9mLCty.js.gz +0 -0
- package/dist/web/assets/{api-themes-6fOQJgM9.js → api-themes-3wW-zLzU.js} +1 -1
- package/dist/web/assets/appearance-settings-section-C0BoIBmz.js +1 -0
- package/dist/web/assets/appearance-settings-section-C0BoIBmz.js.br +0 -0
- package/dist/web/assets/appearance-settings-section-C0BoIBmz.js.gz +0 -0
- package/dist/web/assets/apps-panel-DXAFsveZ.js +1 -0
- package/dist/web/assets/apps-panel-DXAFsveZ.js.br +0 -0
- package/dist/web/assets/apps-panel-DXAFsveZ.js.gz +0 -0
- package/dist/web/assets/{audio-preview-vaG2cB-k.js → audio-preview-BfES4Cx5.js} +1 -1
- package/dist/web/assets/audio-preview-BfES4Cx5.js.br +0 -0
- package/dist/web/assets/audio-preview-BfES4Cx5.js.gz +0 -0
- package/dist/web/assets/branch-review-tab-CA8hPSX9.js +1 -0
- package/dist/web/assets/branch-review-tab-CA8hPSX9.js.br +0 -0
- package/dist/web/assets/branch-review-tab-CA8hPSX9.js.gz +0 -0
- package/dist/web/assets/{button-Ci9EUgqd.js → button-DeAyLH9U.js} +1 -1
- package/dist/web/assets/button-DeAyLH9U.js.br +0 -0
- package/dist/web/assets/button-DeAyLH9U.js.gz +0 -0
- package/dist/web/assets/{chat-preparation-cache-BSIQGiWx.js → chat-preparation-cache-CcCd2g7A.js} +1 -1
- package/dist/web/assets/chat-preparation-cache-CcCd2g7A.js.br +0 -0
- package/dist/web/assets/chat-preparation-cache-CcCd2g7A.js.gz +0 -0
- package/dist/web/assets/chat-tab-BWi_bUzA.js +1 -0
- package/dist/web/assets/chat-tab-BWi_bUzA.js.br +0 -0
- package/dist/web/assets/chat-tab-BWi_bUzA.js.gz +0 -0
- package/dist/web/assets/chat-tab-BvJhIaVE.js +15 -0
- package/dist/web/assets/chat-tab-BvJhIaVE.js.br +0 -0
- package/dist/web/assets/chat-tab-BvJhIaVE.js.gz +0 -0
- package/dist/web/assets/code-editor-OJUdLVnn.js +7 -0
- package/dist/web/assets/code-editor-OJUdLVnn.js.br +0 -0
- package/dist/web/assets/code-editor-OJUdLVnn.js.gz +0 -0
- package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js +1 -0
- package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js.br +0 -0
- package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js.gz +0 -0
- package/dist/web/assets/{conflict-editor-BA3y-qSH.js → conflict-editor-BpKW_vbL.js} +1 -1
- package/dist/web/assets/conflict-editor-BpKW_vbL.js.br +0 -0
- package/dist/web/assets/conflict-editor-BpKW_vbL.js.gz +0 -0
- package/dist/web/assets/context-menu-7OX80HDB.js +1 -0
- package/dist/web/assets/context-menu-7OX80HDB.js.br +0 -0
- package/dist/web/assets/context-menu-7OX80HDB.js.gz +0 -0
- package/dist/web/assets/{csv-preview-BioxkrQF.js → csv-preview-COYdTABa.js} +1 -1
- package/dist/web/assets/csv-preview-COYdTABa.js.br +0 -0
- package/dist/web/assets/csv-preview-COYdTABa.js.gz +0 -0
- package/dist/web/assets/{data-grid-overlay-editor-CQRVKr7y.js → data-grid-overlay-editor-CeZoduke.js} +1 -1
- package/dist/web/assets/data-grid-overlay-editor-CeZoduke.js.br +0 -0
- package/dist/web/assets/data-grid-overlay-editor-CeZoduke.js.gz +0 -0
- package/dist/web/assets/{database-viewer-BSoJ0E6p.js → database-viewer-BQcBqCKm.js} +1 -1
- package/dist/web/assets/database-viewer-BQcBqCKm.js.br +0 -0
- package/dist/web/assets/database-viewer-BQcBqCKm.js.gz +0 -0
- package/dist/web/assets/{design-export-client-ChMcMoqW.js → design-export-client-OrnGCSwu.js} +1 -1
- package/dist/web/assets/design-export-client-OrnGCSwu.js.br +0 -0
- package/dist/web/assets/design-export-client-OrnGCSwu.js.gz +0 -0
- package/dist/web/assets/{design-responsive-dialog-DNBhJJLf.js → design-responsive-dialog-vJjQrC4n.js} +1 -1
- package/dist/web/assets/design-responsive-dialog-vJjQrC4n.js.br +0 -0
- package/dist/web/assets/design-responsive-dialog-vJjQrC4n.js.gz +0 -0
- package/dist/web/assets/design-tab-BbmFk38H.js +33 -0
- package/dist/web/assets/design-tab-BbmFk38H.js.br +0 -0
- package/dist/web/assets/design-tab-BbmFk38H.js.gz +0 -0
- package/dist/web/assets/{designs-sidebar-panel-DHh5QsH9.js → designs-sidebar-panel-D2kXwB8B.js} +1 -1
- package/dist/web/assets/designs-sidebar-panel-D2kXwB8B.js.br +0 -0
- package/dist/web/assets/designs-sidebar-panel-D2kXwB8B.js.gz +0 -0
- package/dist/web/assets/dialog-Bocc0Fgb.js +1 -0
- package/dist/web/assets/dialog-Bocc0Fgb.js.br +0 -0
- package/dist/web/assets/dialog-Bocc0Fgb.js.gz +0 -0
- package/dist/web/assets/{diff-viewer-lctWoSmG.js → diff-viewer-Bj4DT6Mj.js} +1 -1
- package/dist/web/assets/diff-viewer-Bj4DT6Mj.js.br +0 -0
- package/dist/web/assets/diff-viewer-Bj4DT6Mj.js.gz +0 -0
- package/dist/web/assets/{docx-preview-C9XdKEj1.js → docx-preview-C2QqNGRE.js} +1 -1
- package/dist/web/assets/docx-preview-C2QqNGRE.js.br +0 -0
- package/dist/web/assets/docx-preview-C2QqNGRE.js.gz +0 -0
- package/dist/web/assets/editor-language-service-COqB2tuv.js +1 -0
- package/dist/web/assets/editor-language-service-COqB2tuv.js.br +3 -0
- package/dist/web/assets/editor-language-service-COqB2tuv.js.gz +0 -0
- package/dist/web/assets/explorer-body-DGrYajDN.js +2 -0
- package/dist/web/assets/explorer-body-DGrYajDN.js.br +0 -0
- package/dist/web/assets/explorer-body-DGrYajDN.js.gz +0 -0
- package/dist/web/assets/explorer-window-content-DLzkODTP.js +1 -0
- package/dist/web/assets/explorer-window-content-DLzkODTP.js.br +0 -0
- package/dist/web/assets/explorer-window-content-DLzkODTP.js.gz +0 -0
- package/dist/web/assets/{extension-manager-section-rbkXsZVR.js → extension-manager-section-Bu0qcB2i.js} +1 -1
- package/dist/web/assets/extension-manager-section-Bu0qcB2i.js.br +0 -0
- package/dist/web/assets/extension-manager-section-Bu0qcB2i.js.gz +0 -0
- package/dist/web/assets/{extension-webview-uPO0WgCq.js → extension-webview-G_WJ0N52.js} +1 -1
- package/dist/web/assets/extension-webview-G_WJ0N52.js.br +0 -0
- package/dist/web/assets/extension-webview-G_WJ0N52.js.gz +0 -0
- package/dist/web/assets/{file-icons-gx_FBOXY.js → file-icons-l7fNOmdS.js} +1 -1
- package/dist/web/assets/file-icons-l7fNOmdS.js.br +0 -0
- package/dist/web/assets/file-icons-l7fNOmdS.js.gz +0 -0
- package/dist/web/assets/{file-store-D9KE0kQC.js → file-store-B0e7sLag.js} +1 -1
- package/dist/web/assets/file-store-B0e7sLag.js.br +0 -0
- package/dist/web/assets/file-store-B0e7sLag.js.gz +0 -0
- package/dist/web/assets/{files-settings-section-CT7mDb0L.js → files-settings-section-ChZ_CynX.js} +1 -1
- package/dist/web/assets/files-settings-section-ChZ_CynX.js.br +0 -0
- package/dist/web/assets/files-settings-section-ChZ_CynX.js.gz +0 -0
- package/dist/web/assets/format-bytes-__396eCN.js +1 -0
- package/dist/web/assets/{format-file-meta-mQwA6SuY.js → format-file-meta-o1XBuoKS.js} +1 -1
- package/dist/web/assets/format-file-meta-o1XBuoKS.js.br +0 -0
- package/dist/web/assets/format-file-meta-o1XBuoKS.js.gz +0 -0
- package/dist/web/assets/{fs-api-DL36slbd.js → fs-api-CeHKwx95.js} +1 -1
- package/dist/web/assets/fs-api-CeHKwx95.js.br +0 -0
- package/dist/web/assets/fs-api-CeHKwx95.js.gz +0 -0
- package/dist/web/assets/{general-settings-section-DANPfMRN.js → general-settings-section-MSvDEbFa.js} +1 -1
- package/dist/web/assets/general-settings-section-MSvDEbFa.js.br +0 -0
- package/dist/web/assets/general-settings-section-MSvDEbFa.js.gz +0 -0
- package/dist/web/assets/{git-log-panel-BJPkLiEw.js → git-log-panel-gw5_a6j3.js} +1 -1
- package/dist/web/assets/git-log-panel-gw5_a6j3.js.br +0 -0
- package/dist/web/assets/git-log-panel-gw5_a6j3.js.gz +0 -0
- package/dist/web/assets/{git-repo-store-DSypNj19.js → git-repo-store-BpPnah5l.js} +1 -1
- package/dist/web/assets/git-repo-store-BpPnah5l.js.br +0 -0
- package/dist/web/assets/git-repo-store-BpPnah5l.js.gz +0 -0
- package/dist/web/assets/{glide-data-grid-R4PcAntf.js → glide-data-grid-Db2Cl26B.js} +5 -5
- package/dist/web/assets/glide-data-grid-Db2Cl26B.js.br +0 -0
- package/dist/web/assets/glide-data-grid-Db2Cl26B.js.gz +0 -0
- package/dist/web/assets/group-chat-tab-B4etmYTR.js +1 -0
- package/dist/web/assets/group-chat-tab-B4etmYTR.js.br +0 -0
- package/dist/web/assets/group-chat-tab-B4etmYTR.js.gz +0 -0
- package/dist/web/assets/{image-preview-CGdZrmLo.js → image-preview-CjNhpfWw.js} +1 -1
- package/dist/web/assets/index-CtAvmybi.js +52 -0
- package/dist/web/assets/index-CtAvmybi.js.br +0 -0
- package/dist/web/assets/index-CtAvmybi.js.gz +0 -0
- package/dist/web/assets/index-DeCJasyy.css +1 -0
- package/dist/web/assets/index-DeCJasyy.css.br +0 -0
- package/dist/web/assets/index-DeCJasyy.css.gz +0 -0
- package/dist/web/assets/{jira-watcher-section-DHRoyWcG.js → jira-watcher-section-CKSI1Alo.js} +1 -1
- package/dist/web/assets/keybindings-store-C4_yyU4u.js +1 -0
- package/dist/web/assets/{keyboard-shortcuts-section-BKej4mUf.js → keyboard-shortcuts-section-CEaVUc9a.js} +1 -1
- package/dist/web/assets/keyboard-shortcuts-section-CEaVUc9a.js.br +0 -0
- package/dist/web/assets/keyboard-shortcuts-section-CEaVUc9a.js.gz +0 -0
- package/dist/web/assets/language-servers-section-ePtEpnDc.js +2 -0
- package/dist/web/assets/language-servers-section-ePtEpnDc.js.br +0 -0
- package/dist/web/assets/language-servers-section-ePtEpnDc.js.gz +0 -0
- package/dist/web/assets/lsp-client-XzmR3Brr.js +1 -0
- package/dist/web/assets/lsp-client-XzmR3Brr.js.br +0 -0
- package/dist/web/assets/lsp-client-XzmR3Brr.js.gz +0 -0
- package/dist/web/assets/markdown-renderer-CTtDap-l.js +1 -0
- package/dist/web/assets/{markdown-renderer-BHtYqkYZ.js → markdown-renderer-D05fAr57.js} +2 -2
- package/dist/web/assets/markdown-renderer-D05fAr57.js.br +0 -0
- package/dist/web/assets/markdown-renderer-D05fAr57.js.gz +0 -0
- package/dist/web/assets/{media-url-CzUJrREv.js → media-url-C6NumuN5.js} +1 -1
- package/dist/web/assets/metric-chart-canvas-DHJe0VER.js +1 -0
- package/dist/web/assets/metric-chart-canvas-DHJe0VER.js.br +0 -0
- package/dist/web/assets/metric-chart-canvas-DHJe0VER.js.gz +0 -0
- package/dist/web/assets/{mobile-bottom-sheet-CuNi2FRv.js → mobile-bottom-sheet-D4UyOatB.js} +1 -1
- package/dist/web/assets/mobile-bottom-sheet-D4UyOatB.js.br +0 -0
- package/dist/web/assets/mobile-bottom-sheet-D4UyOatB.js.gz +0 -0
- package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js +1 -0
- package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js.br +0 -0
- package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js.gz +0 -0
- package/dist/web/assets/{new-design-dialog-DS_XrpTG.js → new-design-dialog-BgmQopJM.js} +1 -1
- package/dist/web/assets/new-design-dialog-BgmQopJM.js.br +0 -0
- package/dist/web/assets/new-design-dialog-BgmQopJM.js.gz +0 -0
- package/dist/web/assets/notification-store-q5QBklKA.js +1 -0
- package/dist/web/assets/{notifications-settings-section-C05WYqcE.js → notifications-settings-section-BBJ0r9OS.js} +1 -1
- package/dist/web/assets/notifications-settings-section-BBJ0r9OS.js.br +0 -0
- package/dist/web/assets/notifications-settings-section-BBJ0r9OS.js.gz +0 -0
- package/dist/web/assets/{onboarding-entry-CmUqv1kl.js → onboarding-entry-BYOYswsi.js} +1 -1
- package/dist/web/assets/onboarding-entry-BYOYswsi.js.br +0 -0
- package/dist/web/assets/onboarding-entry-BYOYswsi.js.gz +0 -0
- package/dist/web/assets/{onboarding-quick-orientation-DIhWv1CN.js → onboarding-quick-orientation-DPHYFMbA.js} +1 -1
- package/dist/web/assets/onboarding-quick-orientation-DPHYFMbA.js.br +0 -0
- package/dist/web/assets/onboarding-quick-orientation-DPHYFMbA.js.gz +0 -0
- package/dist/web/assets/overview-panel-pkPs44Tv.js +1 -0
- package/dist/web/assets/overview-panel-pkPs44Tv.js.br +0 -0
- package/dist/web/assets/overview-panel-pkPs44Tv.js.gz +0 -0
- package/dist/web/assets/{pdf-preview-qdXmMkOR.js → pdf-preview-c-L_kDAs.js} +1 -1
- package/dist/web/assets/pdf-preview-c-L_kDAs.js.br +0 -0
- package/dist/web/assets/pdf-preview-c-L_kDAs.js.gz +0 -0
- package/dist/web/assets/performance-panel-yPrq0DJV.js +3 -0
- package/dist/web/assets/performance-panel-yPrq0DJV.js.br +0 -0
- package/dist/web/assets/performance-panel-yPrq0DJV.js.gz +0 -0
- package/dist/web/assets/{postgres-viewer-Xvlun_n5.js → postgres-viewer-CnwDCMNd.js} +1 -1
- package/dist/web/assets/postgres-viewer-CnwDCMNd.js.br +0 -0
- package/dist/web/assets/postgres-viewer-CnwDCMNd.js.gz +0 -0
- package/dist/web/assets/{ppmbot-settings-section-D8AES1BA.js → ppmbot-settings-section-BDXoSIDp.js} +1 -1
- package/dist/web/assets/ppmbot-settings-section-BDXoSIDp.js.br +0 -0
- package/dist/web/assets/ppmbot-settings-section-BDXoSIDp.js.gz +0 -0
- package/dist/web/assets/{pptx-export-CG6MRNok.js → pptx-export-D0RDY48h.js} +4 -4
- package/dist/web/assets/pptx-export-D0RDY48h.js.br +0 -0
- package/dist/web/assets/pptx-export-D0RDY48h.js.gz +0 -0
- package/dist/web/assets/{problems-panel-DTBG4beI.js → problems-panel-BgY8oyo9.js} +1 -1
- package/dist/web/assets/problems-panel-BgY8oyo9.js.br +0 -0
- package/dist/web/assets/problems-panel-BgY8oyo9.js.gz +0 -0
- package/dist/web/assets/process-row-format-CaaMcHzn.js +1 -0
- package/dist/web/assets/process-table-BOwDtXuG.js +1 -0
- package/dist/web/assets/process-table-BOwDtXuG.js.br +0 -0
- package/dist/web/assets/process-table-BOwDtXuG.js.gz +0 -0
- package/dist/web/assets/{project-framework-store-XxFXcUpb.js → project-framework-store-UDEMu28U.js} +1 -1
- package/dist/web/assets/{project-store-C5gJXkvb.js → project-store-DGa31y5B.js} +1 -1
- package/dist/web/assets/project-store-DGa31y5B.js.br +0 -0
- package/dist/web/assets/project-store-DGa31y5B.js.gz +0 -0
- package/dist/web/assets/{proxy-settings-section-CqtmbeRj.js → proxy-settings-section-Db6Kc6xG.js} +1 -1
- package/dist/web/assets/proxy-settings-section-Db6Kc6xG.js.br +0 -0
- package/dist/web/assets/proxy-settings-section-Db6Kc6xG.js.gz +0 -0
- package/dist/web/assets/{query-audit-section-UKG_smyt.js → query-audit-section-C0PAXhfT.js} +1 -1
- package/dist/web/assets/query-audit-section-C0PAXhfT.js.br +0 -0
- package/dist/web/assets/query-audit-section-C0PAXhfT.js.gz +0 -0
- package/dist/web/assets/{remote-desktop-clipboard-notice-Djt6cpNL.js → remote-desktop-clipboard-notice-DOVtobj_.js} +1 -1
- package/dist/web/assets/remote-desktop-clipboard-notice-DOVtobj_.js.br +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-DOVtobj_.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js +2 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js +1 -0
- package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js.gz +0 -0
- package/dist/web/assets/{remote-desktop-readiness-gate-DNJF8TcF.js → remote-desktop-readiness-gate-BsfoJzdc.js} +1 -1
- package/dist/web/assets/remote-desktop-readiness-gate-BsfoJzdc.js.br +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-BsfoJzdc.js.gz +0 -0
- package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js +1 -0
- package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js.br +0 -0
- package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js.gz +0 -0
- package/dist/web/assets/{schedules-settings-section-BKoPovy2.js → schedules-settings-section-CvbjQM8z.js} +1 -1
- package/dist/web/assets/schedules-settings-section-CvbjQM8z.js.br +0 -0
- package/dist/web/assets/schedules-settings-section-CvbjQM8z.js.gz +0 -0
- package/dist/web/assets/{scroll-area-XonvWYn_.js → scroll-area-sjOeAfoD.js} +1 -1
- package/dist/web/assets/scroll-area-sjOeAfoD.js.br +0 -0
- package/dist/web/assets/scroll-area-sjOeAfoD.js.gz +0 -0
- package/dist/web/assets/{separator-sQj04Ari.js → separator-9A3PCG1t.js} +1 -1
- package/dist/web/assets/services-panel-CimW47P8.js +1 -0
- package/dist/web/assets/services-panel-CimW47P8.js.br +0 -0
- package/dist/web/assets/services-panel-CimW47P8.js.gz +0 -0
- package/dist/web/assets/settings-body-BTXNtpWL.js +2 -0
- package/dist/web/assets/settings-body-BTXNtpWL.js.br +0 -0
- package/dist/web/assets/settings-body-BTXNtpWL.js.gz +0 -0
- package/dist/web/assets/settings-store-DvftLqzy.js +2 -0
- package/dist/web/assets/settings-store-DvftLqzy.js.br +0 -0
- package/dist/web/assets/settings-store-DvftLqzy.js.gz +0 -0
- package/dist/web/assets/settings-tab-CGhaRXjs.js +1 -0
- package/dist/web/assets/settings-window-content--Uyg_Psr.js +1 -0
- package/dist/web/assets/sortable-header-DUW9T1Hz.js +1 -0
- package/dist/web/assets/sortable-header-DUW9T1Hz.js.br +0 -0
- package/dist/web/assets/sortable-header-DUW9T1Hz.js.gz +0 -0
- package/dist/web/assets/{sql-query-editor-BjIMi9Wk.js → sql-query-editor-Dn-cgDrW.js} +1 -1
- package/dist/web/assets/sql-query-editor-Dn-cgDrW.js.br +0 -0
- package/dist/web/assets/sql-query-editor-Dn-cgDrW.js.gz +0 -0
- package/dist/web/assets/{sqlite-viewer-BNcA6Irq.js → sqlite-viewer-B0NfaMjq.js} +1 -1
- package/dist/web/assets/sqlite-viewer-B0NfaMjq.js.br +0 -0
- package/dist/web/assets/sqlite-viewer-B0NfaMjq.js.gz +0 -0
- package/dist/web/assets/system-monitor-body-CxCfRQFb.js +2 -0
- package/dist/web/assets/system-monitor-body-CxCfRQFb.js.br +0 -0
- package/dist/web/assets/system-monitor-body-CxCfRQFb.js.gz +0 -0
- package/dist/web/assets/system-monitor-tab-Cb3EZUdp.js +1 -0
- package/dist/web/assets/system-monitor-window-content-51CA-2PH.js +1 -0
- package/dist/web/assets/{tab-host-window-content-CIRGNCvi.js → tab-host-window-content-CSrcmKNG.js} +1 -1
- package/dist/web/assets/tab-host-window-content-CSrcmKNG.js.br +0 -0
- package/dist/web/assets/tab-host-window-content-CSrcmKNG.js.gz +0 -0
- package/dist/web/assets/{team-member-sheet-CwXpLi3X.js → team-member-sheet-D4X6nh-x.js} +2 -2
- package/dist/web/assets/team-member-sheet-D4X6nh-x.js.br +0 -0
- package/dist/web/assets/team-member-sheet-D4X6nh-x.js.gz +0 -0
- package/dist/web/assets/{team-member-window-content-4swiiDz7.js → team-member-window-content-BxkbGVIL.js} +1 -1
- package/dist/web/assets/team-member-window-content-BxkbGVIL.js.br +0 -0
- package/dist/web/assets/team-member-window-content-BxkbGVIL.js.gz +0 -0
- package/dist/web/assets/{terminal-tab-BGcdtMMT.js → terminal-tab-BYo34IqU.js} +3 -3
- package/dist/web/assets/terminal-tab-BYo34IqU.js.br +0 -0
- package/dist/web/assets/terminal-tab-BYo34IqU.js.gz +0 -0
- package/dist/web/assets/{tool-cards-D0-krtA2.js → tool-cards-DvXjOped.js} +4 -4
- package/dist/web/assets/tool-cards-DvXjOped.js.br +0 -0
- package/dist/web/assets/tool-cards-DvXjOped.js.gz +0 -0
- package/dist/web/assets/{use-blob-url-CmavyEP8.js → use-blob-url-CISBWKG5.js} +1 -1
- package/dist/web/assets/use-inline-blame-Br6mheS4.js +16 -0
- package/dist/web/assets/use-inline-blame-Br6mheS4.js.br +0 -0
- package/dist/web/assets/use-inline-blame-Br6mheS4.js.gz +0 -0
- package/dist/web/assets/use-lsp-BpJmvQ0n.js +6 -0
- package/dist/web/assets/use-lsp-BpJmvQ0n.js.br +0 -0
- package/dist/web/assets/use-lsp-BpJmvQ0n.js.gz +0 -0
- package/dist/web/assets/{use-monaco-theme-C88KphGx.js → use-monaco-theme-UGOzyIhv.js} +1 -1
- package/dist/web/assets/use-process-kill-CyiiUD1E.js +1 -0
- package/dist/web/assets/use-process-kill-CyiiUD1E.js.br +0 -0
- package/dist/web/assets/use-process-kill-CyiiUD1E.js.gz +0 -0
- package/dist/web/assets/{use-websocket-Chk9guIU.js → use-websocket-Dpl21cHG.js} +1 -1
- package/dist/web/assets/{vendor-ui-BHh12_0v.js → vendor-ui-P9Ym7hCv.js} +1 -1
- package/dist/web/assets/vendor-ui-P9Ym7hCv.js.br +0 -0
- package/dist/web/assets/vendor-ui-P9Ym7hCv.js.gz +0 -0
- package/dist/web/assets/video-preview-D6Jw-IZK.js +1 -0
- package/dist/web/assets/video-preview-D6Jw-IZK.js.br +0 -0
- package/dist/web/assets/video-preview-D6Jw-IZK.js.gz +0 -0
- package/dist/web/assets/voice-settings-section-CcHQDYzN.js +1 -0
- package/dist/web/assets/voice-settings-section-CcHQDYzN.js.br +0 -0
- package/dist/web/assets/voice-settings-section-CcHQDYzN.js.gz +0 -0
- package/dist/web/assets/ws-auth-CqI8-aoA.js +1 -0
- package/dist/web/index.html +20 -20
- package/dist/web/index.html.br +0 -0
- package/dist/web/index.html.gz +0 -0
- package/dist/web/sw.js +1 -1
- package/dist/web/sw.js.br +0 -0
- package/dist/web/sw.js.gz +0 -0
- package/docs/deployment-guide.md +23 -0
- package/package.json +1 -1
- package/release-from-worktree.sh +224 -0
- package/src/cli/commands/config-cmd.ts +12 -0
- package/src/providers/claude-agent-sdk.ts +65 -2
- package/src/providers/codex-app-server/codex-jsonrpc-client.ts +16 -1
- package/src/providers/codex-app-server/codex-provider.ts +39 -7
- package/src/providers/provider-probe.ts +63 -0
- package/src/providers/registry.ts +109 -29
- package/src/server/index.ts +9 -0
- package/src/server/middleware/auth.ts +5 -1
- package/src/server/routes/cross-origin-guard.ts +20 -0
- package/src/server/routes/git.ts +40 -4
- package/src/server/routes/lsp.ts +97 -4
- package/src/server/routes/resources.ts +72 -9
- package/src/server/routes/settings.ts +19 -1
- package/src/server/routes/speech.ts +66 -0
- package/src/server/routes/system-services.ts +76 -0
- package/src/server/routes/tunnel.ts +33 -1
- package/src/server/ws/chat.ts +74 -3
- package/src/services/codex-account-login.ts +26 -2
- package/src/services/codex-reset-credit.service.ts +16 -3
- package/src/services/compaction-savings.ts +127 -0
- package/src/services/db.service.ts +123 -8
- package/src/services/fs-ops/fs-ops-trash.service.ts +22 -9
- package/src/services/git-refs/for-each-ref.ts +118 -0
- package/src/services/git.service.ts +25 -2
- package/src/services/host-info/spawn-runner.ts +48 -4
- package/src/services/jsonl-transcript-parser.ts +7 -42
- package/src/services/lsp/lsp-install.ts +289 -0
- package/src/services/lsp/lsp-manager.ts +160 -29
- package/src/services/lsp/server-registry.ts +120 -4
- package/src/services/named-tunnel/named-tunnel-config.ts +8 -2
- package/src/services/named-tunnel/named-tunnel-setup.service.ts +4 -0
- package/src/services/read-lines.ts +54 -0
- package/src/services/speech-to-text/whisper-catalog.ts +142 -0
- package/src/services/speech-to-text/whisper-download.ts +113 -0
- package/src/services/speech-to-text/whisper-hallucinations.ts +51 -0
- package/src/services/speech-to-text/whisper-install.service.ts +247 -0
- package/src/services/speech-to-text/whisper-paths.ts +62 -0
- package/src/services/speech-to-text/whisper-transcribe.service.ts +117 -0
- package/src/services/supervisor.ts +94 -11
- package/src/services/system-metrics/cpu-details-linux.ts +252 -0
- package/src/services/system-metrics/cpu-memory-collector.ts +140 -18
- package/src/services/system-metrics/device-collector-linux.ts +31 -0
- package/src/services/system-metrics/device-collector-types.ts +40 -0
- package/src/services/system-metrics/disk-devices-linux.ts +156 -0
- package/src/services/system-metrics/disk-inventory-linux.ts +150 -0
- package/src/services/system-metrics/fans-linux.ts +51 -0
- package/src/services/system-metrics/gpu-api-versions.ts +120 -0
- package/src/services/system-metrics/gpu-devices-linux.ts +370 -0
- package/src/services/system-metrics/gpu-fdinfo-linux.ts +253 -0
- package/src/services/system-metrics/hardware-inventory.ts +50 -0
- package/src/services/system-metrics/linux-fs.ts +43 -0
- package/src/services/system-metrics/memory-darwin.ts +91 -0
- package/src/services/system-metrics/memory-linux.ts +156 -0
- package/src/services/system-metrics/net-devices-linux.ts +114 -0
- package/src/services/system-metrics/net-inventory-linux.ts +100 -0
- package/src/services/system-metrics/partitions-linux.ts +158 -0
- package/src/services/system-metrics/process-collector-linux.ts +58 -6
- package/src/services/system-metrics/process-collector-types.ts +8 -1
- package/src/services/system-metrics/process-details-darwin.ts +166 -0
- package/src/services/system-metrics/process-details-linux.ts +150 -0
- package/src/services/system-metrics/process-grouping.ts +2 -1
- package/src/services/system-metrics/process-rows-builder.ts +2 -0
- package/src/services/system-metrics/process-swap-linux.ts +37 -0
- package/src/services/system-metrics/signal-executor.ts +84 -0
- package/src/services/system-metrics/signal-request-handler.ts +92 -0
- package/src/services/system-metrics/system-metrics-platform.ts +30 -4
- package/src/services/system-metrics/system-metrics-tick.ts +73 -4
- package/src/services/system-metrics/system-metrics.service.ts +87 -2
- package/src/services/system-metrics/udev-db.ts +40 -0
- package/src/services/system-services/app-cgroup-linux.ts +115 -0
- package/src/services/system-services/app-icon-service.ts +31 -0
- package/src/services/system-services/app-icons-linux.ts +124 -0
- package/src/services/system-services/apps-linux.ts +174 -0
- package/src/services/system-services/desktop-entry.ts +103 -0
- package/src/services/system-services/service-guard.ts +124 -0
- package/src/services/system-services/systemd-collector.ts +203 -0
- package/src/services/system-services/systemd-parse.ts +162 -0
- package/src/shared/prompt-cache-idle.ts +197 -0
- package/src/shared/turn-usage.ts +85 -1
- package/src/types/chat.ts +27 -0
- package/src/types/config.ts +14 -0
- package/src/types/git.ts +41 -0
- package/src/types/system-hardware.ts +137 -0
- package/src/types/system-metrics.ts +231 -2
- package/src/types/system-services.ts +73 -0
- package/src/web/components/branch-review/branch-review-tab.tsx +20 -20
- package/src/web/components/branch-review/branch-review-tree-row.tsx +1 -13
- package/src/web/components/chat/chat-tab.tsx +3 -0
- package/src/web/components/chat/compaction-divider.tsx +48 -0
- package/src/web/components/chat/idle-cache-notice.tsx +67 -0
- package/src/web/components/chat/message-input.tsx +48 -13
- package/src/web/components/chat/message-list.tsx +15 -0
- package/src/web/components/chat/prompt-cache-chip.tsx +74 -0
- package/src/web/components/editor/code-editor.tsx +1 -0
- package/src/web/components/editor/editor-language-service.tsx +11 -3
- package/src/web/components/editor/lsp-status.tsx +115 -13
- package/src/web/components/git/branch-picker.tsx +419 -0
- package/src/web/components/git/branch-select.tsx +34 -0
- package/src/web/components/git/create-worktree-dialog.tsx +17 -16
- package/src/web/components/git/git-repo-picker.tsx +28 -40
- package/src/web/components/layout/status-bar.tsx +42 -19
- package/src/web/components/settings/accounts/account-card.tsx +5 -1
- package/src/web/components/settings/ai-settings-section.tsx +67 -3
- package/src/web/components/settings/appearance-settings-section.tsx +2 -28
- package/src/web/components/settings/language-servers-section.tsx +362 -0
- package/src/web/components/settings/settings-categories.ts +8 -3
- package/src/web/components/settings/settings-section-content.tsx +2 -0
- package/src/web/components/settings/voice-settings-section.tsx +283 -0
- package/src/web/components/system/apps/app-row.tsx +110 -0
- package/src/web/components/system/apps/app-rows.ts +140 -0
- package/src/web/components/system/apps/apps-panel.tsx +129 -0
- package/src/web/components/system/metric-chart-canvas.tsx +79 -3
- package/src/web/components/system/overview-cards/card-shell.tsx +54 -0
- package/src/web/components/system/overview-cards/cpu-card.tsx +11 -6
- package/src/web/components/system/overview-cards/disk-card.tsx +11 -6
- package/src/web/components/system/overview-cards/gpu-card.tsx +16 -6
- package/src/web/components/system/overview-cards/mem-card.tsx +11 -6
- package/src/web/components/system/overview-cards/net-card.tsx +11 -6
- package/src/web/components/system/overview-device-target.ts +69 -0
- package/src/web/components/system/overview-panel.tsx +15 -1
- package/src/web/components/system/performance/cpu-core-grid.tsx +74 -0
- package/src/web/components/system/performance/cpu-detail.tsx +220 -0
- package/src/web/components/system/performance/detail-parts.tsx +149 -0
- package/src/web/components/system/performance/device-list.ts +139 -0
- package/src/web/components/system/performance/disk-detail.tsx +64 -0
- package/src/web/components/system/performance/fans-detail.tsx +35 -0
- package/src/web/components/system/performance/gpu-detail.tsx +116 -0
- package/src/web/components/system/performance/memory-detail.tsx +109 -0
- package/src/web/components/system/performance/nic-detail.tsx +55 -0
- package/src/web/components/system/performance/partition-list.tsx +79 -0
- package/src/web/components/system/performance/performance-panel.tsx +206 -0
- package/src/web/components/system/performance/use-hardware-inventory.ts +48 -0
- package/src/web/components/system/process-columns-grid.ts +5 -3
- package/src/web/components/system/process-details-dialog.tsx +116 -0
- package/src/web/components/system/process-group-row.tsx +6 -1
- package/src/web/components/system/process-row-format.ts +6 -0
- package/src/web/components/system/process-row-menu.tsx +72 -0
- package/src/web/components/system/process-row.tsx +7 -1
- package/src/web/components/system/process-table-model.ts +1 -1
- package/src/web/components/system/process-table-sort.ts +8 -4
- package/src/web/components/system/process-table-toolbar.tsx +10 -2
- package/src/web/components/system/process-table-totals.ts +3 -0
- package/src/web/components/system/process-table.tsx +25 -2
- package/src/web/components/system/services/service-action-confirm.tsx +100 -0
- package/src/web/components/system/services/service-columns.ts +103 -0
- package/src/web/components/system/services/service-details-sheet.tsx +97 -0
- package/src/web/components/system/services/service-resources.ts +105 -0
- package/src/web/components/system/services/service-row.tsx +146 -0
- package/src/web/components/system/services/service-rows.ts +92 -0
- package/src/web/components/system/services/service-sort.ts +90 -0
- package/src/web/components/system/services/services-header.tsx +51 -0
- package/src/web/components/system/services/services-panel.tsx +207 -0
- package/src/web/components/system/services/use-services.ts +92 -0
- package/src/web/components/system/sortable-header.tsx +13 -8
- package/src/web/components/system/sysmon-preferences.tsx +85 -0
- package/src/web/components/system/system-monitor-body.tsx +101 -43
- package/src/web/components/system/system-monitor-window-content.tsx +2 -3
- package/src/web/components/system/use-process-signal.ts +87 -0
- package/src/web/components/tunnels/public-tunnel-switch.tsx +82 -0
- package/src/web/components/tunnels/tunnel-manager-tab.tsx +4 -0
- package/src/web/components/ui/dialog.tsx +14 -1
- package/src/web/components/ui/search-select.tsx +279 -0
- package/src/web/components/ui/start-ellipsis.tsx +18 -0
- package/src/web/hooks/use-chat.ts +28 -0
- package/src/web/hooks/use-global-keybindings.ts +7 -5
- package/src/web/hooks/use-lsp.ts +23 -2
- package/src/web/hooks/use-minute-clock.ts +20 -0
- package/src/web/hooks/use-whisper-voice-input.ts +113 -0
- package/src/web/lib/api-tunnels.ts +19 -0
- package/src/web/lib/branch-select-items.ts +29 -0
- package/src/web/lib/cpu-graph-mode.ts +90 -0
- package/src/web/lib/format-bytes.ts +14 -0
- package/src/web/lib/git-ref-picker.ts +120 -0
- package/src/web/lib/lsp/lsp-client.ts +32 -0
- package/src/web/lib/search-select-rows.ts +55 -0
- package/src/web/lib/temperature.ts +27 -0
- package/src/web/lib/voice-wav.ts +69 -0
- package/src/web/stores/git-status-store.ts +31 -17
- package/src/web/stores/keybindings-store.ts +14 -1
- package/src/web/stores/settings-store.ts +65 -0
- package/src/web/styles/globals.css +11 -0
- package/dist/web/assets/accounts-settings-section-DUVO32SQ.js +0 -1
- package/dist/web/assets/accounts-settings-section-DUVO32SQ.js.br +0 -0
- package/dist/web/assets/accounts-settings-section-DUVO32SQ.js.gz +0 -0
- package/dist/web/assets/ai-resource-editor-Dn_wB-o5.js.br +0 -0
- package/dist/web/assets/ai-resource-editor-Dn_wB-o5.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-CEbW8jRy.js +0 -1
- package/dist/web/assets/ai-settings-section-CEbW8jRy.js.br +0 -0
- package/dist/web/assets/ai-settings-section-CEbW8jRy.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-D-mwEYFZ.js +0 -1
- package/dist/web/assets/api-client-BgedDTvo.js +0 -1
- package/dist/web/assets/api-client-c8YOpTlT.js.br +0 -0
- package/dist/web/assets/api-client-c8YOpTlT.js.gz +0 -0
- package/dist/web/assets/api-settings-BmvNoCbn.js.br +0 -0
- package/dist/web/assets/api-settings-BmvNoCbn.js.gz +0 -0
- package/dist/web/assets/api-settings-Bti1-Zn3.js +0 -1
- package/dist/web/assets/appearance-settings-section-tw6TpFb6.js +0 -1
- package/dist/web/assets/appearance-settings-section-tw6TpFb6.js.br +0 -0
- package/dist/web/assets/appearance-settings-section-tw6TpFb6.js.gz +0 -0
- package/dist/web/assets/audio-preview-vaG2cB-k.js.br +0 -0
- package/dist/web/assets/audio-preview-vaG2cB-k.js.gz +0 -0
- package/dist/web/assets/branch-review-tab-MBuMWp_i.js +0 -1
- package/dist/web/assets/branch-review-tab-MBuMWp_i.js.br +0 -0
- package/dist/web/assets/branch-review-tab-MBuMWp_i.js.gz +0 -0
- package/dist/web/assets/button-Ci9EUgqd.js.br +0 -0
- package/dist/web/assets/button-Ci9EUgqd.js.gz +0 -0
- package/dist/web/assets/chat-preparation-cache-BSIQGiWx.js.br +0 -0
- package/dist/web/assets/chat-preparation-cache-BSIQGiWx.js.gz +0 -0
- package/dist/web/assets/chat-tab-DVvnqhw6.js +0 -1
- package/dist/web/assets/chat-tab-DVvnqhw6.js.br +0 -0
- package/dist/web/assets/chat-tab-DVvnqhw6.js.gz +0 -0
- package/dist/web/assets/chat-tab-DaEHva22.js +0 -15
- package/dist/web/assets/chat-tab-DaEHva22.js.br +0 -0
- package/dist/web/assets/chat-tab-DaEHva22.js.gz +0 -0
- package/dist/web/assets/code-editor-Bu9lhTVp.js +0 -7
- package/dist/web/assets/code-editor-Bu9lhTVp.js.br +0 -0
- package/dist/web/assets/code-editor-Bu9lhTVp.js.gz +0 -0
- package/dist/web/assets/codex-reset-credit-button-CbmE5mRX.js +0 -1
- package/dist/web/assets/codex-reset-credit-button-CbmE5mRX.js.br +0 -0
- package/dist/web/assets/codex-reset-credit-button-CbmE5mRX.js.gz +0 -0
- package/dist/web/assets/conflict-editor-BA3y-qSH.js.br +0 -0
- package/dist/web/assets/conflict-editor-BA3y-qSH.js.gz +0 -0
- package/dist/web/assets/context-menu-CjYTq8DI.js +0 -1
- package/dist/web/assets/context-menu-CjYTq8DI.js.br +0 -0
- package/dist/web/assets/context-menu-CjYTq8DI.js.gz +0 -0
- package/dist/web/assets/csv-preview-BioxkrQF.js.br +0 -0
- package/dist/web/assets/csv-preview-BioxkrQF.js.gz +0 -0
- package/dist/web/assets/data-grid-overlay-editor-CQRVKr7y.js.br +0 -0
- package/dist/web/assets/data-grid-overlay-editor-CQRVKr7y.js.gz +0 -0
- package/dist/web/assets/database-viewer-BSoJ0E6p.js.br +0 -0
- package/dist/web/assets/database-viewer-BSoJ0E6p.js.gz +0 -0
- package/dist/web/assets/design-export-client-ChMcMoqW.js.br +0 -0
- package/dist/web/assets/design-export-client-ChMcMoqW.js.gz +0 -0
- package/dist/web/assets/design-responsive-dialog-DNBhJJLf.js.br +0 -0
- package/dist/web/assets/design-responsive-dialog-DNBhJJLf.js.gz +0 -0
- package/dist/web/assets/design-tab-iU2CviE3.js +0 -33
- package/dist/web/assets/design-tab-iU2CviE3.js.br +0 -0
- package/dist/web/assets/design-tab-iU2CviE3.js.gz +0 -0
- package/dist/web/assets/designs-sidebar-panel-DHh5QsH9.js.br +0 -0
- package/dist/web/assets/designs-sidebar-panel-DHh5QsH9.js.gz +0 -0
- package/dist/web/assets/dialog-B8clVkyi.js +0 -1
- package/dist/web/assets/dialog-B8clVkyi.js.br +0 -0
- package/dist/web/assets/dialog-B8clVkyi.js.gz +0 -0
- package/dist/web/assets/diff-viewer-lctWoSmG.js.br +0 -0
- package/dist/web/assets/diff-viewer-lctWoSmG.js.gz +0 -0
- package/dist/web/assets/docx-preview-C9XdKEj1.js.br +0 -0
- package/dist/web/assets/docx-preview-C9XdKEj1.js.gz +0 -0
- package/dist/web/assets/editor-language-service-fPG56hQO.js +0 -1
- package/dist/web/assets/editor-language-service-fPG56hQO.js.br +0 -0
- package/dist/web/assets/editor-language-service-fPG56hQO.js.gz +0 -0
- package/dist/web/assets/explorer-body-BgF7FsxI.js +0 -2
- package/dist/web/assets/explorer-body-BgF7FsxI.js.br +0 -0
- package/dist/web/assets/explorer-body-BgF7FsxI.js.gz +0 -0
- package/dist/web/assets/explorer-window-content-C21w_7lf.js +0 -1
- package/dist/web/assets/explorer-window-content-C21w_7lf.js.br +0 -0
- package/dist/web/assets/explorer-window-content-C21w_7lf.js.gz +0 -0
- package/dist/web/assets/extension-manager-section-rbkXsZVR.js.br +0 -0
- package/dist/web/assets/extension-manager-section-rbkXsZVR.js.gz +0 -0
- package/dist/web/assets/extension-webview-uPO0WgCq.js.br +0 -0
- package/dist/web/assets/extension-webview-uPO0WgCq.js.gz +0 -0
- package/dist/web/assets/file-icons-gx_FBOXY.js.br +0 -0
- package/dist/web/assets/file-icons-gx_FBOXY.js.gz +0 -0
- package/dist/web/assets/file-store-D9KE0kQC.js.br +0 -0
- package/dist/web/assets/file-store-D9KE0kQC.js.gz +0 -0
- package/dist/web/assets/files-settings-section-CT7mDb0L.js.br +0 -0
- package/dist/web/assets/files-settings-section-CT7mDb0L.js.gz +0 -0
- package/dist/web/assets/format-bytes-DmSHAKFe.js +0 -1
- package/dist/web/assets/format-file-meta-mQwA6SuY.js.br +0 -0
- package/dist/web/assets/format-file-meta-mQwA6SuY.js.gz +0 -0
- package/dist/web/assets/fs-api-DL36slbd.js.br +0 -0
- package/dist/web/assets/fs-api-DL36slbd.js.gz +0 -0
- package/dist/web/assets/general-settings-section-DANPfMRN.js.br +0 -0
- package/dist/web/assets/general-settings-section-DANPfMRN.js.gz +0 -0
- package/dist/web/assets/git-log-panel-BJPkLiEw.js.br +0 -0
- package/dist/web/assets/git-log-panel-BJPkLiEw.js.gz +0 -0
- package/dist/web/assets/git-repo-store-DSypNj19.js.br +0 -0
- package/dist/web/assets/git-repo-store-DSypNj19.js.gz +0 -0
- package/dist/web/assets/glide-data-grid-R4PcAntf.js.br +0 -0
- package/dist/web/assets/glide-data-grid-R4PcAntf.js.gz +0 -0
- package/dist/web/assets/group-chat-tab-BXMdo8w9.js +0 -1
- package/dist/web/assets/group-chat-tab-BXMdo8w9.js.br +0 -0
- package/dist/web/assets/group-chat-tab-BXMdo8w9.js.gz +0 -0
- package/dist/web/assets/index-C8nGqkKN.js +0 -52
- package/dist/web/assets/index-C8nGqkKN.js.br +0 -0
- package/dist/web/assets/index-C8nGqkKN.js.gz +0 -0
- package/dist/web/assets/index-DvClbTQx.css +0 -1
- package/dist/web/assets/index-DvClbTQx.css.br +0 -0
- package/dist/web/assets/index-DvClbTQx.css.gz +0 -0
- package/dist/web/assets/keybindings-store-BGKlQQAv.js +0 -1
- package/dist/web/assets/keyboard-shortcuts-section-BKej4mUf.js.br +0 -0
- package/dist/web/assets/keyboard-shortcuts-section-BKej4mUf.js.gz +0 -0
- package/dist/web/assets/markdown-renderer-BHtYqkYZ.js.br +0 -0
- package/dist/web/assets/markdown-renderer-BHtYqkYZ.js.gz +0 -0
- package/dist/web/assets/markdown-renderer-vDNuKjel.js +0 -1
- package/dist/web/assets/mobile-bottom-sheet-CuNi2FRv.js.br +0 -0
- package/dist/web/assets/mobile-bottom-sheet-CuNi2FRv.js.gz +0 -0
- package/dist/web/assets/mobile-explorer-sheet-DtvxS7-r.js +0 -1
- package/dist/web/assets/mobile-explorer-sheet-DtvxS7-r.js.br +0 -0
- package/dist/web/assets/mobile-explorer-sheet-DtvxS7-r.js.gz +0 -0
- package/dist/web/assets/new-design-dialog-DS_XrpTG.js.br +0 -0
- package/dist/web/assets/new-design-dialog-DS_XrpTG.js.gz +0 -0
- package/dist/web/assets/notification-store-Dnnj20Ky.js +0 -1
- package/dist/web/assets/notifications-settings-section-C05WYqcE.js.br +0 -0
- package/dist/web/assets/notifications-settings-section-C05WYqcE.js.gz +0 -0
- package/dist/web/assets/onboarding-entry-CmUqv1kl.js.br +0 -0
- package/dist/web/assets/onboarding-entry-CmUqv1kl.js.gz +0 -0
- package/dist/web/assets/onboarding-quick-orientation-DIhWv1CN.js.br +0 -0
- package/dist/web/assets/onboarding-quick-orientation-DIhWv1CN.js.gz +0 -0
- package/dist/web/assets/overview-panel-BZAW_nag.js +0 -1
- package/dist/web/assets/overview-panel-BZAW_nag.js.br +0 -0
- package/dist/web/assets/overview-panel-BZAW_nag.js.gz +0 -0
- package/dist/web/assets/pdf-preview-qdXmMkOR.js.br +0 -0
- package/dist/web/assets/pdf-preview-qdXmMkOR.js.gz +0 -0
- package/dist/web/assets/postgres-viewer-Xvlun_n5.js.br +0 -0
- package/dist/web/assets/postgres-viewer-Xvlun_n5.js.gz +0 -0
- package/dist/web/assets/ppmbot-settings-section-D8AES1BA.js.br +0 -0
- package/dist/web/assets/ppmbot-settings-section-D8AES1BA.js.gz +0 -0
- package/dist/web/assets/pptx-export-CG6MRNok.js.br +0 -0
- package/dist/web/assets/pptx-export-CG6MRNok.js.gz +0 -0
- package/dist/web/assets/problems-panel-DTBG4beI.js.br +0 -0
- package/dist/web/assets/problems-panel-DTBG4beI.js.gz +0 -0
- package/dist/web/assets/process-table-D_gR2XA6.js +0 -1
- package/dist/web/assets/process-table-D_gR2XA6.js.br +0 -0
- package/dist/web/assets/process-table-D_gR2XA6.js.gz +0 -0
- package/dist/web/assets/project-store-C5gJXkvb.js.br +0 -0
- package/dist/web/assets/project-store-C5gJXkvb.js.gz +0 -0
- package/dist/web/assets/proxy-settings-section-CqtmbeRj.js.br +0 -0
- package/dist/web/assets/proxy-settings-section-CqtmbeRj.js.gz +0 -0
- package/dist/web/assets/query-audit-section-UKG_smyt.js.br +0 -0
- package/dist/web/assets/query-audit-section-UKG_smyt.js.gz +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-Djt6cpNL.js.br +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-Djt6cpNL.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-BQxhJUkm.js +0 -2
- package/dist/web/assets/remote-desktop-mobile-sheet-BQxhJUkm.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-BQxhJUkm.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-DGnT8RY7.js +0 -1
- package/dist/web/assets/remote-desktop-mobile-view-DGnT8RY7.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-DGnT8RY7.js.gz +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-DNJF8TcF.js.br +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-DNJF8TcF.js.gz +0 -0
- package/dist/web/assets/remote-desktop-window-content-Ds0DKmM0.js +0 -1
- package/dist/web/assets/remote-desktop-window-content-Ds0DKmM0.js.br +0 -0
- package/dist/web/assets/remote-desktop-window-content-Ds0DKmM0.js.gz +0 -0
- package/dist/web/assets/schedules-settings-section-BKoPovy2.js.br +0 -0
- package/dist/web/assets/schedules-settings-section-BKoPovy2.js.gz +0 -0
- package/dist/web/assets/scroll-area-XonvWYn_.js.br +0 -0
- package/dist/web/assets/scroll-area-XonvWYn_.js.gz +0 -0
- package/dist/web/assets/settings-body-k2qPgRFe.js +0 -2
- package/dist/web/assets/settings-body-k2qPgRFe.js.br +0 -0
- package/dist/web/assets/settings-body-k2qPgRFe.js.gz +0 -0
- package/dist/web/assets/settings-store-Br5c1efC.js +0 -2
- package/dist/web/assets/settings-store-Br5c1efC.js.br +0 -0
- package/dist/web/assets/settings-store-Br5c1efC.js.gz +0 -0
- package/dist/web/assets/settings-tab-Bb23VdBu.js +0 -1
- package/dist/web/assets/settings-window-content-ClarWusz.js +0 -1
- package/dist/web/assets/sql-query-editor-BjIMi9Wk.js.br +0 -0
- package/dist/web/assets/sql-query-editor-BjIMi9Wk.js.gz +0 -0
- package/dist/web/assets/sqlite-viewer-BNcA6Irq.js.br +0 -0
- package/dist/web/assets/sqlite-viewer-BNcA6Irq.js.gz +0 -0
- package/dist/web/assets/system-monitor-body-D0T3ggt2.js +0 -2
- package/dist/web/assets/system-monitor-body-D0T3ggt2.js.br +0 -0
- package/dist/web/assets/system-monitor-body-D0T3ggt2.js.gz +0 -0
- package/dist/web/assets/system-monitor-tab-I1Igmoey.js +0 -1
- package/dist/web/assets/system-monitor-window-content-C5SeUv1H.js +0 -1
- package/dist/web/assets/tab-host-window-content-CIRGNCvi.js.br +0 -0
- package/dist/web/assets/tab-host-window-content-CIRGNCvi.js.gz +0 -0
- package/dist/web/assets/team-member-sheet-CwXpLi3X.js.br +0 -0
- package/dist/web/assets/team-member-sheet-CwXpLi3X.js.gz +0 -0
- package/dist/web/assets/team-member-window-content-4swiiDz7.js.br +0 -0
- package/dist/web/assets/team-member-window-content-4swiiDz7.js.gz +0 -0
- package/dist/web/assets/terminal-tab-BGcdtMMT.js.br +0 -0
- package/dist/web/assets/terminal-tab-BGcdtMMT.js.gz +0 -0
- package/dist/web/assets/tool-cards-D0-krtA2.js.br +0 -0
- package/dist/web/assets/tool-cards-D0-krtA2.js.gz +0 -0
- package/dist/web/assets/use-inline-blame-pKaXyGU-.js +0 -16
- package/dist/web/assets/use-inline-blame-pKaXyGU-.js.br +0 -0
- package/dist/web/assets/use-inline-blame-pKaXyGU-.js.gz +0 -0
- package/dist/web/assets/use-lsp-71azTXQz.js +0 -6
- package/dist/web/assets/use-lsp-71azTXQz.js.br +0 -0
- package/dist/web/assets/use-lsp-71azTXQz.js.gz +0 -0
- package/dist/web/assets/vendor-ui-BHh12_0v.js.br +0 -0
- package/dist/web/assets/vendor-ui-BHh12_0v.js.gz +0 -0
- package/dist/web/assets/video-preview-DxEX-uGo.js +0 -1
- package/dist/web/assets/video-preview-DxEX-uGo.js.br +0 -0
- package/dist/web/assets/video-preview-DxEX-uGo.js.gz +0 -0
- package/dist/web/assets/ws-auth-kXgsX2Js.js +0 -1
- /package/dist/web/assets/{__vite-browser-external-BpSQWxcq.js → __vite-browser-external-BILfYaAs.js} +0 -0
- /package/dist/web/assets/{run-in-terminal-HIdNgYim.js → run-in-terminal-2pSiup8e.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-DLDtzLib.js → vendor-xterm-DF1JTfsy.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-DLDtzLib.js.br → vendor-xterm-DF1JTfsy.js.br} +0 -0
- /package/dist/web/assets/{vendor-xterm-DLDtzLib.js.gz → vendor-xterm-DF1JTfsy.js.gz} +0 -0
|
@@ -8,12 +8,33 @@ export interface MetricSeries {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
interface MetricChartCanvasProps {
|
|
11
|
-
/**
|
|
11
|
+
/** Series drawn on the same axis. Overlaid by default; see `stacked`. */
|
|
12
12
|
series: MetricSeries[];
|
|
13
13
|
height: number;
|
|
14
14
|
/** Fixed scale ceiling (e.g. 100 for a percentage axis). Omitted = autoscale to
|
|
15
15
|
* the max across all series in the visible window. */
|
|
16
16
|
maxValue?: number;
|
|
17
|
+
/** Mission Center's faint ruled background. Off by default — the Overview cards
|
|
18
|
+
* are 56px tall and a grid in there is noise rather than a reading aid. */
|
|
19
|
+
grid?: boolean;
|
|
20
|
+
/** Stack the series instead of overlaying them: each is drawn on top of the sum
|
|
21
|
+
* of the ones before it, so the top edge is the total. The caller supplies
|
|
22
|
+
* values that already sum to the scale (24 threads each divided by 24), because
|
|
23
|
+
* only the caller knows what the total is supposed to mean. */
|
|
24
|
+
stacked?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Mission Center's ruling: ten columns and five rows, fixed rather than derived
|
|
28
|
+
* from the point count, so the background does not crawl as the window fills. */
|
|
29
|
+
const GRID_COLS = 10;
|
|
30
|
+
const GRID_ROWS = 5;
|
|
31
|
+
|
|
32
|
+
/** The per-column sums a stack reaches, which is what its axis has to fit. */
|
|
33
|
+
function stackedTotals(series: MetricSeries[]): number[] {
|
|
34
|
+
const len = Math.max(0, ...series.map((s) => s.data.length));
|
|
35
|
+
const totals = new Array(len).fill(0);
|
|
36
|
+
for (const s of series) for (let i = 0; i < s.data.length; i++) totals[i] += s.data[i] ?? 0;
|
|
37
|
+
return totals;
|
|
17
38
|
}
|
|
18
39
|
|
|
19
40
|
/** Generalised, filled, multi-series canvas chart for the Overview cards. Fills the
|
|
@@ -25,6 +46,8 @@ export const MetricChartCanvas = memo(function MetricChartCanvas({
|
|
|
25
46
|
series,
|
|
26
47
|
height,
|
|
27
48
|
maxValue,
|
|
49
|
+
grid = false,
|
|
50
|
+
stacked = false,
|
|
28
51
|
}: MetricChartCanvasProps) {
|
|
29
52
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
30
53
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
@@ -51,6 +74,26 @@ export const MetricChartCanvas = memo(function MetricChartCanvas({
|
|
|
51
74
|
const drawH = height - padding * 2;
|
|
52
75
|
const longest = Math.max(1, ...series.map((s) => s.data.length));
|
|
53
76
|
|
|
77
|
+
// Behind everything, so a curve is never cut by a rule.
|
|
78
|
+
if (grid) {
|
|
79
|
+
ctx.strokeStyle = colorOf("var(--color-border)");
|
|
80
|
+
ctx.globalAlpha = 0.5;
|
|
81
|
+
ctx.lineWidth = 1;
|
|
82
|
+
ctx.beginPath();
|
|
83
|
+
for (let c = 1; c < GRID_COLS; c++) {
|
|
84
|
+
const x = Math.round((width / GRID_COLS) * c) + 0.5;
|
|
85
|
+
ctx.moveTo(x, 0);
|
|
86
|
+
ctx.lineTo(x, height);
|
|
87
|
+
}
|
|
88
|
+
for (let r = 1; r < GRID_ROWS; r++) {
|
|
89
|
+
const y = Math.round((height / GRID_ROWS) * r) + 0.5;
|
|
90
|
+
ctx.moveTo(0, y);
|
|
91
|
+
ctx.lineTo(width, y);
|
|
92
|
+
}
|
|
93
|
+
ctx.stroke();
|
|
94
|
+
ctx.globalAlpha = 1;
|
|
95
|
+
}
|
|
96
|
+
|
|
54
97
|
// A flat baseline when there isn't enough data yet to draw a meaningful line —
|
|
55
98
|
// a freshly-opened window otherwise shows nothing at all for the first tick.
|
|
56
99
|
if (longest < 2) {
|
|
@@ -63,7 +106,40 @@ export const MetricChartCanvas = memo(function MetricChartCanvas({
|
|
|
63
106
|
return;
|
|
64
107
|
}
|
|
65
108
|
|
|
66
|
-
const scaleMax = resolveScaleMax(
|
|
109
|
+
const scaleMax = resolveScaleMax(
|
|
110
|
+
stacked ? stackedTotals(series) : series.flatMap((s) => s.data),
|
|
111
|
+
maxValue,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
if (stacked) {
|
|
115
|
+
// Each band is the area between the running sum before it and after it, so
|
|
116
|
+
// the visible height of a band IS that series' contribution. Drawn bottom-up
|
|
117
|
+
// with a closed polygon per band rather than one fill per series over a
|
|
118
|
+
// shared baseline, which would hide every series behind the first.
|
|
119
|
+
const below: number[] = new Array(Math.max(0, ...series.map((x) => x.data.length))).fill(0);
|
|
120
|
+
for (const s of series) {
|
|
121
|
+
if (s.data.length < 2) continue;
|
|
122
|
+
const stepX = width / (s.data.length - 1);
|
|
123
|
+
const yOf = (v: number) => padding + drawH - (v / scaleMax) * drawH;
|
|
124
|
+
ctx.beginPath();
|
|
125
|
+
for (let i = 0; i < s.data.length; i++) {
|
|
126
|
+
const top = (below[i] ?? 0) + (s.data[i] ?? 0);
|
|
127
|
+
const p = [i * stepX, yOf(top)] as const;
|
|
128
|
+
if (i === 0) ctx.moveTo(p[0], p[1]);
|
|
129
|
+
else ctx.lineTo(p[0], p[1]);
|
|
130
|
+
}
|
|
131
|
+
for (let i = s.data.length - 1; i >= 0; i--) {
|
|
132
|
+
ctx.lineTo(i * stepX, yOf(below[i] ?? 0));
|
|
133
|
+
}
|
|
134
|
+
ctx.closePath();
|
|
135
|
+
ctx.fillStyle = colorOf(s.color);
|
|
136
|
+
ctx.globalAlpha = 0.75;
|
|
137
|
+
ctx.fill();
|
|
138
|
+
ctx.globalAlpha = 1;
|
|
139
|
+
for (let i = 0; i < s.data.length; i++) below[i] = (below[i] ?? 0) + (s.data[i] ?? 0);
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
67
143
|
|
|
68
144
|
for (const s of series) {
|
|
69
145
|
if (s.data.length < 2) continue;
|
|
@@ -97,7 +173,7 @@ export const MetricChartCanvas = memo(function MetricChartCanvas({
|
|
|
97
173
|
}
|
|
98
174
|
ctx.stroke();
|
|
99
175
|
}
|
|
100
|
-
}, [series, width, height, maxValue]);
|
|
176
|
+
}, [series, width, height, maxValue, grid, stacked]);
|
|
101
177
|
|
|
102
178
|
return (
|
|
103
179
|
<div ref={wrapperRef} className="w-full min-w-0 overflow-hidden" style={{ height }}>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
export interface CardShellProps {
|
|
5
|
+
testId: string;
|
|
6
|
+
/** Extra `data-*` the card publishes for tests, e.g. `data-available`. */
|
|
7
|
+
data?: Record<string, string | number | boolean>;
|
|
8
|
+
/** Present when this card has a Performance device to open. A card with no
|
|
9
|
+
* target — a host reporting no drives at all — stays a plain `div`, because a
|
|
10
|
+
* button that does nothing is worse than no button. */
|
|
11
|
+
onOpen?: () => void;
|
|
12
|
+
/** What the button announces. Required with `onOpen`: a button's name is
|
|
13
|
+
* otherwise computed from its contents, which here is the whole card
|
|
14
|
+
* ("CPU 6.9% 12th Gen Intel(R) Core(TM) i9-12900K"). */
|
|
15
|
+
openLabel?: string;
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The frame every Overview card shares, and the click that opens its Performance
|
|
21
|
+
* page. Extracted because all five cards had a byte-identical wrapper and this
|
|
22
|
+
* adds a conditional element type to each of them.
|
|
23
|
+
*
|
|
24
|
+
* It is one button over the whole card rather than a small "details" affordance
|
|
25
|
+
* in a corner: a 44px target is the mobile floor and the card is the thing the
|
|
26
|
+
* reader is already pointing at. That does mean the heading inside it stops being
|
|
27
|
+
* a navigable heading for a screen reader, which is why the name is given
|
|
28
|
+
* explicitly instead of being read off the contents.
|
|
29
|
+
*/
|
|
30
|
+
export function CardShell({ testId, data, onOpen, openLabel, children }: CardShellProps) {
|
|
31
|
+
const frame = "rounded-lg border border-border p-4 space-y-2";
|
|
32
|
+
const attrs = { "data-testid": testId, ...data };
|
|
33
|
+
|
|
34
|
+
if (!onOpen) return <div className={frame} {...attrs}>{children}</div>;
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<button
|
|
38
|
+
type="button"
|
|
39
|
+
onClick={onOpen}
|
|
40
|
+
aria-label={openLabel}
|
|
41
|
+
{...attrs}
|
|
42
|
+
className={cn(
|
|
43
|
+
frame,
|
|
44
|
+
// `text-left` because a button centres its content, and `w-full` because
|
|
45
|
+
// it is a grid item that would otherwise shrink to its content.
|
|
46
|
+
"w-full text-left cursor-pointer transition-colors",
|
|
47
|
+
"hover:bg-surface-hover hover:border-primary/40",
|
|
48
|
+
"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary",
|
|
49
|
+
)}
|
|
50
|
+
>
|
|
51
|
+
{children}
|
|
52
|
+
</button>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { MetricChartCanvas } from "../metric-chart-canvas";
|
|
2
2
|
import { CpuCoreBars } from "../cpu-core-bars";
|
|
3
|
+
import { CardShell } from "./card-shell";
|
|
3
4
|
|
|
4
5
|
export interface CpuCardProps {
|
|
5
6
|
total: number;
|
|
6
7
|
cores: number[];
|
|
7
8
|
model: string;
|
|
8
9
|
series: number[];
|
|
10
|
+
/** Opens the Performance page on this device. */
|
|
11
|
+
onOpen?: () => void;
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
function cpuColor(pct: number): string {
|
|
@@ -14,12 +17,13 @@ function cpuColor(pct: number): string {
|
|
|
14
17
|
return "text-success";
|
|
15
18
|
}
|
|
16
19
|
|
|
17
|
-
export function CpuCard({ total, cores, model, series }: CpuCardProps) {
|
|
20
|
+
export function CpuCard({ total, cores, model, series, onOpen }: CpuCardProps) {
|
|
18
21
|
return (
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
data
|
|
22
|
-
|
|
22
|
+
<CardShell
|
|
23
|
+
testId="sysmon-card-cpu"
|
|
24
|
+
data={{ "data-cpu-total": total }}
|
|
25
|
+
onOpen={onOpen}
|
|
26
|
+
openLabel="CPU details"
|
|
23
27
|
>
|
|
24
28
|
<div className="flex items-baseline justify-between">
|
|
25
29
|
<h3 className="text-sm font-medium">CPU</h3>
|
|
@@ -29,11 +33,12 @@ export function CpuCard({ total, cores, model, series }: CpuCardProps) {
|
|
|
29
33
|
series={[{ data: series, color: "var(--color-primary)" }]}
|
|
30
34
|
height={56}
|
|
31
35
|
maxValue={100}
|
|
36
|
+
grid
|
|
32
37
|
/>
|
|
33
38
|
<CpuCoreBars cores={cores} />
|
|
34
39
|
<p className="text-[11px] text-text-subtle truncate" title={model}>
|
|
35
40
|
{model}
|
|
36
41
|
</p>
|
|
37
|
-
</
|
|
42
|
+
</CardShell>
|
|
38
43
|
);
|
|
39
44
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { formatBps } from "@/lib/format-bytes";
|
|
2
2
|
import { MetricChartCanvas } from "../metric-chart-canvas";
|
|
3
|
+
import { CardShell } from "./card-shell";
|
|
3
4
|
|
|
4
5
|
export interface DiskCardProps {
|
|
5
6
|
available: boolean;
|
|
@@ -10,14 +11,17 @@ export interface DiskCardProps {
|
|
|
10
11
|
/** True while the stream has not yet delivered a second tick — a rate needs two
|
|
11
12
|
* samples, so `available:false` here is expected, not a missing collector. */
|
|
12
13
|
measuring?: boolean;
|
|
14
|
+
/** Opens the Performance page on the busiest device of this kind. */
|
|
15
|
+
onOpen?: () => void;
|
|
13
16
|
}
|
|
14
17
|
|
|
15
|
-
export function DiskCard({ available, inBps, outBps, readSeries, writeSeries, measuring }: DiskCardProps) {
|
|
18
|
+
export function DiskCard({ available, inBps, outBps, readSeries, writeSeries, measuring, onOpen }: DiskCardProps) {
|
|
16
19
|
return (
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
data
|
|
20
|
-
|
|
20
|
+
<CardShell
|
|
21
|
+
testId="sysmon-card-disk"
|
|
22
|
+
data={{ "data-available": available }}
|
|
23
|
+
onOpen={onOpen}
|
|
24
|
+
openLabel="Disk details"
|
|
21
25
|
>
|
|
22
26
|
<h3 className="text-sm font-medium">Disk</h3>
|
|
23
27
|
{available ? (
|
|
@@ -28,6 +32,7 @@ export function DiskCard({ available, inBps, outBps, readSeries, writeSeries, me
|
|
|
28
32
|
{ data: writeSeries, color: "var(--color-warning)" },
|
|
29
33
|
]}
|
|
30
34
|
height={56}
|
|
35
|
+
grid
|
|
31
36
|
/>
|
|
32
37
|
<p className="text-[11px] text-text-subtle">
|
|
33
38
|
Read {formatBps(inBps)} · Write {formatBps(outBps)}
|
|
@@ -36,6 +41,6 @@ export function DiskCard({ available, inBps, outBps, readSeries, writeSeries, me
|
|
|
36
41
|
) : (
|
|
37
42
|
<p className="text-[11px] text-text-subtle">{measuring ? "measuring…" : "n/a"}</p>
|
|
38
43
|
)}
|
|
39
|
-
</
|
|
44
|
+
</CardShell>
|
|
40
45
|
);
|
|
41
46
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { formatRam } from "@/lib/format-bytes";
|
|
2
2
|
import { MetricChartCanvas } from "../metric-chart-canvas";
|
|
3
|
+
import { CardShell } from "./card-shell";
|
|
3
4
|
|
|
4
5
|
export interface GpuCardProps {
|
|
5
6
|
name: string;
|
|
@@ -7,13 +8,15 @@ export interface GpuCardProps {
|
|
|
7
8
|
vramUsedMB: number;
|
|
8
9
|
vramTotalMB: number;
|
|
9
10
|
series: number[];
|
|
11
|
+
/** Opens the Performance page on this GPU. */
|
|
12
|
+
onOpen?: () => void;
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
/** One card per GPU. The caller (`overview-panel.tsx`) renders zero of these when
|
|
13
16
|
* `system.gpus` is empty — hide, never a disabled placeholder card. */
|
|
14
|
-
export function GpuCard({ name, utilPercent, vramUsedMB, vramTotalMB, series }: GpuCardProps) {
|
|
17
|
+
export function GpuCard({ name, utilPercent, vramUsedMB, vramTotalMB, series, onOpen }: GpuCardProps) {
|
|
15
18
|
return (
|
|
16
|
-
<
|
|
19
|
+
<CardShell testId="sysmon-card-gpu" onOpen={onOpen} openLabel={`${name} details`}>
|
|
17
20
|
<div className="flex items-baseline justify-between gap-2">
|
|
18
21
|
<h3 className="text-sm font-medium truncate" title={name}>
|
|
19
22
|
{name}
|
|
@@ -24,10 +27,17 @@ export function GpuCard({ name, utilPercent, vramUsedMB, vramTotalMB, series }:
|
|
|
24
27
|
series={[{ data: series, color: "var(--color-primary)" }]}
|
|
25
28
|
height={56}
|
|
26
29
|
maxValue={100}
|
|
30
|
+
grid
|
|
27
31
|
/>
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
{/* A total of 0 is the contract's "this device has no dedicated memory" — an
|
|
33
|
+
integrated GPU — not a card with an empty one. Saying "0 MB / 0 MB" states
|
|
34
|
+
a measurement that was never taken, and disagrees with the Performance
|
|
35
|
+
page's GPU detail, which renders the same case as an em dash. */}
|
|
36
|
+
{vramTotalMB > 0 && (
|
|
37
|
+
<p className="text-[11px] text-text-subtle">
|
|
38
|
+
VRAM {formatRam(vramUsedMB)} / {formatRam(vramTotalMB)}
|
|
39
|
+
</p>
|
|
40
|
+
)}
|
|
41
|
+
</CardShell>
|
|
32
42
|
);
|
|
33
43
|
}
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import { formatRam } from "@/lib/format-bytes";
|
|
2
2
|
import { MetricChartCanvas } from "../metric-chart-canvas";
|
|
3
|
+
import { CardShell } from "./card-shell";
|
|
3
4
|
|
|
4
5
|
export interface MemCardProps {
|
|
5
6
|
usedMB: number;
|
|
6
7
|
totalMB: number;
|
|
7
8
|
percent: number;
|
|
8
9
|
series: number[];
|
|
10
|
+
/** Opens the Performance page on this device. */
|
|
11
|
+
onOpen?: () => void;
|
|
9
12
|
}
|
|
10
13
|
|
|
11
|
-
export function MemCard({ usedMB, totalMB, percent, series }: MemCardProps) {
|
|
14
|
+
export function MemCard({ usedMB, totalMB, percent, series, onOpen }: MemCardProps) {
|
|
12
15
|
return (
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
data
|
|
16
|
-
|
|
16
|
+
<CardShell
|
|
17
|
+
testId="sysmon-card-mem"
|
|
18
|
+
data={{ "data-mem-percent": percent }}
|
|
19
|
+
onOpen={onOpen}
|
|
20
|
+
openLabel="Memory details"
|
|
17
21
|
>
|
|
18
22
|
<div className="flex items-baseline justify-between">
|
|
19
23
|
<h3 className="text-sm font-medium">Memory</h3>
|
|
@@ -23,10 +27,11 @@ export function MemCard({ usedMB, totalMB, percent, series }: MemCardProps) {
|
|
|
23
27
|
series={[{ data: series, color: "var(--color-primary)" }]}
|
|
24
28
|
height={56}
|
|
25
29
|
maxValue={100}
|
|
30
|
+
grid
|
|
26
31
|
/>
|
|
27
32
|
<p className="text-[11px] text-text-subtle">
|
|
28
33
|
{formatRam(usedMB)} / {formatRam(totalMB)}
|
|
29
34
|
</p>
|
|
30
|
-
</
|
|
35
|
+
</CardShell>
|
|
31
36
|
);
|
|
32
37
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { formatBps } from "@/lib/format-bytes";
|
|
2
2
|
import { MetricChartCanvas } from "../metric-chart-canvas";
|
|
3
|
+
import { CardShell } from "./card-shell";
|
|
3
4
|
|
|
4
5
|
export interface NetCardProps {
|
|
5
6
|
available: boolean;
|
|
@@ -10,14 +11,17 @@ export interface NetCardProps {
|
|
|
10
11
|
/** True while the stream has not yet delivered a second tick — a rate needs two
|
|
11
12
|
* samples, so `available:false` here is expected, not a missing collector. */
|
|
12
13
|
measuring?: boolean;
|
|
14
|
+
/** Opens the Performance page on the busiest device of this kind. */
|
|
15
|
+
onOpen?: () => void;
|
|
13
16
|
}
|
|
14
17
|
|
|
15
|
-
export function NetCard({ available, inBps, outBps, downSeries, upSeries, measuring }: NetCardProps) {
|
|
18
|
+
export function NetCard({ available, inBps, outBps, downSeries, upSeries, measuring, onOpen }: NetCardProps) {
|
|
16
19
|
return (
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
data
|
|
20
|
-
|
|
20
|
+
<CardShell
|
|
21
|
+
testId="sysmon-card-net"
|
|
22
|
+
data={{ "data-available": available }}
|
|
23
|
+
onOpen={onOpen}
|
|
24
|
+
openLabel="Network details"
|
|
21
25
|
>
|
|
22
26
|
<h3 className="text-sm font-medium">Network</h3>
|
|
23
27
|
{available ? (
|
|
@@ -28,6 +32,7 @@ export function NetCard({ available, inBps, outBps, downSeries, upSeries, measur
|
|
|
28
32
|
{ data: upSeries, color: "var(--color-warning)" },
|
|
29
33
|
]}
|
|
30
34
|
height={56}
|
|
35
|
+
grid
|
|
31
36
|
/>
|
|
32
37
|
<p className="text-[11px] text-text-subtle">
|
|
33
38
|
Down {formatBps(inBps)} · Up {formatBps(outBps)}
|
|
@@ -36,6 +41,6 @@ export function NetCard({ available, inBps, outBps, downSeries, upSeries, measur
|
|
|
36
41
|
) : (
|
|
37
42
|
<p className="text-[11px] text-text-subtle">{measuring ? "measuring…" : "n/a"}</p>
|
|
38
43
|
)}
|
|
39
|
-
</
|
|
44
|
+
</CardShell>
|
|
40
45
|
);
|
|
41
46
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which Performance device an Overview card opens.
|
|
3
|
+
*
|
|
4
|
+
* Three of the five cards have a 1-to-1 target and need no logic: CPU is `cpu`,
|
|
5
|
+
* Memory is `memory`, and each GPU card already knows its own GPU. The Disk and
|
|
6
|
+
* Network cards are the awkward pair — they show **whole-machine** rates while
|
|
7
|
+
* the Performance sidebar lists every drive and every interface separately (two
|
|
8
|
+
* drives and seven interfaces on an ordinary desktop), so a card click has to
|
|
9
|
+
* choose one.
|
|
10
|
+
*
|
|
11
|
+
* It chooses the busiest, because that is what the reader was looking at: you
|
|
12
|
+
* click a Disk card that says "Write 191 MB/s" to find out which drive is doing
|
|
13
|
+
* it. The cost, accepted deliberately: the destination is not fixed, so the same
|
|
14
|
+
* card can open Disk 1 now and Disk 0 later. The alternative — always the first
|
|
15
|
+
* device — is predictable and usually wrong, since `Disk 0` on this host is an
|
|
16
|
+
* idle Toshiba while the loaded drive is `Disk 1`.
|
|
17
|
+
*
|
|
18
|
+
* Each metric matches the figure its own surface already shows, so the jump never
|
|
19
|
+
* contradicts what was on screen: **active time** for a drive (what the sidebar
|
|
20
|
+
* prints, and Mission Center's choice — a drive at 100% busy moving very little
|
|
21
|
+
* still matters) and **raw throughput** for an interface (what the card prints;
|
|
22
|
+
* normalising by link speed would rank a 100 Mbit NIC at 50% above a 10 Gbit one
|
|
23
|
+
* carrying ten times the traffic).
|
|
24
|
+
*
|
|
25
|
+
* Pure, React-free, relative imports only. The keys are `DeviceEntry.key`
|
|
26
|
+
* strings, so they are coupled to `performance/device-list.ts` by format — which
|
|
27
|
+
* is why the test asserts the key against a real `buildDeviceList` rather than
|
|
28
|
+
* against a literal. A key that matches no entry is not an error anywhere:
|
|
29
|
+
* `resolveSelected` silently falls back to the first entry, so the jump would
|
|
30
|
+
* quietly land on CPU.
|
|
31
|
+
*/
|
|
32
|
+
import type { SystemMetrics } from "../../../types/system-metrics";
|
|
33
|
+
|
|
34
|
+
/** Highest-scoring entry, or null when there is nothing to pick from. Ties go to
|
|
35
|
+
* the first, so a wholly idle machine is at least deterministic. */
|
|
36
|
+
function busiest<T>(items: readonly T[], score: (item: T) => number | null): T | null {
|
|
37
|
+
let best: T | null = null;
|
|
38
|
+
let bestScore = -Infinity;
|
|
39
|
+
for (const item of items) {
|
|
40
|
+
const s = score(item);
|
|
41
|
+
if (s === null) continue;
|
|
42
|
+
if (s > bestScore) {
|
|
43
|
+
best = item;
|
|
44
|
+
bestScore = s;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Every device unmeasurable (every `available: false`, i.e. the very first
|
|
48
|
+
// tick) still has to go somewhere, so fall back to the first one and let its
|
|
49
|
+
// page render the em dashes honestly.
|
|
50
|
+
return best ?? items[0] ?? null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** The drive with the most active time. Null when the host reports no drives. */
|
|
54
|
+
export function busiestDiskKey(system: SystemMetrics): string | null {
|
|
55
|
+
const disk = busiest(system.disks ?? [], (d) => (d.available ? d.busyPercent : null));
|
|
56
|
+
return disk ? `disk:${disk.id}` : null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** The interface carrying the most traffic. Null when the host reports none. */
|
|
60
|
+
export function busiestNicKey(system: SystemMetrics): string | null {
|
|
61
|
+
const nic = busiest(system.nics ?? [], (n) => (n.available ? n.rxBps + n.txBps : null));
|
|
62
|
+
return nic ? `nic:${nic.id}` : null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The sidebar key for one GPU, matching `buildDeviceList`'s own fallback to the
|
|
66
|
+
* index for a device with no PCI address. */
|
|
67
|
+
export function gpuKey(id: string | undefined, index: number): string {
|
|
68
|
+
return `gpu:${id ?? index}`;
|
|
69
|
+
}
|
|
@@ -5,10 +5,14 @@ import { MemCard } from "./overview-cards/mem-card";
|
|
|
5
5
|
import { DiskCard } from "./overview-cards/disk-card";
|
|
6
6
|
import { NetCard } from "./overview-cards/net-card";
|
|
7
7
|
import { GpuCard } from "./overview-cards/gpu-card";
|
|
8
|
+
import { busiestDiskKey, busiestNicKey, gpuKey } from "./overview-device-target";
|
|
8
9
|
|
|
9
10
|
export interface OverviewPanelProps {
|
|
10
11
|
system: SystemMetrics;
|
|
11
12
|
history: MetricsHistoryPoint[];
|
|
13
|
+
/** Opens the Performance tab on one device. Absent in a read-only render (and
|
|
14
|
+
* then every card stays a plain frame rather than a button that does nothing). */
|
|
15
|
+
onOpenDevice?: (key: string) => void;
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
const SERIES_POINTS = 200;
|
|
@@ -42,12 +46,17 @@ function useOverviewSeries(history: MetricsHistoryPoint[]) {
|
|
|
42
46
|
}, [history]);
|
|
43
47
|
}
|
|
44
48
|
|
|
45
|
-
export function OverviewPanel({ system, history }: OverviewPanelProps) {
|
|
49
|
+
export function OverviewPanel({ system, history, onOpenDevice }: OverviewPanelProps) {
|
|
46
50
|
const series = useOverviewSeries(history);
|
|
47
51
|
// Disk/net rates need a delta between two samples — `available:false` on the very
|
|
48
52
|
// first frame(s) is the collector doing exactly what it should, not a missing
|
|
49
53
|
// source, so the card says so instead of the flat, indistinguishable "n/a".
|
|
50
54
|
const measuring = history.length <= 1;
|
|
55
|
+
// Undefined rather than a no-op handler when there is no device to open, so
|
|
56
|
+
// `CardShell` renders a frame instead of a dead button. Computed per render
|
|
57
|
+
// because the busiest drive and interface change with the tick.
|
|
58
|
+
const open = (key: string | null) =>
|
|
59
|
+
onOpenDevice && key ? () => onOpenDevice(key) : undefined;
|
|
51
60
|
|
|
52
61
|
return (
|
|
53
62
|
<div
|
|
@@ -59,12 +68,14 @@ export function OverviewPanel({ system, history }: OverviewPanelProps) {
|
|
|
59
68
|
cores={system.cpu.cores}
|
|
60
69
|
model={system.cpu.model}
|
|
61
70
|
series={series.cpu}
|
|
71
|
+
onOpen={open("cpu")}
|
|
62
72
|
/>
|
|
63
73
|
<MemCard
|
|
64
74
|
usedMB={system.mem.usedMB}
|
|
65
75
|
totalMB={system.mem.totalMB}
|
|
66
76
|
percent={system.mem.percent}
|
|
67
77
|
series={series.mem}
|
|
78
|
+
onOpen={open("memory")}
|
|
68
79
|
/>
|
|
69
80
|
<DiskCard
|
|
70
81
|
available={system.disk.available}
|
|
@@ -73,6 +84,7 @@ export function OverviewPanel({ system, history }: OverviewPanelProps) {
|
|
|
73
84
|
readSeries={series.diskRead}
|
|
74
85
|
writeSeries={series.diskWrite}
|
|
75
86
|
measuring={measuring}
|
|
87
|
+
onOpen={open(busiestDiskKey(system))}
|
|
76
88
|
/>
|
|
77
89
|
<NetCard
|
|
78
90
|
available={system.net.available}
|
|
@@ -81,6 +93,7 @@ export function OverviewPanel({ system, history }: OverviewPanelProps) {
|
|
|
81
93
|
downSeries={series.netDown}
|
|
82
94
|
upSeries={series.netUp}
|
|
83
95
|
measuring={measuring}
|
|
96
|
+
onOpen={open(busiestNicKey(system))}
|
|
84
97
|
/>
|
|
85
98
|
{system.gpus.map((gpu, i) => (
|
|
86
99
|
<GpuCard
|
|
@@ -90,6 +103,7 @@ export function OverviewPanel({ system, history }: OverviewPanelProps) {
|
|
|
90
103
|
vramUsedMB={gpu.vramUsedMB}
|
|
91
104
|
vramTotalMB={gpu.vramTotalMB}
|
|
92
105
|
series={series.gpuUtil[i] ?? []}
|
|
106
|
+
onOpen={open(gpuKey(gpu.id, i))}
|
|
93
107
|
/>
|
|
94
108
|
))}
|
|
95
109
|
</div>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One graph per logical processor — Mission Center's "Logical Processors" top
|
|
3
|
+
* graph, which is the view that makes a hybrid part legible: on a 12900K the
|
|
4
|
+
* eight P-cores and their SMT siblings move quite differently from the eight
|
|
5
|
+
* E-cores, and a single overall line says none of that.
|
|
6
|
+
*
|
|
7
|
+
* Each cell draws its OWN history rather than a bar of the current value, so a
|
|
8
|
+
* thread that spiked two seconds ago is still visible — which is the whole point
|
|
9
|
+
* of a graph over a meter.
|
|
10
|
+
*/
|
|
11
|
+
import { useRef, useMemo } from "react";
|
|
12
|
+
import { useElementWidth } from "@/hooks/use-element-width";
|
|
13
|
+
import { coreGridLayout } from "@/lib/cpu-graph-mode";
|
|
14
|
+
import { MetricChartCanvas } from "../metric-chart-canvas";
|
|
15
|
+
import { CHART_COLORS } from "./detail-parts";
|
|
16
|
+
import type { MetricsHistoryPoint } from "../../../../types/system-metrics";
|
|
17
|
+
|
|
18
|
+
export interface CpuCoreGridProps {
|
|
19
|
+
/** Current reading per logical processor — the length is what decides the grid. */
|
|
20
|
+
cores: readonly number[];
|
|
21
|
+
history: readonly MetricsHistoryPoint[];
|
|
22
|
+
points?: number;
|
|
23
|
+
/** Total height the grid may use; each row gets an equal share. */
|
|
24
|
+
height?: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function CpuCoreGrid({ cores, history, points = 200, height = 260 }: CpuCoreGridProps) {
|
|
28
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
29
|
+
const width = useElementWidth(ref);
|
|
30
|
+
const { cols, rows } = coreGridLayout(cores.length, width);
|
|
31
|
+
|
|
32
|
+
// One pass over the window building every cell's series together, rather than
|
|
33
|
+
// twenty-four separate `.map`s over the same 200 points on every tick.
|
|
34
|
+
const series = useMemo(() => {
|
|
35
|
+
const window = history.slice(-points);
|
|
36
|
+
const out: number[][] = Array.from({ length: cores.length }, () => []);
|
|
37
|
+
for (const point of window) {
|
|
38
|
+
const values = point.system.cpu.cores;
|
|
39
|
+
for (let i = 0; i < out.length; i++) out[i]!.push(values[i] ?? 0);
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}, [history, points, cores.length]);
|
|
43
|
+
|
|
44
|
+
if (cores.length === 0) return null;
|
|
45
|
+
|
|
46
|
+
// A cell is short; the ruled background would be denser than the curve, so only
|
|
47
|
+
// the frame is drawn and the grid stays on the full-width graphs.
|
|
48
|
+
const cellHeight = Math.max(28, Math.floor(height / Math.max(1, rows)) - 6);
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div
|
|
52
|
+
ref={ref}
|
|
53
|
+
className="grid gap-1.5"
|
|
54
|
+
style={{ gridTemplateColumns: `repeat(${Math.max(1, cols)}, minmax(0, 1fr))` }}
|
|
55
|
+
data-testid="sysmon-core-grid"
|
|
56
|
+
data-core-count={cores.length}
|
|
57
|
+
data-cols={cols}
|
|
58
|
+
>
|
|
59
|
+
{series.map((data, i) => (
|
|
60
|
+
<div
|
|
61
|
+
key={i}
|
|
62
|
+
className="rounded-sm border border-border/70 overflow-hidden px-0.5"
|
|
63
|
+
title={`CPU ${i}: ${(cores[i] ?? 0).toFixed(0)}%`}
|
|
64
|
+
>
|
|
65
|
+
<MetricChartCanvas
|
|
66
|
+
series={[{ data, color: CHART_COLORS.primary }]}
|
|
67
|
+
height={cellHeight}
|
|
68
|
+
maxValue={100}
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
71
|
+
))}
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
}
|