@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,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One transcription = one `whisper-cli` run over a temp WAV.
|
|
3
|
+
*
|
|
4
|
+
* Per-request process rather than a long-lived `whisper-server`, for two
|
|
5
|
+
* reasons: Homebrew's formula builds with `WHISPER_BUILD_SERVER=OFF`, so a Mac
|
|
6
|
+
* has no server binary to talk to; and a resident server holds the model
|
|
7
|
+
* (574 MB) in RAM between sentences that are minutes apart.
|
|
8
|
+
*
|
|
9
|
+
* Runs are serialised. Two at once would each load the model and fight for the
|
|
10
|
+
* same cores, turning two five-second waits into two twelve-second ones.
|
|
11
|
+
*/
|
|
12
|
+
import { randomUUID } from "node:crypto";
|
|
13
|
+
import { mkdirSync, rmSync } from "node:fs";
|
|
14
|
+
import { availableParallelism } from "node:os";
|
|
15
|
+
import { resolve } from "node:path";
|
|
16
|
+
import { isInventedLine } from "./whisper-hallucinations.ts";
|
|
17
|
+
import { installedModel, vadModelPath } from "./whisper-install.service.ts";
|
|
18
|
+
import { findWhisperBinary, whisperModelDir, whisperTmpDir } from "./whisper-paths.ts";
|
|
19
|
+
|
|
20
|
+
const TIMEOUT_MS = 180_000;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* whisper.cpp defaults to 4 threads. Measured on a 24-thread i9-12900K with
|
|
24
|
+
* large-v3-turbo over a 10s clip: 4 threads 12.0s, 8 threads 8.1s, 16 threads
|
|
25
|
+
* 5.6s, 24 threads 5.4s — so it is worth raising, and worth capping where the
|
|
26
|
+
* curve flattens instead of taking every core the host has.
|
|
27
|
+
*/
|
|
28
|
+
export function threadCount(cpus: number = availableParallelism()): number {
|
|
29
|
+
return Math.max(1, Math.min(16, cpus));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** A non-speech annotation on a line of its own: "[BLANK_AUDIO]", "(nhạc)", "*gunshot*". */
|
|
33
|
+
const ANNOTATION = /^[[(*][^)\]*]*[\])*]$/;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* `-nt` prints text without timestamps, one line per segment. Three kinds of
|
|
37
|
+
* line are not something anyone dictated: an annotation, a line with no letter
|
|
38
|
+
* or digit in it at all (a bare "." is what this model makes of a hum in
|
|
39
|
+
* English), and a sentence it invented out of non-speech — see
|
|
40
|
+
* whisper-hallucinations.ts.
|
|
41
|
+
*/
|
|
42
|
+
export function parseWhisperText(stdout: string): string {
|
|
43
|
+
return stdout
|
|
44
|
+
.split("\n")
|
|
45
|
+
.map((line) => line.trim())
|
|
46
|
+
.filter(
|
|
47
|
+
(line) =>
|
|
48
|
+
line.length > 0 &&
|
|
49
|
+
!ANNOTATION.test(line) &&
|
|
50
|
+
/[\p{L}\p{N}]/u.test(line) &&
|
|
51
|
+
!isInventedLine(line),
|
|
52
|
+
)
|
|
53
|
+
.join(" ")
|
|
54
|
+
.replace(/\s+/g, " ")
|
|
55
|
+
.trim();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function whisperArgs(binary: string, wavPath: string, modelPath: string, language: string): string[] {
|
|
59
|
+
return [
|
|
60
|
+
binary,
|
|
61
|
+
"-m", modelPath,
|
|
62
|
+
"-f", wavPath,
|
|
63
|
+
"-l", language,
|
|
64
|
+
"-t", String(threadCount()),
|
|
65
|
+
"-nt",
|
|
66
|
+
"-np",
|
|
67
|
+
// Without VAD, silence is transcribed as an invented sentence — see whisper-catalog.ts.
|
|
68
|
+
"--vad",
|
|
69
|
+
"--vad-model", vadModelPath(),
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let queue: Promise<unknown> = Promise.resolve();
|
|
74
|
+
|
|
75
|
+
export interface TranscribeResult {
|
|
76
|
+
text: string;
|
|
77
|
+
/** Wall time of the whisper-cli run, for the UI's "took Ns" and for tuning. */
|
|
78
|
+
ms: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Throws when Whisper is not installed, the run fails, or it outruns the timeout. */
|
|
82
|
+
export async function transcribeWav(wav: Uint8Array, language = "vi"): Promise<TranscribeResult> {
|
|
83
|
+
const run = queue.then(() => runOnce(wav, language));
|
|
84
|
+
// Keep the chain alive after a failure, and never leak the rejection through it.
|
|
85
|
+
queue = run.catch(() => {});
|
|
86
|
+
return run;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function runOnce(wav: Uint8Array, language: string): Promise<TranscribeResult> {
|
|
90
|
+
const binary = findWhisperBinary();
|
|
91
|
+
const model = installedModel();
|
|
92
|
+
if (!binary || !model) throw new Error("Whisper is not installed on this host");
|
|
93
|
+
|
|
94
|
+
mkdirSync(whisperTmpDir(), { recursive: true });
|
|
95
|
+
const wavPath = resolve(whisperTmpDir(), `${randomUUID()}.wav`);
|
|
96
|
+
await Bun.write(wavPath, wav);
|
|
97
|
+
|
|
98
|
+
const started = Date.now();
|
|
99
|
+
try {
|
|
100
|
+
const cmd = whisperArgs(binary.path, wavPath, resolve(whisperModelDir(), model.file), language);
|
|
101
|
+
const proc = Bun.spawn({ cmd, stdout: "pipe", stderr: "pipe", stdin: "ignore", windowsHide: true });
|
|
102
|
+
const timer = setTimeout(() => proc.kill(), TIMEOUT_MS);
|
|
103
|
+
const [stdout, stderr, code] = await Promise.all([
|
|
104
|
+
new Response(proc.stdout).text(),
|
|
105
|
+
new Response(proc.stderr).text(),
|
|
106
|
+
proc.exited,
|
|
107
|
+
]);
|
|
108
|
+
clearTimeout(timer);
|
|
109
|
+
if (code !== 0) {
|
|
110
|
+
const detail = stderr.trim().split("\n").slice(-1)[0] ?? `exit ${code}`;
|
|
111
|
+
throw new Error(`whisper-cli failed: ${detail}`);
|
|
112
|
+
}
|
|
113
|
+
return { text: parseWhisperText(stdout), ms: Date.now() - started };
|
|
114
|
+
} finally {
|
|
115
|
+
rmSync(wavPath, { force: true });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
readAndDeleteCmd, readStatus, updateStatus, writeStatus,
|
|
21
21
|
STATUS_FILE, PID_FILE,
|
|
22
22
|
} from "./supervisor-state.ts";
|
|
23
|
-
import type
|
|
23
|
+
import { resolveTunnelConfig, type ResolvedTunnelConfig, type TunnelMode } from "./named-tunnel/named-tunnel-config.ts";
|
|
24
24
|
import { readTunnelConfigFresh, chooseTunnelSpawn } from "./named-tunnel/named-tunnel-runtime.ts";
|
|
25
25
|
import { waitForLogLine } from "./named-tunnel/named-tunnel-readiness.ts";
|
|
26
26
|
import { nextNamedRetryDelayMs } from "./named-tunnel/named-tunnel-retry.ts";
|
|
@@ -101,6 +101,11 @@ const TUNNEL_REGEN_MIN_INTERVAL_MS = 300_000; // 5min
|
|
|
101
101
|
// cache, never `configService` (a separate process, stale here) nor a fresh
|
|
102
102
|
// async DB read (would reorder the startup adopt/probe-before-spawn race).
|
|
103
103
|
let namedTunnelMode: ResolvedTunnelConfig | null = null;
|
|
104
|
+
// Effective master switch: the argv flag AND `tunnel.enabled` from config.
|
|
105
|
+
// Module-level rather than a local because the SIGUSR1 and Windows-command
|
|
106
|
+
// handlers close over it before startup reaches the config read, and because
|
|
107
|
+
// `retunnel` flips it live when the user toggles the switch.
|
|
108
|
+
let tunnelSharingEnabled = false;
|
|
104
109
|
// The mode of the tunnel actually spawned (as opposed to `namedTunnelMode`,
|
|
105
110
|
// which is merely the persisted intent) — a token failure leaves config=named
|
|
106
111
|
// but live=quick, and every status write / throttle / restart decision must
|
|
@@ -430,6 +435,26 @@ function restartTunnel(port: number) {
|
|
|
430
435
|
spawnTunnel(port).catch((e) => log("ERROR", `restartTunnel failed: ${e}`));
|
|
431
436
|
}
|
|
432
437
|
|
|
438
|
+
/**
|
|
439
|
+
* Tear the tunnel down for good because the master switch went off — as opposed
|
|
440
|
+
* to `restartTunnel`, which kills in order to respawn.
|
|
441
|
+
*
|
|
442
|
+
* Bumping the generation is the load-bearing part: the running spawn loop is
|
|
443
|
+
* awaiting its child's `exited` and would otherwise treat the kill as a crash
|
|
444
|
+
* and respawn. The probe needs no stopping — it returns early once there is no
|
|
445
|
+
* `tunnelUrl` and no live process.
|
|
446
|
+
*/
|
|
447
|
+
function stopTunnelForDisable(): void {
|
|
448
|
+
tunnelGeneration++;
|
|
449
|
+
cancelNamedRetry();
|
|
450
|
+
namedRetryAttempt = 0;
|
|
451
|
+
if (tunnelChild) { try { tunnelChild.kill(); } catch {} tunnelChild = null; }
|
|
452
|
+
if (adoptedTunnelPid) { try { process.kill(adoptedTunnelPid, "SIGTERM"); } catch {} adoptedTunnelPid = null; }
|
|
453
|
+
tunnelUrl = null;
|
|
454
|
+
tunnelPort = null;
|
|
455
|
+
updateStatus({ shareUrl: null, tunnelPid: null, tunnelPort: null });
|
|
456
|
+
}
|
|
457
|
+
|
|
433
458
|
// ─── Server shutdown ───────────────────────────────────────────────────
|
|
434
459
|
// On Windows the server's Claude SDK grandchildren are node-spawned (the
|
|
435
460
|
// provider forces `executable: "node"`), so they live OUTSIDE Bun's job
|
|
@@ -855,6 +880,14 @@ export async function spawnTunnel(port: number, generation: number = ++tunnelGen
|
|
|
855
880
|
// setup, disable, or token rotation since the last spawn must be picked up
|
|
856
881
|
// before deciding what to spawn next.
|
|
857
882
|
namedTunnelMode = await readTunnelConfigFresh();
|
|
883
|
+
// The freshest possible view of the master switch, so consult it here rather than
|
|
884
|
+
// relying on all six call sites remembering to. Two of them — the Windows
|
|
885
|
+
// leaked-probe-handle restart and the edge probe's respawns — do not, and a
|
|
886
|
+
// respawn is exactly when a switch flipped since the last spawn should take hold.
|
|
887
|
+
if (!namedTunnelMode.enabled) {
|
|
888
|
+
log("INFO", "Public tunnel is switched off — not spawning cloudflared");
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
858
891
|
|
|
859
892
|
let bin: string;
|
|
860
893
|
try {
|
|
@@ -1206,6 +1239,10 @@ async function probeNamedTunnelHealth(): Promise<boolean> {
|
|
|
1206
1239
|
}
|
|
1207
1240
|
|
|
1208
1241
|
function startTunnelProbe() {
|
|
1242
|
+
// Idempotent: a supervisor that booted with the tunnel switched off never
|
|
1243
|
+
// started this, and turning the switch on has to be able to start it then —
|
|
1244
|
+
// without leaving a second interval behind on the boots that did start it.
|
|
1245
|
+
if (tunnelProbeTimer) return;
|
|
1209
1246
|
tunnelProbeTimer = setInterval(async () => {
|
|
1210
1247
|
if (shuttingDown || !tunnelUrl) { tunnelFailCount = 0; return; }
|
|
1211
1248
|
if (!tunnelChild && !adoptedTunnelPid) { tunnelFailCount = 0; return; }
|
|
@@ -2049,7 +2086,16 @@ export async function runSupervisor(opts: {
|
|
|
2049
2086
|
// restarts the ladder so a later transient failure gets a full budget.
|
|
2050
2087
|
cancelNamedRetry();
|
|
2051
2088
|
namedRetryAttempt = 0;
|
|
2052
|
-
|
|
2089
|
+
// `retunnel` is also how the master switch is applied without a
|
|
2090
|
+
// restart, so it has to be able to mean "stop" and not only "respawn".
|
|
2091
|
+
tunnelSharingEnabled = _opts.share && namedTunnelMode.enabled;
|
|
2092
|
+
if (tunnelSharingEnabled) {
|
|
2093
|
+
startTunnelProbe();
|
|
2094
|
+
restartTunnel(_opts.port);
|
|
2095
|
+
} else {
|
|
2096
|
+
log("INFO", "Tunnel switched off — tearing down the running tunnel");
|
|
2097
|
+
stopTunnelForDisable();
|
|
2098
|
+
}
|
|
2053
2099
|
// Deliberate fall-through (no return): a bare `ppm restart` sends a
|
|
2054
2100
|
// bare SIGUSR2 with no command file of its own, and a `retunnel` that
|
|
2055
2101
|
// happens to still be unclaimed at that instant must not silently
|
|
@@ -2091,7 +2137,7 @@ export async function runSupervisor(opts: {
|
|
|
2091
2137
|
log("ERROR", `Self-replace failed: ${result.error}, restarting children`);
|
|
2092
2138
|
spawnServer(serverArgs, logFd);
|
|
2093
2139
|
// Tunnel was kept alive during selfReplace; only respawn if dead
|
|
2094
|
-
if (
|
|
2140
|
+
if (tunnelSharingEnabled && !tunnelChild && !tunnelUrl) spawnTunnel(_opts.port);
|
|
2095
2141
|
}
|
|
2096
2142
|
});
|
|
2097
2143
|
|
|
@@ -2200,7 +2246,16 @@ export async function runSupervisor(opts: {
|
|
|
2200
2246
|
tunnelFailCount = 0;
|
|
2201
2247
|
cancelNamedRetry();
|
|
2202
2248
|
namedRetryAttempt = 0;
|
|
2203
|
-
|
|
2249
|
+
// Same dual meaning as the POSIX path: this is how the master switch
|
|
2250
|
+
// is applied live, so it must also be able to mean "stop".
|
|
2251
|
+
tunnelSharingEnabled = _opts.share && cfg.enabled;
|
|
2252
|
+
if (tunnelSharingEnabled) {
|
|
2253
|
+
startTunnelProbe();
|
|
2254
|
+
restartTunnel(_opts.port);
|
|
2255
|
+
} else {
|
|
2256
|
+
log("INFO", "Tunnel switched off — tearing down the running tunnel");
|
|
2257
|
+
stopTunnelForDisable();
|
|
2258
|
+
}
|
|
2204
2259
|
});
|
|
2205
2260
|
}
|
|
2206
2261
|
else if (cmd.action === "upgrade") {
|
|
@@ -2209,7 +2264,7 @@ export async function runSupervisor(opts: {
|
|
|
2209
2264
|
if (!result.success) {
|
|
2210
2265
|
log("ERROR", `Self-replace failed: ${result.error}, restarting children`);
|
|
2211
2266
|
spawnServer(serverArgs, logFd);
|
|
2212
|
-
if (
|
|
2267
|
+
if (tunnelSharingEnabled && !tunnelChild && !tunnelUrl) spawnTunnel(_opts.port);
|
|
2213
2268
|
}
|
|
2214
2269
|
});
|
|
2215
2270
|
}
|
|
@@ -2229,12 +2284,34 @@ export async function runSupervisor(opts: {
|
|
|
2229
2284
|
// tunnel's origin port (public URL continuity), so adoption state must be
|
|
2230
2285
|
// settled first — the old order raced spawnServer's port selection.
|
|
2231
2286
|
let tunnelAdopted = false;
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2287
|
+
// Populate the cache BEFORE adoptTunnel/probe — an adopted tunnel skips
|
|
2288
|
+
// spawnTunnel entirely for this whole generation, so without this the
|
|
2289
|
+
// cache would stay null (adoptTunnel's named-hostname gate always refuses,
|
|
2290
|
+
// and the probe can never tell named from quick) until the next spawn.
|
|
2291
|
+
// It also carries the master switch, so it is read before the gate rather
|
|
2292
|
+
// than inside it.
|
|
2293
|
+
// This read must not be able to decide whether the edge below gets spawned.
|
|
2294
|
+
// It already did once: a `systemctl restart` brought this process up while
|
|
2295
|
+
// the outgoing one still held the database's write lock, the rejection ended
|
|
2296
|
+
// startup right here, and PPM ran for eight minutes with nothing listening on
|
|
2297
|
+
// its public port — the server child came back on the health check, which has
|
|
2298
|
+
// no equivalent for an edge that was never started in the first place.
|
|
2299
|
+
//
|
|
2300
|
+
// The fallback is sharing OFF, not the resolver's default: an absent config
|
|
2301
|
+
// row means "on" (it predates the master switch), so defaulting would publish
|
|
2302
|
+
// a tunnel for someone who had switched sharing off and whose config merely
|
|
2303
|
+
// could not be read.
|
|
2304
|
+
try {
|
|
2237
2305
|
namedTunnelMode = await readTunnelConfigFresh();
|
|
2306
|
+
} catch (e) {
|
|
2307
|
+
log("ERROR", `Tunnel config unreadable — continuing with sharing off: ${e}`);
|
|
2308
|
+
namedTunnelMode = resolveTunnelConfig({ enabled: false });
|
|
2309
|
+
}
|
|
2310
|
+
tunnelSharingEnabled = opts.share && namedTunnelMode.enabled;
|
|
2311
|
+
if (opts.share && !tunnelSharingEnabled) {
|
|
2312
|
+
log("INFO", "Tunnel off (tunnel.enabled = false) — no cloudflared will be started");
|
|
2313
|
+
}
|
|
2314
|
+
if (tunnelSharingEnabled) {
|
|
2238
2315
|
// Defensive — already `false` at module init, but a fresh boot must never
|
|
2239
2316
|
// start with an inherited restart-once budget "spent".
|
|
2240
2317
|
namedProbeRestartAttempted = false;
|
|
@@ -2250,6 +2327,12 @@ export async function runSupervisor(opts: {
|
|
|
2250
2327
|
// Sweep leftover cloudflared orphans (crashed supervisors / pre-fix stale
|
|
2251
2328
|
// loops) so they don't saturate the network and false-trigger regeneration.
|
|
2252
2329
|
await reapOrphanedTunnels(tunnelAdopted ? adoptedTunnelPid : null);
|
|
2330
|
+
} else if (opts.share) {
|
|
2331
|
+
// Switched off while a tunnel from an earlier boot is still alive: nothing
|
|
2332
|
+
// adopts or probes it now, so it would go on serving a stale origin with no
|
|
2333
|
+
// supervisor watching it.
|
|
2334
|
+
killStaleTunnel();
|
|
2335
|
+
await reapOrphanedTunnels(null);
|
|
2253
2336
|
}
|
|
2254
2337
|
|
|
2255
2338
|
// The edge owns the public port, so it must exist before anything else tries
|
|
@@ -2298,7 +2381,7 @@ export async function runSupervisor(opts: {
|
|
|
2298
2381
|
|
|
2299
2382
|
// Spawn server + (fresh) tunnel in parallel
|
|
2300
2383
|
const promises: Promise<void>[] = [spawnServer(serverArgs, logFd)];
|
|
2301
|
-
if (
|
|
2384
|
+
if (tunnelSharingEnabled && !tunnelAdopted) promises.push(spawnTunnel(_opts.port));
|
|
2302
2385
|
|
|
2303
2386
|
await Promise.all(promises);
|
|
2304
2387
|
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mission Center's CPU page, from `/sys/devices/system/cpu`, `/proc` and hwmon.
|
|
3
|
+
* Split in two: the static facts go in the hardware inventory (they cannot change
|
|
4
|
+
* while the kernel is up), the live ones ride the tick.
|
|
5
|
+
*
|
|
6
|
+
* Package power is RAPL's cumulative energy counter, so it needs two samples like
|
|
7
|
+
* any other rate — the caller keeps the previous one.
|
|
8
|
+
*/
|
|
9
|
+
import type { CpuInfo } from "../../types/system-hardware.ts";
|
|
10
|
+
import { readAttr, readNumber, realLinuxFs, type LinuxFs } from "./linux-fs.ts";
|
|
11
|
+
|
|
12
|
+
export const SYS_CPU = "/sys/devices/system/cpu";
|
|
13
|
+
const RAPL_DIR = "/sys/class/powercap";
|
|
14
|
+
const HWMON_DIR = "/sys/class/hwmon";
|
|
15
|
+
|
|
16
|
+
/** `/sys/class/hwmon/<h>/name` of the package sensor, in preference order. */
|
|
17
|
+
const PACKAGE_SENSORS = ["coretemp", "k10temp", "zenpower"];
|
|
18
|
+
|
|
19
|
+
// ---------------------------------------------------------------- static
|
|
20
|
+
|
|
21
|
+
export function readCpuInfo(fs: LinuxFs = realLinuxFs): CpuInfo | undefined {
|
|
22
|
+
const cpuinfo = fs.read("/proc/cpuinfo");
|
|
23
|
+
if (!cpuinfo) return undefined;
|
|
24
|
+
const topology = parseCpuinfoTopology(cpuinfo);
|
|
25
|
+
const caches = readCacheSizes(fs);
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
name: topology.model,
|
|
29
|
+
sockets: topology.sockets,
|
|
30
|
+
physicalCores: topology.physicalCores,
|
|
31
|
+
logicalCores: topology.logicalCores,
|
|
32
|
+
...defined("baseMHz", khzToMhz(readNumber(fs, `${SYS_CPU}/cpu0/cpufreq/base_frequency`))),
|
|
33
|
+
...defined("maxMHz", khzToMhz(readNumber(fs, `${SYS_CPU}/cpu0/cpufreq/cpuinfo_max_freq`))),
|
|
34
|
+
...defined("virtualization", virtualizationName(topology.flags)),
|
|
35
|
+
isVirtualMachine: topology.flags.has("hypervisor"),
|
|
36
|
+
...defined("l1CacheBytes", caches.l1),
|
|
37
|
+
...defined("l2CacheBytes", caches.l2),
|
|
38
|
+
...defined("l3CacheBytes", caches.l3),
|
|
39
|
+
...defined("freqDriver", readAttr(fs, `${SYS_CPU}/cpu0/cpufreq/scaling_driver`)),
|
|
40
|
+
...defined("freqGovernor", readAttr(fs, `${SYS_CPU}/cpu0/cpufreq/scaling_governor`)),
|
|
41
|
+
...defined("powerPreference", readAttr(fs, `${SYS_CPU}/cpu0/cpufreq/energy_performance_preference`)),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface CpuTopology {
|
|
46
|
+
model: string;
|
|
47
|
+
logicalCores: number;
|
|
48
|
+
physicalCores: number;
|
|
49
|
+
sockets: number;
|
|
50
|
+
flags: Set<string>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** `/proc/cpuinfo` is one block per logical CPU. Sockets are the distinct
|
|
54
|
+
* `physical id`s; physical cores are `cpu cores` summed once per socket, which
|
|
55
|
+
* is right for a hybrid part too — the kernel reports the real count there. */
|
|
56
|
+
export function parseCpuinfoTopology(text: string): CpuTopology {
|
|
57
|
+
let model = "";
|
|
58
|
+
const flags = new Set<string>();
|
|
59
|
+
const coresPerSocket = new Map<string, number>();
|
|
60
|
+
let logicalCores = 0;
|
|
61
|
+
let currentSocket = "0";
|
|
62
|
+
|
|
63
|
+
for (const line of text.split("\n")) {
|
|
64
|
+
const sep = line.indexOf(":");
|
|
65
|
+
if (sep < 0) continue;
|
|
66
|
+
const key = line.slice(0, sep).trim();
|
|
67
|
+
const value = line.slice(sep + 1).trim();
|
|
68
|
+
if (key === "processor") { logicalCores++; currentSocket = "0"; }
|
|
69
|
+
else if (key === "model name" && !model) model = value;
|
|
70
|
+
else if (key === "physical id") currentSocket = value;
|
|
71
|
+
else if (key === "cpu cores") coresPerSocket.set(currentSocket, Number(value) || 0);
|
|
72
|
+
else if (key === "flags" && flags.size === 0) for (const f of value.split(/\s+/)) flags.add(f);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const sockets = Math.max(coresPerSocket.size, 1);
|
|
76
|
+
let physicalCores = 0;
|
|
77
|
+
for (const n of coresPerSocket.values()) physicalCores += n;
|
|
78
|
+
return { model, logicalCores, physicalCores: physicalCores || logicalCores, sockets, flags };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Intel publishes `vmx`, AMD `svm`. Mission Center prints the marketing name. */
|
|
82
|
+
export function virtualizationName(flags: ReadonlySet<string>): string | undefined {
|
|
83
|
+
if (flags.has("vmx")) return "Intel VT-x";
|
|
84
|
+
if (flags.has("svm")) return "AMD-V";
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Cache sizes summed over DISTINCT caches: every CPU sharing one reports the
|
|
89
|
+
* same `shared_cpu_list`, so that string is the deduplication key. L1 combines
|
|
90
|
+
* data and instruction, which is what Mission Center shows as one figure. */
|
|
91
|
+
export function readCacheSizes(fs: Pick<LinuxFs, "list" | "read">): { l1?: number; l2?: number; l3?: number } {
|
|
92
|
+
const seen = new Set<string>();
|
|
93
|
+
const totals = new Map<number, number>();
|
|
94
|
+
|
|
95
|
+
for (const cpu of fs.list(SYS_CPU) ?? []) {
|
|
96
|
+
if (!/^cpu\d+$/.test(cpu)) continue;
|
|
97
|
+
const cacheDir = `${SYS_CPU}/${cpu}/cache`;
|
|
98
|
+
for (const index of fs.list(cacheDir) ?? []) {
|
|
99
|
+
if (!index.startsWith("index")) continue;
|
|
100
|
+
const dir = `${cacheDir}/${index}`;
|
|
101
|
+
const level = readNumber(fs, `${dir}/level`);
|
|
102
|
+
const size = parseCacheSize(readAttr(fs, `${dir}/size`));
|
|
103
|
+
const shared = readAttr(fs, `${dir}/shared_cpu_list`);
|
|
104
|
+
if (level === undefined || size === undefined) continue;
|
|
105
|
+
const key = `${level}:${readAttr(fs, `${dir}/type`) ?? ""}:${shared ?? `${cpu}/${index}`}`;
|
|
106
|
+
if (seen.has(key)) continue;
|
|
107
|
+
seen.add(key);
|
|
108
|
+
totals.set(level, (totals.get(level) ?? 0) + size);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
...defined("l1", totals.get(1)),
|
|
113
|
+
...defined("l2", totals.get(2)),
|
|
114
|
+
...defined("l3", totals.get(3)),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** sysfs writes cache sizes as "48K" / "30720K" / "16M". */
|
|
119
|
+
export function parseCacheSize(raw: string | undefined): number | undefined {
|
|
120
|
+
if (!raw) return undefined;
|
|
121
|
+
const m = /^(\d+)([KMG])?$/i.exec(raw.trim());
|
|
122
|
+
if (!m) return undefined;
|
|
123
|
+
const n = Number(m[1]);
|
|
124
|
+
const unit = (m[2] ?? "").toUpperCase();
|
|
125
|
+
const scale = unit === "G" ? 1024 ** 3 : unit === "M" ? 1024 ** 2 : unit === "K" ? 1024 : 1;
|
|
126
|
+
return n * scale;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ---------------------------------------------------------------- live
|
|
130
|
+
|
|
131
|
+
export interface RaplSample {
|
|
132
|
+
microjoules: number;
|
|
133
|
+
atSec: number;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface CpuLiveExtras {
|
|
137
|
+
currentMHz?: number;
|
|
138
|
+
tempC?: number;
|
|
139
|
+
powerW?: number;
|
|
140
|
+
threadCount?: number;
|
|
141
|
+
handleCount?: number;
|
|
142
|
+
uptimeSec?: number;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface CpuLiveResult {
|
|
146
|
+
extras: CpuLiveExtras;
|
|
147
|
+
/** RAPL baseline to hand back on the next tick; null when the host has none. */
|
|
148
|
+
rapl: RaplSample | null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function collectCpuLive(
|
|
152
|
+
prevRapl: RaplSample | null,
|
|
153
|
+
fs: Pick<LinuxFs, "list" | "read"> = realLinuxFs,
|
|
154
|
+
now: () => number = Date.now,
|
|
155
|
+
): CpuLiveResult {
|
|
156
|
+
const atSec = now() / 1000;
|
|
157
|
+
const rapl = readRaplEnergy(fs, atSec);
|
|
158
|
+
const loadavg = fs.read("/proc/loadavg") ?? "";
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
rapl,
|
|
162
|
+
extras: {
|
|
163
|
+
...defined("currentMHz", meanCurrentMHz(fs)),
|
|
164
|
+
...defined("tempC", readPackageTempC(fs)),
|
|
165
|
+
...defined("powerW", raplWatts(prevRapl, rapl)),
|
|
166
|
+
...defined("threadCount", parseThreadCount(loadavg)),
|
|
167
|
+
...defined("handleCount", parseHandleCount(fs.read("/proc/sys/fs/file-nr"))),
|
|
168
|
+
...defined("uptimeSec", parseUptimeSec(fs.read("/proc/uptime"))),
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** Mean of every online core's current clock. `scaling_cur_freq` is what the
|
|
174
|
+
* governor asked for; `cpuinfo_cur_freq` needs root on some drivers, so it is
|
|
175
|
+
* never read here. */
|
|
176
|
+
export function meanCurrentMHz(fs: Pick<LinuxFs, "list" | "read">): number | undefined {
|
|
177
|
+
let sum = 0;
|
|
178
|
+
let count = 0;
|
|
179
|
+
for (const cpu of fs.list(SYS_CPU) ?? []) {
|
|
180
|
+
if (!/^cpu\d+$/.test(cpu)) continue;
|
|
181
|
+
const khz = readNumber(fs, `${SYS_CPU}/${cpu}/cpufreq/scaling_cur_freq`);
|
|
182
|
+
if (khz === undefined) continue;
|
|
183
|
+
sum += khz;
|
|
184
|
+
count++;
|
|
185
|
+
}
|
|
186
|
+
return count > 0 ? Math.round(sum / count / 1000) : undefined;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** The package sensor, in preference order; `temp1_input` is the package on
|
|
190
|
+
* coretemp ("Package id 0") and the die on k10temp. */
|
|
191
|
+
export function readPackageTempC(fs: Pick<LinuxFs, "list" | "read">): number | undefined {
|
|
192
|
+
const chips = fs.list(HWMON_DIR) ?? [];
|
|
193
|
+
for (const wanted of PACKAGE_SENSORS) {
|
|
194
|
+
for (const chip of chips) {
|
|
195
|
+
if (readAttr(fs, `${HWMON_DIR}/${chip}/name`) !== wanted) continue;
|
|
196
|
+
const milli = readNumber(fs, `${HWMON_DIR}/${chip}/temp1_input`);
|
|
197
|
+
if (milli !== undefined) return Math.round(milli / 100) / 10;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** Sum of every RAPL package domain. Intel exposes `intel-rapl:N`, AMD the same
|
|
204
|
+
* interface; a host with neither (a VM, an ARM board) reports no power at all. */
|
|
205
|
+
export function readRaplEnergy(fs: Pick<LinuxFs, "list" | "read">, atSec: number): RaplSample | null {
|
|
206
|
+
let microjoules = 0;
|
|
207
|
+
let found = false;
|
|
208
|
+
for (const entry of fs.list(RAPL_DIR) ?? []) {
|
|
209
|
+
if (!/^intel-rapl:\d+$/.test(entry)) continue;
|
|
210
|
+
const name = readAttr(fs, `${RAPL_DIR}/${entry}/name`) ?? "";
|
|
211
|
+
if (!name.startsWith("package")) continue;
|
|
212
|
+
const uj = readNumber(fs, `${RAPL_DIR}/${entry}/energy_uj`);
|
|
213
|
+
if (uj === undefined) continue;
|
|
214
|
+
microjoules += uj;
|
|
215
|
+
found = true;
|
|
216
|
+
}
|
|
217
|
+
return found ? { microjoules, atSec } : null;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** Watts over the interval. The counter wraps at `max_energy_range_uj`, which a
|
|
221
|
+
* negative delta reveals — one unmeasured tick is better than a false spike. */
|
|
222
|
+
export function raplWatts(prev: RaplSample | null, next: RaplSample | null): number | undefined {
|
|
223
|
+
if (!prev || !next) return undefined;
|
|
224
|
+
const dt = next.atSec - prev.atSec;
|
|
225
|
+
const dj = next.microjoules - prev.microjoules;
|
|
226
|
+
if (!(dt > 0) || dj < 0) return undefined;
|
|
227
|
+
return Math.round(dj / dt / 1000) / 1000;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** `/proc/loadavg`'s fourth field is `running/total` kernel tasks. */
|
|
231
|
+
export function parseThreadCount(loadavg: string): number | undefined {
|
|
232
|
+
const m = /\s(\d+)\/(\d+)\s/.exec(` ${loadavg.trim()} `);
|
|
233
|
+
const n = m ? Number(m[2]) : NaN;
|
|
234
|
+
return Number.isFinite(n) ? n : undefined;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** `/proc/sys/fs/file-nr`: allocated, free, max. The first is the live count. */
|
|
238
|
+
export function parseHandleCount(fileNr: string | null): number | undefined {
|
|
239
|
+
const n = Number(fileNr?.trim().split(/\s+/)[0]);
|
|
240
|
+
return Number.isFinite(n) ? n : undefined;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export function parseUptimeSec(uptime: string | null): number | undefined {
|
|
244
|
+
const n = Number(uptime?.trim().split(/\s+/)[0]);
|
|
245
|
+
return Number.isFinite(n) ? Math.round(n) : undefined;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const khzToMhz = (khz: number | undefined) => (khz === undefined ? undefined : Math.round(khz / 1000));
|
|
249
|
+
|
|
250
|
+
function defined<K extends string, V>(key: K, value: V | undefined): Partial<Record<K, V>> {
|
|
251
|
+
return value === undefined ? {} : ({ [key]: value } as Record<K, V>);
|
|
252
|
+
}
|