@hienlh/ppm 0.23.5 → 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 +89 -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 +30 -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-DKcsVDle.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-qMGJH0Bx.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-D2I742dl.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-Bz4LjgIa.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-CapP1yXq.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-CdXi7cZN.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-B2nZzJ2b.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-BGoDxkdF.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-DC3OzzOl.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-i41W43ER.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-DHzPIkJg.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-Dj4vrDvj.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-BJ9edGEP.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-CxdGSNGr.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-ok96IgnS.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-Drkjb_LI.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-C8PFlvaq.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-CFYO0Ro3.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-BcHIEANE.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-BGsp0edA.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-CsZCCRJI.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-Ci0O2Ng6.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-4iCGE4h2.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-CK6DulYk.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-CWBaWKjA.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-Br6mrxrw.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-CwCy7ZWf.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-BW14RpCb.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-CgOBEUnb.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-rH6epJYA.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-QwURkjpV.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/codex-app-server/codex-reset-credit.ts +49 -0
- 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/codex-accounts.ts +14 -0
- 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 +83 -0
- package/src/services/compaction-savings.ts +127 -0
- package/src/services/db.service.ts +123 -8
- package/src/services/edge-forwarder.ts +191 -191
- 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/services/windows-process-tree.ts +351 -351
- package/src/shared/prompt-cache-idle.ts +197 -0
- package/src/shared/turn-usage.ts +85 -1
- package/src/shared/usage-extra.ts +19 -0
- package/src/types/chat.ts +29 -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/codex-usage-panel.tsx +4 -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 +10 -2
- package/src/web/components/settings/accounts/account-usage-extras.tsx +3 -2
- package/src/web/components/settings/accounts/codex-accounts-section.tsx +3 -1
- package/src/web/components/settings/accounts/codex-reset-credit-button.tsx +120 -0
- 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-CgG5P3Jm.js +0 -1
- package/dist/web/assets/accounts-settings-section-CgG5P3Jm.js.br +0 -0
- package/dist/web/assets/accounts-settings-section-CgG5P3Jm.js.gz +0 -0
- package/dist/web/assets/ai-resource-editor-DKcsVDle.js.br +0 -0
- package/dist/web/assets/ai-resource-editor-DKcsVDle.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-D7zJ-hCO.js +0 -1
- package/dist/web/assets/ai-settings-section-D7zJ-hCO.js.br +0 -0
- package/dist/web/assets/ai-settings-section-D7zJ-hCO.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-OPqC2bYG.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-DL466x83.js +0 -1
- package/dist/web/assets/appearance-settings-section-DL466x83.js.br +0 -0
- package/dist/web/assets/appearance-settings-section-DL466x83.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-Dag86n_R.js +0 -1
- package/dist/web/assets/branch-review-tab-Dag86n_R.js.br +0 -0
- package/dist/web/assets/branch-review-tab-Dag86n_R.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-CcYZLXls.js +0 -15
- package/dist/web/assets/chat-tab-CcYZLXls.js.br +0 -0
- package/dist/web/assets/chat-tab-CcYZLXls.js.gz +0 -0
- package/dist/web/assets/chat-tab-QFDhzzBZ.js +0 -1
- package/dist/web/assets/chat-tab-QFDhzzBZ.js.br +0 -0
- package/dist/web/assets/chat-tab-QFDhzzBZ.js.gz +0 -0
- package/dist/web/assets/code-editor-K-IN8VwJ.js +0 -7
- package/dist/web/assets/code-editor-K-IN8VwJ.js.br +0 -0
- package/dist/web/assets/code-editor-K-IN8VwJ.js.gz +0 -0
- package/dist/web/assets/codex-sign-in-again-dialog-C8JvblLG.js +0 -1
- package/dist/web/assets/codex-sign-in-again-dialog-C8JvblLG.js.br +0 -0
- package/dist/web/assets/codex-sign-in-again-dialog-C8JvblLG.js.gz +0 -0
- package/dist/web/assets/conflict-editor-qMGJH0Bx.js.br +0 -0
- package/dist/web/assets/conflict-editor-qMGJH0Bx.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-D2I742dl.js.br +0 -0
- package/dist/web/assets/csv-preview-D2I742dl.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-Bz4LjgIa.js.br +0 -0
- package/dist/web/assets/database-viewer-Bz4LjgIa.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-C987MtMR.js +0 -33
- package/dist/web/assets/design-tab-C987MtMR.js.br +0 -0
- package/dist/web/assets/design-tab-C987MtMR.js.gz +0 -0
- package/dist/web/assets/designs-sidebar-panel-CapP1yXq.js.br +0 -0
- package/dist/web/assets/designs-sidebar-panel-CapP1yXq.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-CdXi7cZN.js.br +0 -0
- package/dist/web/assets/diff-viewer-CdXi7cZN.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-Zle_PZV8.js +0 -1
- package/dist/web/assets/editor-language-service-Zle_PZV8.js.br +0 -0
- package/dist/web/assets/editor-language-service-Zle_PZV8.js.gz +0 -0
- package/dist/web/assets/explorer-body-DHMQR1Rk.js +0 -2
- package/dist/web/assets/explorer-body-DHMQR1Rk.js.br +0 -0
- package/dist/web/assets/explorer-body-DHMQR1Rk.js.gz +0 -0
- package/dist/web/assets/explorer-window-content-Df40nQBk.js +0 -1
- package/dist/web/assets/explorer-window-content-Df40nQBk.js.br +0 -0
- package/dist/web/assets/explorer-window-content-Df40nQBk.js.gz +0 -0
- package/dist/web/assets/extension-manager-section-B2nZzJ2b.js.br +0 -0
- package/dist/web/assets/extension-manager-section-B2nZzJ2b.js.gz +0 -0
- package/dist/web/assets/extension-webview-BGoDxkdF.js.br +0 -0
- package/dist/web/assets/extension-webview-BGoDxkdF.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-DC3OzzOl.js.br +0 -0
- package/dist/web/assets/files-settings-section-DC3OzzOl.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-i41W43ER.js.br +0 -0
- package/dist/web/assets/general-settings-section-i41W43ER.js.gz +0 -0
- package/dist/web/assets/git-log-panel-DHzPIkJg.js.br +0 -0
- package/dist/web/assets/git-log-panel-DHzPIkJg.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-Dj4vrDvj.js.br +0 -0
- package/dist/web/assets/glide-data-grid-Dj4vrDvj.js.gz +0 -0
- package/dist/web/assets/group-chat-tab-DfwZb-fI.js +0 -1
- package/dist/web/assets/group-chat-tab-DfwZb-fI.js.br +0 -0
- package/dist/web/assets/group-chat-tab-DfwZb-fI.js.gz +0 -0
- package/dist/web/assets/index-DMA-So69.css +0 -1
- package/dist/web/assets/index-DMA-So69.css.br +0 -0
- package/dist/web/assets/index-DMA-So69.css.gz +0 -0
- package/dist/web/assets/index-jG9mLs-J.js +0 -52
- package/dist/web/assets/index-jG9mLs-J.js.br +0 -0
- package/dist/web/assets/index-jG9mLs-J.js.gz +0 -0
- package/dist/web/assets/keybindings-store-BlapkC6O.js +0 -1
- package/dist/web/assets/keyboard-shortcuts-section-CxdGSNGr.js.br +0 -0
- package/dist/web/assets/keyboard-shortcuts-section-CxdGSNGr.js.gz +0 -0
- package/dist/web/assets/markdown-renderer-DJ9EVU1B.js +0 -1
- package/dist/web/assets/markdown-renderer-ok96IgnS.js.br +0 -0
- package/dist/web/assets/markdown-renderer-ok96IgnS.js.gz +0 -0
- 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-Cc03LUKy.js +0 -1
- package/dist/web/assets/mobile-explorer-sheet-Cc03LUKy.js.br +0 -0
- package/dist/web/assets/mobile-explorer-sheet-Cc03LUKy.js.gz +0 -0
- package/dist/web/assets/new-design-dialog-Drkjb_LI.js.br +0 -0
- package/dist/web/assets/new-design-dialog-Drkjb_LI.js.gz +0 -0
- package/dist/web/assets/notification-store-DCyxho0O.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-C8PFlvaq.js.br +0 -0
- package/dist/web/assets/ppmbot-settings-section-C8PFlvaq.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-CFYO0Ro3.js.br +0 -0
- package/dist/web/assets/problems-panel-CFYO0Ro3.js.gz +0 -0
- package/dist/web/assets/process-table-BVeRguFg.js +0 -1
- package/dist/web/assets/process-table-BVeRguFg.js.br +0 -0
- package/dist/web/assets/process-table-BVeRguFg.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-BcHIEANE.js.br +0 -0
- package/dist/web/assets/proxy-settings-section-BcHIEANE.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-BGsp0edA.js.br +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-BGsp0edA.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-DxkmF8qb.js +0 -2
- package/dist/web/assets/remote-desktop-mobile-sheet-DxkmF8qb.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-DxkmF8qb.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-DMD0M9Jh.js +0 -1
- package/dist/web/assets/remote-desktop-mobile-view-DMD0M9Jh.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-DMD0M9Jh.js.gz +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-CsZCCRJI.js.br +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-CsZCCRJI.js.gz +0 -0
- package/dist/web/assets/remote-desktop-window-content-DrHw_vwY.js +0 -1
- package/dist/web/assets/remote-desktop-window-content-DrHw_vwY.js.br +0 -0
- package/dist/web/assets/remote-desktop-window-content-DrHw_vwY.js.gz +0 -0
- package/dist/web/assets/schedules-settings-section-Ci0O2Ng6.js.br +0 -0
- package/dist/web/assets/schedules-settings-section-Ci0O2Ng6.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-B6JGOIYb.js +0 -2
- package/dist/web/assets/settings-body-B6JGOIYb.js.br +0 -0
- package/dist/web/assets/settings-body-B6JGOIYb.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-CIQM4fNE.js +0 -1
- package/dist/web/assets/settings-window-content-BGNNz-E5.js +0 -1
- package/dist/web/assets/sql-query-editor-4iCGE4h2.js.br +0 -3
- package/dist/web/assets/sql-query-editor-4iCGE4h2.js.gz +0 -0
- package/dist/web/assets/sqlite-viewer-CK6DulYk.js.br +0 -0
- package/dist/web/assets/sqlite-viewer-CK6DulYk.js.gz +0 -0
- package/dist/web/assets/system-monitor-body-J9JtvAWV.js +0 -2
- package/dist/web/assets/system-monitor-body-J9JtvAWV.js.br +0 -0
- package/dist/web/assets/system-monitor-body-J9JtvAWV.js.gz +0 -0
- package/dist/web/assets/system-monitor-tab-DjBeRE81.js +0 -1
- package/dist/web/assets/system-monitor-window-content-BT7-ugFx.js +0 -1
- package/dist/web/assets/tab-host-window-content-CWBaWKjA.js.br +0 -0
- package/dist/web/assets/tab-host-window-content-CWBaWKjA.js.gz +0 -0
- package/dist/web/assets/team-member-sheet-Br6mrxrw.js.br +0 -0
- package/dist/web/assets/team-member-sheet-Br6mrxrw.js.gz +0 -0
- package/dist/web/assets/team-member-window-content-CwCy7ZWf.js.br +0 -0
- package/dist/web/assets/team-member-window-content-CwCy7ZWf.js.gz +0 -0
- package/dist/web/assets/terminal-tab-BW14RpCb.js.br +0 -0
- package/dist/web/assets/terminal-tab-BW14RpCb.js.gz +0 -0
- package/dist/web/assets/tool-cards-CgOBEUnb.js.br +0 -0
- package/dist/web/assets/tool-cards-CgOBEUnb.js.gz +0 -0
- package/dist/web/assets/use-inline-blame-Bzjfru4n.js +0 -16
- package/dist/web/assets/use-inline-blame-Bzjfru4n.js.br +0 -0
- package/dist/web/assets/use-inline-blame-Bzjfru4n.js.gz +0 -0
- package/dist/web/assets/use-lsp-hGdjL2hV.js +0 -6
- package/dist/web/assets/use-lsp-hGdjL2hV.js.br +0 -0
- package/dist/web/assets/use-lsp-hGdjL2hV.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-P9T-ZVdN.js +0 -1
- package/dist/web/assets/video-preview-P9T-ZVdN.js.br +0 -0
- package/dist/web/assets/video-preview-P9T-ZVdN.js.gz +0 -0
- package/dist/web/assets/ws-auth-kXgsX2Js.js +0 -1
- package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
- /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
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a session has sat idle long enough that its prompt cache is gone.
|
|
3
|
+
*
|
|
4
|
+
* The cost of a turn is dominated by the replayed transcript, and that replay is cheap only
|
|
5
|
+
* while the prefix behind it is still cached (see `turn-usage.ts`). The cache is the one
|
|
6
|
+
* part of that with a clock on it: it lapses on its own, silently, some time after the last
|
|
7
|
+
* turn — so the first message of the next morning costs several times what the last message
|
|
8
|
+
* of the night before did, for no reason visible in the conversation.
|
|
9
|
+
*
|
|
10
|
+
* `TurnCostWarning` reports that after the fact, on the turn that paid. This says it
|
|
11
|
+
* *before*, while the user can still decide whether to carry on in this chat or start a
|
|
12
|
+
* cheaper one. Pure and shared so the threshold is the same one the warning already uses.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { PREFIX_WARN_TOKENS } from "./turn-usage.ts";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* What the server knows about a session's cache.
|
|
19
|
+
*
|
|
20
|
+
* `ttlMs` alone is the state of a session that has not completed a turn yet — it is a
|
|
21
|
+
* property of the install, not of the conversation, and sending it early is what lets a
|
|
22
|
+
* long-lived tab arm this notice from its own turns without waiting for a reconnect.
|
|
23
|
+
*/
|
|
24
|
+
export interface PromptCacheState {
|
|
25
|
+
/** This install's cache lifetime: an hour on a subscription, five minutes on an API key. */
|
|
26
|
+
ttlMs: number;
|
|
27
|
+
/** When the last turn completed — the moment the cache was last written. */
|
|
28
|
+
lastTurnEndedAt?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Cached prefix *billed* on the last turn — a running session total, not a transcript size.
|
|
31
|
+
*
|
|
32
|
+
* The SDK sums `modelUsage` across a streaming session, so a long chat reports tens of
|
|
33
|
+
* millions against a context window of one. It is a usable floor for "has this session
|
|
34
|
+
* cached anything worth losing" and nothing more; never show it as a number.
|
|
35
|
+
*/
|
|
36
|
+
billedPrefixTokens?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Context the last turn actually held — the figure that may be displayed.
|
|
39
|
+
*
|
|
40
|
+
* Measured from one API call's own `usage` rather than summed (see
|
|
41
|
+
* `TurnUsage.contextTokens`). Absent for a turn recorded before PPM measured this, so the
|
|
42
|
+
* notice has to read correctly without it.
|
|
43
|
+
*/
|
|
44
|
+
contextTokens?: number;
|
|
45
|
+
/**
|
|
46
|
+
* When this session was compacted, if it has been since its last cache write.
|
|
47
|
+
*
|
|
48
|
+
* A compaction replaces the conversation with a summary, so the cached prefix no longer
|
|
49
|
+
* matches anything that will be sent — the cache is gone regardless of how recently it was
|
|
50
|
+
* written. Cleared again by the first API call after the boundary, which caches the new
|
|
51
|
+
* prefix; it therefore only survives a compaction that nothing followed, which is exactly
|
|
52
|
+
* the `/compact` the user is about to type into.
|
|
53
|
+
*/
|
|
54
|
+
compactedAt?: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Why a session's cache is gone. */
|
|
58
|
+
export type ColdReason = "expired" | "compacted";
|
|
59
|
+
|
|
60
|
+
export interface IdleCacheNotice {
|
|
61
|
+
/** How long since the last turn, or since the compaction, for the wording. */
|
|
62
|
+
idleMs: number;
|
|
63
|
+
reason: ColdReason;
|
|
64
|
+
/**
|
|
65
|
+
* Transcript that the next message re-sends, when PPM measured it.
|
|
66
|
+
*
|
|
67
|
+
* Never set for a compaction: what will be re-cached then is the summary the compaction
|
|
68
|
+
* produced, which no API call has reported a size for yet. Claude Code hardcodes the same
|
|
69
|
+
* `undefined` for that branch.
|
|
70
|
+
*/
|
|
71
|
+
contextTokens?: number;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The notice to show, or null for nothing worth saying.
|
|
76
|
+
*
|
|
77
|
+
* Silent in three cases, all of them deliberate. Before the TTL, because the cache really is
|
|
78
|
+
* still warm and a countdown to a cost that has not happened is just noise. Below
|
|
79
|
+
* `PREFIX_WARN_TOKENS`, because a session that has never billed even that much has nothing
|
|
80
|
+
* worth warning about — the same floor the after-the-fact warning uses, so the two cannot
|
|
81
|
+
* disagree about what is worth mentioning. And with no state at all, because "PPM has not
|
|
82
|
+
* measured this" and "this session has nothing cached" must not be reported as the same thing.
|
|
83
|
+
*/
|
|
84
|
+
export function idleCacheNotice(
|
|
85
|
+
state: PromptCacheState | null | undefined,
|
|
86
|
+
now: number,
|
|
87
|
+
): IdleCacheNotice | null {
|
|
88
|
+
const status = promptCacheStatus(state, now);
|
|
89
|
+
if (status.kind !== "cold") return null;
|
|
90
|
+
return {
|
|
91
|
+
idleMs: status.idleMs,
|
|
92
|
+
reason: status.reason,
|
|
93
|
+
...(status.contextTokens != null && { contextTokens: status.contextTokens }),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* The cache's clock, for a countdown that is on screen the whole time.
|
|
99
|
+
*
|
|
100
|
+
* Same three gates as the notice, deliberately: a chip that turns red at the hour while no
|
|
101
|
+
* banner appears — or the reverse — asks the user to reconcile two readings of one fact.
|
|
102
|
+
* `unknown` means PPM has not measured this session, which must render as nothing rather
|
|
103
|
+
* than as a full or empty timer.
|
|
104
|
+
*/
|
|
105
|
+
export type PromptCacheStatus =
|
|
106
|
+
| { kind: "unknown" }
|
|
107
|
+
| { kind: "warm"; remainingMs: number }
|
|
108
|
+
| { kind: "cold"; reason: ColdReason; idleMs: number; contextTokens?: number };
|
|
109
|
+
|
|
110
|
+
export function promptCacheStatus(
|
|
111
|
+
state: PromptCacheState | null | undefined,
|
|
112
|
+
now: number,
|
|
113
|
+
): PromptCacheStatus {
|
|
114
|
+
if (!state) return { kind: "unknown" };
|
|
115
|
+
|
|
116
|
+
// Before every other question, including whether anything has been measured at all. A
|
|
117
|
+
// compaction does not make the cache *stale*, it makes it inapplicable — the prefix it
|
|
118
|
+
// holds is not the conversation any more — so a turn that finished ten seconds ago is
|
|
119
|
+
// still cold. Ordered exactly as Claude Code orders it, and it also settles the floor
|
|
120
|
+
// below: a session large enough to have been compacted is never a trivial one.
|
|
121
|
+
if (state.compactedAt != null) {
|
|
122
|
+
return { kind: "cold", reason: "compacted", idleMs: Math.max(0, now - state.compactedAt) };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// No completed turn means nothing has been cached, so there is nothing to lose yet.
|
|
126
|
+
if (state.lastTurnEndedAt == null || state.billedPrefixTokens == null) return { kind: "unknown" };
|
|
127
|
+
if (state.billedPrefixTokens < PREFIX_WARN_TOKENS) return { kind: "unknown" };
|
|
128
|
+
|
|
129
|
+
const idleMs = now - state.lastTurnEndedAt;
|
|
130
|
+
// A clock that disagrees between server and browser can make this negative; a turn that
|
|
131
|
+
// just finished is the warmest case there is, so it reads as "not idle" either way.
|
|
132
|
+
if (idleMs < state.ttlMs) {
|
|
133
|
+
// Clamped, so a skewed clock shows a full window rather than one longer than the TTL.
|
|
134
|
+
return { kind: "warm", remainingMs: Math.min(state.ttlMs, state.ttlMs - idleMs) };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
kind: "cold",
|
|
139
|
+
reason: "expired",
|
|
140
|
+
idleMs,
|
|
141
|
+
...(state.contextTokens != null && { contextTokens: state.contextTokens }),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const MINUTE_MS = 60_000;
|
|
146
|
+
const HOUR_MS = 60 * MINUTE_MS;
|
|
147
|
+
const DAY_MS = 24 * HOUR_MS;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* How long the session has been idle, at the coarsest unit that still says something.
|
|
151
|
+
*
|
|
152
|
+
* Minutes are dropped past a day: "2d 7h 13m" is three figures to answer "is this stale",
|
|
153
|
+
* which is the only question being asked.
|
|
154
|
+
*/
|
|
155
|
+
export function formatIdleDuration(ms: number): string {
|
|
156
|
+
if (ms >= DAY_MS) {
|
|
157
|
+
const days = Math.floor(ms / DAY_MS);
|
|
158
|
+
const hours = Math.floor((ms % DAY_MS) / HOUR_MS);
|
|
159
|
+
return hours > 0 ? `${days}d ${hours}h` : `${days}d`;
|
|
160
|
+
}
|
|
161
|
+
if (ms >= HOUR_MS) {
|
|
162
|
+
const hours = Math.floor(ms / HOUR_MS);
|
|
163
|
+
const minutes = Math.floor((ms % HOUR_MS) / MINUTE_MS);
|
|
164
|
+
return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;
|
|
165
|
+
}
|
|
166
|
+
return `${Math.max(1, Math.floor(ms / MINUTE_MS))}m`;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Time left on the cache, for the composer's countdown chip.
|
|
171
|
+
*
|
|
172
|
+
* Rounded **up**, so a fresh turn reads the install's whole window (`60m`, not `59m`) and the
|
|
173
|
+
* last partial minute reads `1m` rather than `0m` — a zero here would say expired while the
|
|
174
|
+
* cache is still warm, which is the one reading the chip must never give.
|
|
175
|
+
*
|
|
176
|
+
* Minutes throughout, with no hours branch: the longest window PPM has is the subscription's
|
|
177
|
+
* hour, so the only thing an hours branch could ever render is the full window as `1h` — one
|
|
178
|
+
* more unit for the eye to parse, in the single case the chip is least interesting.
|
|
179
|
+
*/
|
|
180
|
+
export function formatCacheCountdown(ms: number): string {
|
|
181
|
+
return `${Math.max(1, Math.ceil(ms / MINUTE_MS))}m`;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* A measured context size, at the precision the decision needs.
|
|
186
|
+
*
|
|
187
|
+
* Whole thousands: the user is deciding whether to carry on in this chat or start a fresh
|
|
188
|
+
* one, and no part of that turns on the difference between 58.7k and 59k.
|
|
189
|
+
*/
|
|
190
|
+
export function formatContextTokens(tokens: number): string {
|
|
191
|
+
if (tokens >= 1_000_000) {
|
|
192
|
+
const millions = tokens / 1_000_000;
|
|
193
|
+
return `${millions >= 10 ? Math.round(millions) : millions.toFixed(1)}M`;
|
|
194
|
+
}
|
|
195
|
+
if (tokens >= 1_000) return `${Math.round(tokens / 1_000)}k`;
|
|
196
|
+
return `${tokens}`;
|
|
197
|
+
}
|
package/src/shared/turn-usage.ts
CHANGED
|
@@ -46,6 +46,36 @@ export interface TurnUsage {
|
|
|
46
46
|
*/
|
|
47
47
|
accountId?: string;
|
|
48
48
|
accountLabel?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Live context held at the end of the turn — what the next message actually replays.
|
|
51
|
+
*
|
|
52
|
+
* Not derivable from anything else on this type. Every other field here is summed out of
|
|
53
|
+
* the result's `modelUsage`, which the SDK accumulates across a streaming session and
|
|
54
|
+
* across subagents: one measured session reported 55.9M prefix tokens against a 200k
|
|
55
|
+
* window, and per-turn deltas fare no better (one turn's delta was 4.2M — twenty-one
|
|
56
|
+
* windows — because twenty subagents each replayed their own prefix into the same sum).
|
|
57
|
+
*
|
|
58
|
+
* This comes instead from the `usage` on the turn's last top-level assistant message,
|
|
59
|
+
* which is one API call's own input side and so is a real context size. Absent when no
|
|
60
|
+
* such message carried usage; never substitute a summed figure for it.
|
|
61
|
+
*/
|
|
62
|
+
contextTokens?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Cache window the API reported for this turn, when it reported one.
|
|
65
|
+
*
|
|
66
|
+
* Outranks the provider's credential-shaped guess wherever both exist — see
|
|
67
|
+
* `messageCacheTtl`. Absent on a turn that only read the cache, and on every turn recorded
|
|
68
|
+
* before PPM read this field.
|
|
69
|
+
*/
|
|
70
|
+
cacheTtlMs?: number;
|
|
71
|
+
/**
|
|
72
|
+
* When a compaction invalidated this session's cache, if one did and nothing re-cached after.
|
|
73
|
+
*
|
|
74
|
+
* Not a timestamp of "the last compaction" — the provider clears it on the next API call,
|
|
75
|
+
* so an auto-compact mid-turn never reaches here. What survives is a compaction the turn
|
|
76
|
+
* ended on, which is the case where the user's next message pays to rebuild the prefix.
|
|
77
|
+
*/
|
|
78
|
+
compactedAt?: number;
|
|
49
79
|
}
|
|
50
80
|
|
|
51
81
|
/** Total prefix replayed to the API this turn, cached or not. */
|
|
@@ -66,7 +96,7 @@ export function uncachedPrefixTokens(u: TurnUsage): number {
|
|
|
66
96
|
*/
|
|
67
97
|
export function buildTurnUsage(
|
|
68
98
|
modelUsage: Record<string, ModelUsageLike> | undefined,
|
|
69
|
-
opts: { coldReason?: string; accountId?: string; accountLabel?: string } = {},
|
|
99
|
+
opts: { coldReason?: string; accountId?: string; accountLabel?: string; contextTokens?: number; cacheTtlMs?: number; compactedAt?: number } = {},
|
|
70
100
|
): TurnUsage | undefined {
|
|
71
101
|
if (!modelUsage) return undefined;
|
|
72
102
|
const entries = Object.entries(modelUsage);
|
|
@@ -113,9 +143,63 @@ export function buildTurnUsage(
|
|
|
113
143
|
...(opts.coldReason && { coldReason: opts.coldReason }),
|
|
114
144
|
...(opts.accountId && { accountId: opts.accountId }),
|
|
115
145
|
...(opts.accountLabel && { accountLabel: opts.accountLabel }),
|
|
146
|
+
...(opts.contextTokens != null && { contextTokens: opts.contextTokens }),
|
|
147
|
+
...(opts.cacheTtlMs != null && { cacheTtlMs: opts.cacheTtlMs }),
|
|
148
|
+
...(opts.compactedAt != null && { compactedAt: opts.compactedAt }),
|
|
116
149
|
};
|
|
117
150
|
}
|
|
118
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Context size carried by one assistant message's `usage`, or undefined if it carried none.
|
|
154
|
+
*
|
|
155
|
+
* The input side of a single API call: what the model was actually given, whether it arrived
|
|
156
|
+
* fresh or out of the cache. Output tokens are excluded — they are not in the context the
|
|
157
|
+
* *next* call replays until they have been written back as a message, and counting them here
|
|
158
|
+
* would inflate every turn by its own answer.
|
|
159
|
+
*/
|
|
160
|
+
export function messageContextTokens(usage: unknown): number | undefined {
|
|
161
|
+
if (!usage || typeof usage !== "object") return undefined;
|
|
162
|
+
const u = usage as Record<string, unknown>;
|
|
163
|
+
const num = (v: unknown): number => (typeof v === "number" && Number.isFinite(v) ? v : 0);
|
|
164
|
+
const total = num(u.input_tokens) + num(u.cache_read_input_tokens) + num(u.cache_creation_input_tokens);
|
|
165
|
+
// Zero is not a context, it is a frame that carried no input side — a usage object with
|
|
166
|
+
// only output tokens, say. Returning it would render as "re-sends about 0 tokens" on a
|
|
167
|
+
// full session. Matches Claude Code's own reader, which likewise sums all three fields
|
|
168
|
+
// without requiring any one of them and rejects a zero total.
|
|
169
|
+
return total > 0 ? total : undefined;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Which prompt-cache window the API wrote this turn's prefix into. */
|
|
173
|
+
export type PromptCacheTtl = "1h" | "5m";
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* The cache lifetime the API itself reports, or undefined when it reported none.
|
|
177
|
+
*
|
|
178
|
+
* PPM otherwise *infers* this from the credential — an `sk-ant-oat` token means a
|
|
179
|
+
* subscription and therefore an hour, anything else five minutes — which is a guess about
|
|
180
|
+
* billing made from the shape of a string. It is wrong for a proxy, for a custom `base_url`,
|
|
181
|
+
* and for a subscription past its usage limits, and being wrong is not cosmetic: the
|
|
182
|
+
* countdown and the idle banner both measure against this, so a session whose cache really
|
|
183
|
+
* lives an hour is declared cold at minute five.
|
|
184
|
+
*
|
|
185
|
+
* `usage.cache_creation` answers it outright. Mirrors Claude Code's own reader, including
|
|
186
|
+
* the order: a prefix written into both windows is reported as the longer one, because that
|
|
187
|
+
* is the one still standing. Returns the discriminant rather than milliseconds so this stays
|
|
188
|
+
* free of the server's constants — `shared/` is imported by the browser bundle.
|
|
189
|
+
*/
|
|
190
|
+
export function messageCacheTtl(usage: unknown): PromptCacheTtl | undefined {
|
|
191
|
+
if (!usage || typeof usage !== "object") return undefined;
|
|
192
|
+
const cc = (usage as { cache_creation?: unknown }).cache_creation;
|
|
193
|
+
if (!cc || typeof cc !== "object") return undefined;
|
|
194
|
+
const c = cc as Record<string, unknown>;
|
|
195
|
+
const num = (v: unknown): number => (typeof v === "number" && Number.isFinite(v) ? v : 0);
|
|
196
|
+
if (num(c.ephemeral_1h_input_tokens) > 0) return "1h";
|
|
197
|
+
if (num(c.ephemeral_5m_input_tokens) > 0) return "5m";
|
|
198
|
+
// A turn that only *read* the cache writes nothing, so it names no window. That is silence,
|
|
199
|
+
// not five minutes: answering the short one here would expire a warm hour-long cache.
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
|
|
119
203
|
/**
|
|
120
204
|
* A prefix smaller than this is cheap however it is billed, so a poor hit rate on it is not
|
|
121
205
|
* worth interrupting the user over. Short sessions legitimately start cold.
|
|
@@ -84,9 +84,28 @@ export function parseCodexResetCredits(raw: unknown): ResetCredits | undefined {
|
|
|
84
84
|
available: available.length,
|
|
85
85
|
...(typeof next?.expiresAt === "number" ? { nextExpiresAt: new Date(next.expiresAt * 1000).toISOString() } : {}),
|
|
86
86
|
...(typeof next?.title === "string" ? { title: next.title } : {}),
|
|
87
|
+
...(typeof next?.id === "string" ? { nextCreditId: next.id } : {}),
|
|
87
88
|
};
|
|
88
89
|
}
|
|
89
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Whether a limit has actually been reached — at 100% of a window, as the card rounds it.
|
|
93
|
+
*
|
|
94
|
+
* The one rule both the "Use reset" button and the server's refusal follow, so the button can
|
|
95
|
+
* never offer what the server would turn down. Reached, not approaching: spending a reset at
|
|
96
|
+
* 90% throws away the 10% left *and* moves the weekly reset date (OpenAI: the next weekly reset
|
|
97
|
+
* is counted from when you continue, and the original one is not also granted).
|
|
98
|
+
*/
|
|
99
|
+
export function usageLimitReached(u: { session?: { utilization: number }; weekly?: { utilization: number } }): boolean {
|
|
100
|
+
const atCap = (util?: number) => Math.round((util ?? 0) * 100) >= 100;
|
|
101
|
+
return atCap(u.session?.utilization) || atCap(u.weekly?.utilization);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** A reset may be offered: a limit is reached and a credit is left to spend on it. */
|
|
105
|
+
export function canUseResetCredit(u: { session?: { utilization: number }; weekly?: { utilization: number }; resetCredits?: ResetCredits }): boolean {
|
|
106
|
+
return usageLimitReached(u) && (u.resetCredits?.available ?? 0) > 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
90
109
|
/** The extra fields of a `UsageInfo`, as the JSON column holds them — null when there are none. */
|
|
91
110
|
export function serializeUsageExtra(u: { weeklyScoped?: ScopedLimitBucket[]; resetCredits?: ResetCredits }): string | null {
|
|
92
111
|
const extra: UsageExtra = {};
|
package/src/types/chat.ts
CHANGED
|
@@ -230,6 +230,8 @@ export interface ResetCredits {
|
|
|
230
230
|
nextExpiresAt?: string;
|
|
231
231
|
/** What the soonest one resets, as Codex words it ("Full reset (Weekly + 5 hr)"). */
|
|
232
232
|
title?: string;
|
|
233
|
+
/** Codex's opaque id of that soonest-expiring credit — the one "Use reset" spends. */
|
|
234
|
+
nextCreditId?: string;
|
|
233
235
|
}
|
|
234
236
|
|
|
235
237
|
/** Result subtype from SDK ResultMessage */
|
|
@@ -280,4 +282,31 @@ export interface ChatMessage {
|
|
|
280
282
|
sdkUuid?: string;
|
|
281
283
|
/** Token split for the turn that produced this message; drives the cost warning. */
|
|
282
284
|
usage?: import("../shared/turn-usage").TurnUsage;
|
|
285
|
+
/**
|
|
286
|
+
* Set only on the compact-summary message that opens a post-compaction segment,
|
|
287
|
+
* so the divider above it can say what the compaction cost and saved.
|
|
288
|
+
*/
|
|
289
|
+
compaction?: CompactionInfo;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* What one compaction did, read back from the `compact_boundary` record Claude Code
|
|
294
|
+
* writes into the transcript.
|
|
295
|
+
*
|
|
296
|
+
* Taken from the file rather than from the live `compact_boundary` event because the
|
|
297
|
+
* figure has to survive a reload: the turn that compacts ends by refetching history,
|
|
298
|
+
* so a notice that existed only in WebSocket state would vanish seconds after it
|
|
299
|
+
* appeared. The event carries the same numbers and is deliberately not plumbed.
|
|
300
|
+
*/
|
|
301
|
+
export interface CompactionInfo {
|
|
302
|
+
/** `auto` when the context window forced it, `manual` when the user ran /compact. */
|
|
303
|
+
trigger: "manual" | "auto";
|
|
304
|
+
/** Transcript size going in. */
|
|
305
|
+
preTokens: number;
|
|
306
|
+
/** Size of the summary that replaced it. */
|
|
307
|
+
postTokens: number;
|
|
308
|
+
/** `preTokens - postTokens` — this compaction alone, not the session's running total. */
|
|
309
|
+
savedTokens: number;
|
|
310
|
+
/** How long the compaction took, when the record says. */
|
|
311
|
+
durationMs?: number;
|
|
283
312
|
}
|
package/src/types/config.ts
CHANGED
|
@@ -44,6 +44,14 @@ export interface PpmConfig {
|
|
|
44
44
|
* `zoneID`/`accountID` are pinned at setup and re-checked on every reuse.
|
|
45
45
|
*/
|
|
46
46
|
export interface TunnelConfig {
|
|
47
|
+
/**
|
|
48
|
+
* Master switch for the public tunnel. `false` means the supervisor spawns no
|
|
49
|
+
* cloudflared at all, whatever `mode` says — a machine reached over a LAN, a
|
|
50
|
+
* VPN or Tailscale gains nothing from a public URL and pays for it in
|
|
51
|
+
* exposure. Absent in rows written before this switch existed, so every
|
|
52
|
+
* reader must default it to `true`: the tunnel used to be unconditional.
|
|
53
|
+
*/
|
|
54
|
+
enabled: boolean;
|
|
47
55
|
mode: "quick" | "named";
|
|
48
56
|
namedTunnelName?: string;
|
|
49
57
|
namedTunnelHostname?: string;
|
|
@@ -176,6 +184,7 @@ export const DEFAULT_CONFIG: PpmConfig = {
|
|
|
176
184
|
debounce_ms: 2000,
|
|
177
185
|
},
|
|
178
186
|
tunnel: {
|
|
187
|
+
enabled: true,
|
|
179
188
|
mode: "quick",
|
|
180
189
|
},
|
|
181
190
|
};
|
|
@@ -348,6 +357,11 @@ export function sanitizeConfig(config: PpmConfig): boolean {
|
|
|
348
357
|
(config.tunnel.mode !== "quick" && config.tunnel.mode !== "named")) {
|
|
349
358
|
config.tunnel = structuredClone(DEFAULT_CONFIG.tunnel);
|
|
350
359
|
dirty = true;
|
|
360
|
+
} else if (typeof config.tunnel.enabled !== "boolean") {
|
|
361
|
+
// Written before the master switch existed, when the tunnel was
|
|
362
|
+
// unconditional — so an absent flag must read as on, never off.
|
|
363
|
+
config.tunnel.enabled = true;
|
|
364
|
+
dirty = true;
|
|
351
365
|
}
|
|
352
366
|
|
|
353
367
|
return dirty;
|
package/src/types/git.ts
CHANGED
|
@@ -21,6 +21,47 @@ export interface GitBranch {
|
|
|
21
21
|
remotes: string[];
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* One checkout target for the branch picker: a local branch, a remote-tracking
|
|
26
|
+
* branch or a tag, together with the commit it points at.
|
|
27
|
+
*
|
|
28
|
+
* Separate from `GitBranch` because that shape is what the graph draws and it
|
|
29
|
+
* carries no commit metadata — the picker needs an author, a subject and a date
|
|
30
|
+
* per row, and it needs tags, which `branches()` never returns.
|
|
31
|
+
*/
|
|
32
|
+
export interface GitRef {
|
|
33
|
+
/** Full ref name: `refs/heads/main`, `refs/remotes/origin/main`, `refs/tags/v1`. */
|
|
34
|
+
refName: string;
|
|
35
|
+
/** Short name, as a user reads it and as git checks it out by: `main`, `origin/main`, `v1`. */
|
|
36
|
+
name: string;
|
|
37
|
+
type: "branch" | "remote" | "tag";
|
|
38
|
+
/** True for the one local branch HEAD is on. */
|
|
39
|
+
current: boolean;
|
|
40
|
+
/** The commit this ref resolves to — dereferenced, so an annotated tag names its commit. */
|
|
41
|
+
hash: string;
|
|
42
|
+
shortHash: string;
|
|
43
|
+
subject: string;
|
|
44
|
+
author: string;
|
|
45
|
+
/** ISO 8601 commit date. */
|
|
46
|
+
date: string;
|
|
47
|
+
/** Upstream ref short name (`origin/main`), or null. Local branches only. */
|
|
48
|
+
upstream: string | null;
|
|
49
|
+
/** Commits ahead of / behind `upstream`; both 0 when there is none. */
|
|
50
|
+
ahead: number;
|
|
51
|
+
behind: number;
|
|
52
|
+
/** An upstream is configured but no longer exists on the remote. */
|
|
53
|
+
gone: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* How `git checkout` is asked to move HEAD.
|
|
58
|
+
*
|
|
59
|
+
* `track` exists because a remote-tracking ref is not a branch: plain
|
|
60
|
+
* `git checkout origin/foo` lands on a detached HEAD, and `-t` is what creates
|
|
61
|
+
* the local `foo` that follows it.
|
|
62
|
+
*/
|
|
63
|
+
export type CheckoutMode = "checkout" | "detach" | "track";
|
|
64
|
+
|
|
24
65
|
export interface GitStatus {
|
|
25
66
|
current: string | null;
|
|
26
67
|
/** Commits ahead of the upstream branch. */
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/** Static hardware facts for the Performance page — everything that does not change
|
|
2
|
+
* tick to tick, served once by GET /api/system/hardware instead of riding every 2 s
|
|
3
|
+
* snapshot over a tunnel. The client refetches when a snapshot names a device id it
|
|
4
|
+
* does not know (a USB disk plugged in, an interface created). Types + constants
|
|
5
|
+
* only. Import RELATIVELY — the "@" alias points at src/web. */
|
|
6
|
+
import type { GpuInfo, MetricsPlatform } from "./system-metrics.ts";
|
|
7
|
+
|
|
8
|
+
export type DiskKind = "hdd" | "ssd" | "nvme" | "emmc" | "sd" | "optical" | "thumb" | "unknown";
|
|
9
|
+
|
|
10
|
+
/** One place a partition is mounted. A partition can have several: a btrfs
|
|
11
|
+
* subvolume layout mounts the same device at `/`, `/home` and `/var/log`. */
|
|
12
|
+
export interface PartitionMount {
|
|
13
|
+
mountPoint: string;
|
|
14
|
+
filesystem: string;
|
|
15
|
+
/** From `statfs` on the mount, not from the partition's size — metadata,
|
|
16
|
+
* root-reserved blocks and a shared subvolume pool all make the two differ.
|
|
17
|
+
* Both absent when statfs refused; a filesystem we could not read is not an
|
|
18
|
+
* empty one. */
|
|
19
|
+
usedBytes?: number;
|
|
20
|
+
totalBytes?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface PartitionInfo {
|
|
24
|
+
/** Kernel name, e.g. "sda1". */
|
|
25
|
+
id: string;
|
|
26
|
+
devicePath: string;
|
|
27
|
+
/** What the partition table says, which is the number that never changes. */
|
|
28
|
+
sizeBytes: number;
|
|
29
|
+
/** udev's `ID_FS_TYPE`, so it is known even for a partition nothing mounted. */
|
|
30
|
+
filesystem?: string;
|
|
31
|
+
/** Empty for a partition that is not mounted anywhere. */
|
|
32
|
+
mounts: PartitionMount[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface DiskInfo {
|
|
36
|
+
/** /sys/block name — the key `DiskMetrics.id` uses. */
|
|
37
|
+
id: string;
|
|
38
|
+
/** Vendor + model as the drive reports them; absent when it reports neither. */
|
|
39
|
+
model?: string;
|
|
40
|
+
kind: DiskKind;
|
|
41
|
+
capacityBytes: number;
|
|
42
|
+
/** Holds the root filesystem (through partitions, LUKS or LVM). */
|
|
43
|
+
systemDisk: boolean;
|
|
44
|
+
removable: boolean;
|
|
45
|
+
serial?: string;
|
|
46
|
+
wwn?: string;
|
|
47
|
+
rotationRpm?: number;
|
|
48
|
+
/** Absent on a platform with no partition support yet; empty on a disk with no
|
|
49
|
+
* partition table (a whole-device filesystem, an unformatted drive). */
|
|
50
|
+
partitions?: PartitionInfo[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Mission Center's interface kinds. It classifies by name prefix because its
|
|
54
|
+
* NetworkManager type read always fails; PPM uses sysfs first and the same
|
|
55
|
+
* prefixes only as the fallback. */
|
|
56
|
+
export type NicKind =
|
|
57
|
+
| "wired" | "wireless" | "bluetooth" | "bridge" | "docker" | "infiniband"
|
|
58
|
+
| "multipass" | "virtual" | "vpn" | "other";
|
|
59
|
+
|
|
60
|
+
export interface NicInfo {
|
|
61
|
+
/** Interface name — the key `NicMetrics.id` uses. */
|
|
62
|
+
id: string;
|
|
63
|
+
kind: NicKind;
|
|
64
|
+
/** Adapter name from the PCI/USB database ("RTL8125 2.5GbE Controller"). */
|
|
65
|
+
deviceName?: string;
|
|
66
|
+
driver?: string;
|
|
67
|
+
/** Hardware address, absent for interfaces without one (tun, wireguard). */
|
|
68
|
+
mac?: string;
|
|
69
|
+
ipv4: string[];
|
|
70
|
+
ipv6: string[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Static CPU facts — Mission Center's CPU page header and its bottom grid. */
|
|
74
|
+
export interface CpuInfo {
|
|
75
|
+
/** Marketing name, e.g. "12th Gen Intel(R) Core(TM) i9-12900K". */
|
|
76
|
+
name: string;
|
|
77
|
+
/** Populated sockets. */
|
|
78
|
+
sockets: number;
|
|
79
|
+
/** Physical cores across all sockets, and hardware threads. On a hybrid part
|
|
80
|
+
* (Intel P+E) the physical count is what the kernel reports per socket. */
|
|
81
|
+
physicalCores: number;
|
|
82
|
+
logicalCores: number;
|
|
83
|
+
/** Nominal clock and the highest the driver will ask for, MHz. */
|
|
84
|
+
baseMHz?: number;
|
|
85
|
+
maxMHz?: number;
|
|
86
|
+
/** "Intel VT-x" / "AMD-V", absent when the flag is missing (or hidden in a VM). */
|
|
87
|
+
virtualization?: string;
|
|
88
|
+
/** True when this kernel is itself running virtualised. */
|
|
89
|
+
isVirtualMachine: boolean;
|
|
90
|
+
/** Summed over DISTINCT caches, bytes. L1 combines data and instruction, as
|
|
91
|
+
* Mission Center does. Absent when sysfs exposes no cache topology. */
|
|
92
|
+
l1CacheBytes?: number;
|
|
93
|
+
l2CacheBytes?: number;
|
|
94
|
+
l3CacheBytes?: number;
|
|
95
|
+
/** cpufreq's driver, governor and energy-performance preference. */
|
|
96
|
+
freqDriver?: string;
|
|
97
|
+
freqGovernor?: string;
|
|
98
|
+
powerPreference?: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** One populated memory slot, from the SMBIOS table udev already decoded. */
|
|
102
|
+
export interface MemoryDeviceInfo {
|
|
103
|
+
/** Slot name as the board labels it, e.g. "DDR4-A1". */
|
|
104
|
+
locator: string;
|
|
105
|
+
bankLocator?: string;
|
|
106
|
+
sizeBytes: number;
|
|
107
|
+
/** "DIMM", "SODIMM", … */
|
|
108
|
+
formFactor?: string;
|
|
109
|
+
/** "DDR4", "DDR5", … */
|
|
110
|
+
ramType?: string;
|
|
111
|
+
/** Configured transfer rate, MT/s. */
|
|
112
|
+
speedMts?: number;
|
|
113
|
+
manufacturer?: string;
|
|
114
|
+
rank?: number;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface MemoryInfo {
|
|
118
|
+
/** Populated slots. Empty when the firmware table is unreadable — the UI then
|
|
119
|
+
* shows the totals only, as Mission Center does inside a VM. */
|
|
120
|
+
devices: MemoryDeviceInfo[];
|
|
121
|
+
/** Slots the board has in total, when the firmware says. */
|
|
122
|
+
slotsTotal?: number;
|
|
123
|
+
/** Largest configuration the board accepts, bytes. */
|
|
124
|
+
maxCapacityBytes?: number;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface HardwareInventory {
|
|
128
|
+
platform: MetricsPlatform;
|
|
129
|
+
/** Epoch ms the inventory was read. */
|
|
130
|
+
ts: number;
|
|
131
|
+
disks: DiskInfo[];
|
|
132
|
+
nics: NicInfo[];
|
|
133
|
+
gpus: GpuInfo[];
|
|
134
|
+
/** Absent where the host exposes no CPU topology (never on Linux). */
|
|
135
|
+
cpu?: CpuInfo;
|
|
136
|
+
memory?: MemoryInfo;
|
|
137
|
+
}
|