@hienlh/ppm 0.23.6 → 0.23.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +84 -0
- package/CLAUDE.md +21 -1
- package/Dockerfile.test +8 -1
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/cli-reference.md +4 -4
- package/assets/skills/ppm/references/http-api.md +29 -1
- package/dist/web/assets/accounts-settings-section-BYWnY9hH.js +1 -0
- package/dist/web/assets/accounts-settings-section-BYWnY9hH.js.br +0 -0
- package/dist/web/assets/accounts-settings-section-BYWnY9hH.js.gz +0 -0
- package/dist/web/assets/{ai-resource-editor-Dn_wB-o5.js → ai-resource-editor-CY4n_Ccv.js} +1 -1
- package/dist/web/assets/ai-resource-editor-CY4n_Ccv.js.br +0 -0
- package/dist/web/assets/ai-resource-editor-CY4n_Ccv.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-Bs3iUW4j.js +1 -0
- package/dist/web/assets/ai-settings-section-Bs3iUW4j.js.br +0 -0
- package/dist/web/assets/ai-settings-section-Bs3iUW4j.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-DDs11XV4.js +1 -0
- package/dist/web/assets/api-client-CJPnCOG-.js +1 -0
- package/dist/web/assets/{api-client-c8YOpTlT.js → api-client-D-SMbdiH.js} +1 -1
- package/dist/web/assets/api-client-D-SMbdiH.js.br +0 -0
- package/dist/web/assets/api-client-D-SMbdiH.js.gz +0 -0
- package/dist/web/assets/api-settings-BDkkhFMq.js +1 -0
- package/dist/web/assets/{api-settings-BmvNoCbn.js → api-settings-Bv9mLCty.js} +1 -1
- package/dist/web/assets/api-settings-Bv9mLCty.js.br +0 -0
- package/dist/web/assets/api-settings-Bv9mLCty.js.gz +0 -0
- package/dist/web/assets/{api-themes-6fOQJgM9.js → api-themes-3wW-zLzU.js} +1 -1
- package/dist/web/assets/appearance-settings-section-C0BoIBmz.js +1 -0
- package/dist/web/assets/appearance-settings-section-C0BoIBmz.js.br +0 -0
- package/dist/web/assets/appearance-settings-section-C0BoIBmz.js.gz +0 -0
- package/dist/web/assets/apps-panel-DXAFsveZ.js +1 -0
- package/dist/web/assets/apps-panel-DXAFsveZ.js.br +0 -0
- package/dist/web/assets/apps-panel-DXAFsveZ.js.gz +0 -0
- package/dist/web/assets/{audio-preview-vaG2cB-k.js → audio-preview-BfES4Cx5.js} +1 -1
- package/dist/web/assets/audio-preview-BfES4Cx5.js.br +0 -0
- package/dist/web/assets/audio-preview-BfES4Cx5.js.gz +0 -0
- package/dist/web/assets/branch-review-tab-CA8hPSX9.js +1 -0
- package/dist/web/assets/branch-review-tab-CA8hPSX9.js.br +0 -0
- package/dist/web/assets/branch-review-tab-CA8hPSX9.js.gz +0 -0
- package/dist/web/assets/{button-Ci9EUgqd.js → button-DeAyLH9U.js} +1 -1
- package/dist/web/assets/button-DeAyLH9U.js.br +0 -0
- package/dist/web/assets/button-DeAyLH9U.js.gz +0 -0
- package/dist/web/assets/{chat-preparation-cache-BSIQGiWx.js → chat-preparation-cache-CcCd2g7A.js} +1 -1
- package/dist/web/assets/chat-preparation-cache-CcCd2g7A.js.br +0 -0
- package/dist/web/assets/chat-preparation-cache-CcCd2g7A.js.gz +0 -0
- package/dist/web/assets/chat-tab-BWi_bUzA.js +1 -0
- package/dist/web/assets/chat-tab-BWi_bUzA.js.br +0 -0
- package/dist/web/assets/chat-tab-BWi_bUzA.js.gz +0 -0
- package/dist/web/assets/chat-tab-BvJhIaVE.js +15 -0
- package/dist/web/assets/chat-tab-BvJhIaVE.js.br +0 -0
- package/dist/web/assets/chat-tab-BvJhIaVE.js.gz +0 -0
- package/dist/web/assets/code-editor-OJUdLVnn.js +7 -0
- package/dist/web/assets/code-editor-OJUdLVnn.js.br +0 -0
- package/dist/web/assets/code-editor-OJUdLVnn.js.gz +0 -0
- package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js +1 -0
- package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js.br +0 -0
- package/dist/web/assets/codex-reset-credit-button-Dgxy_VNp.js.gz +0 -0
- package/dist/web/assets/{conflict-editor-BA3y-qSH.js → conflict-editor-BpKW_vbL.js} +1 -1
- package/dist/web/assets/conflict-editor-BpKW_vbL.js.br +0 -0
- package/dist/web/assets/conflict-editor-BpKW_vbL.js.gz +0 -0
- package/dist/web/assets/context-menu-7OX80HDB.js +1 -0
- package/dist/web/assets/context-menu-7OX80HDB.js.br +0 -0
- package/dist/web/assets/context-menu-7OX80HDB.js.gz +0 -0
- package/dist/web/assets/{csv-preview-BioxkrQF.js → csv-preview-COYdTABa.js} +1 -1
- package/dist/web/assets/csv-preview-COYdTABa.js.br +0 -0
- package/dist/web/assets/csv-preview-COYdTABa.js.gz +0 -0
- package/dist/web/assets/{data-grid-overlay-editor-CQRVKr7y.js → data-grid-overlay-editor-CeZoduke.js} +1 -1
- package/dist/web/assets/data-grid-overlay-editor-CeZoduke.js.br +0 -0
- package/dist/web/assets/data-grid-overlay-editor-CeZoduke.js.gz +0 -0
- package/dist/web/assets/{database-viewer-BSoJ0E6p.js → database-viewer-BQcBqCKm.js} +1 -1
- package/dist/web/assets/database-viewer-BQcBqCKm.js.br +0 -0
- package/dist/web/assets/database-viewer-BQcBqCKm.js.gz +0 -0
- package/dist/web/assets/{design-export-client-ChMcMoqW.js → design-export-client-OrnGCSwu.js} +1 -1
- package/dist/web/assets/design-export-client-OrnGCSwu.js.br +0 -0
- package/dist/web/assets/design-export-client-OrnGCSwu.js.gz +0 -0
- package/dist/web/assets/{design-responsive-dialog-DNBhJJLf.js → design-responsive-dialog-vJjQrC4n.js} +1 -1
- package/dist/web/assets/design-responsive-dialog-vJjQrC4n.js.br +0 -0
- package/dist/web/assets/design-responsive-dialog-vJjQrC4n.js.gz +0 -0
- package/dist/web/assets/design-tab-BbmFk38H.js +33 -0
- package/dist/web/assets/design-tab-BbmFk38H.js.br +0 -0
- package/dist/web/assets/design-tab-BbmFk38H.js.gz +0 -0
- package/dist/web/assets/{designs-sidebar-panel-DHh5QsH9.js → designs-sidebar-panel-D2kXwB8B.js} +1 -1
- package/dist/web/assets/designs-sidebar-panel-D2kXwB8B.js.br +0 -0
- package/dist/web/assets/designs-sidebar-panel-D2kXwB8B.js.gz +0 -0
- package/dist/web/assets/dialog-Bocc0Fgb.js +1 -0
- package/dist/web/assets/dialog-Bocc0Fgb.js.br +0 -0
- package/dist/web/assets/dialog-Bocc0Fgb.js.gz +0 -0
- package/dist/web/assets/{diff-viewer-lctWoSmG.js → diff-viewer-Bj4DT6Mj.js} +1 -1
- package/dist/web/assets/diff-viewer-Bj4DT6Mj.js.br +0 -0
- package/dist/web/assets/diff-viewer-Bj4DT6Mj.js.gz +0 -0
- package/dist/web/assets/{docx-preview-C9XdKEj1.js → docx-preview-C2QqNGRE.js} +1 -1
- package/dist/web/assets/docx-preview-C2QqNGRE.js.br +0 -0
- package/dist/web/assets/docx-preview-C2QqNGRE.js.gz +0 -0
- package/dist/web/assets/editor-language-service-COqB2tuv.js +1 -0
- package/dist/web/assets/editor-language-service-COqB2tuv.js.br +3 -0
- package/dist/web/assets/editor-language-service-COqB2tuv.js.gz +0 -0
- package/dist/web/assets/explorer-body-DGrYajDN.js +2 -0
- package/dist/web/assets/explorer-body-DGrYajDN.js.br +0 -0
- package/dist/web/assets/explorer-body-DGrYajDN.js.gz +0 -0
- package/dist/web/assets/explorer-window-content-DLzkODTP.js +1 -0
- package/dist/web/assets/explorer-window-content-DLzkODTP.js.br +0 -0
- package/dist/web/assets/explorer-window-content-DLzkODTP.js.gz +0 -0
- package/dist/web/assets/{extension-manager-section-rbkXsZVR.js → extension-manager-section-Bu0qcB2i.js} +1 -1
- package/dist/web/assets/extension-manager-section-Bu0qcB2i.js.br +0 -0
- package/dist/web/assets/extension-manager-section-Bu0qcB2i.js.gz +0 -0
- package/dist/web/assets/{extension-webview-uPO0WgCq.js → extension-webview-G_WJ0N52.js} +1 -1
- package/dist/web/assets/extension-webview-G_WJ0N52.js.br +0 -0
- package/dist/web/assets/extension-webview-G_WJ0N52.js.gz +0 -0
- package/dist/web/assets/{file-icons-gx_FBOXY.js → file-icons-l7fNOmdS.js} +1 -1
- package/dist/web/assets/file-icons-l7fNOmdS.js.br +0 -0
- package/dist/web/assets/file-icons-l7fNOmdS.js.gz +0 -0
- package/dist/web/assets/{file-store-D9KE0kQC.js → file-store-B0e7sLag.js} +1 -1
- package/dist/web/assets/file-store-B0e7sLag.js.br +0 -0
- package/dist/web/assets/file-store-B0e7sLag.js.gz +0 -0
- package/dist/web/assets/{files-settings-section-CT7mDb0L.js → files-settings-section-ChZ_CynX.js} +1 -1
- package/dist/web/assets/files-settings-section-ChZ_CynX.js.br +0 -0
- package/dist/web/assets/files-settings-section-ChZ_CynX.js.gz +0 -0
- package/dist/web/assets/format-bytes-__396eCN.js +1 -0
- package/dist/web/assets/{format-file-meta-mQwA6SuY.js → format-file-meta-o1XBuoKS.js} +1 -1
- package/dist/web/assets/format-file-meta-o1XBuoKS.js.br +0 -0
- package/dist/web/assets/format-file-meta-o1XBuoKS.js.gz +0 -0
- package/dist/web/assets/{fs-api-DL36slbd.js → fs-api-CeHKwx95.js} +1 -1
- package/dist/web/assets/fs-api-CeHKwx95.js.br +0 -0
- package/dist/web/assets/fs-api-CeHKwx95.js.gz +0 -0
- package/dist/web/assets/{general-settings-section-DANPfMRN.js → general-settings-section-MSvDEbFa.js} +1 -1
- package/dist/web/assets/general-settings-section-MSvDEbFa.js.br +0 -0
- package/dist/web/assets/general-settings-section-MSvDEbFa.js.gz +0 -0
- package/dist/web/assets/{git-log-panel-BJPkLiEw.js → git-log-panel-gw5_a6j3.js} +1 -1
- package/dist/web/assets/git-log-panel-gw5_a6j3.js.br +0 -0
- package/dist/web/assets/git-log-panel-gw5_a6j3.js.gz +0 -0
- package/dist/web/assets/{git-repo-store-DSypNj19.js → git-repo-store-BpPnah5l.js} +1 -1
- package/dist/web/assets/git-repo-store-BpPnah5l.js.br +0 -0
- package/dist/web/assets/git-repo-store-BpPnah5l.js.gz +0 -0
- package/dist/web/assets/{glide-data-grid-R4PcAntf.js → glide-data-grid-Db2Cl26B.js} +5 -5
- package/dist/web/assets/glide-data-grid-Db2Cl26B.js.br +0 -0
- package/dist/web/assets/glide-data-grid-Db2Cl26B.js.gz +0 -0
- package/dist/web/assets/group-chat-tab-B4etmYTR.js +1 -0
- package/dist/web/assets/group-chat-tab-B4etmYTR.js.br +0 -0
- package/dist/web/assets/group-chat-tab-B4etmYTR.js.gz +0 -0
- package/dist/web/assets/{image-preview-CGdZrmLo.js → image-preview-CjNhpfWw.js} +1 -1
- package/dist/web/assets/index-CtAvmybi.js +52 -0
- package/dist/web/assets/index-CtAvmybi.js.br +0 -0
- package/dist/web/assets/index-CtAvmybi.js.gz +0 -0
- package/dist/web/assets/index-DeCJasyy.css +1 -0
- package/dist/web/assets/index-DeCJasyy.css.br +0 -0
- package/dist/web/assets/index-DeCJasyy.css.gz +0 -0
- package/dist/web/assets/{jira-watcher-section-DHRoyWcG.js → jira-watcher-section-CKSI1Alo.js} +1 -1
- package/dist/web/assets/keybindings-store-C4_yyU4u.js +1 -0
- package/dist/web/assets/{keyboard-shortcuts-section-BKej4mUf.js → keyboard-shortcuts-section-CEaVUc9a.js} +1 -1
- package/dist/web/assets/keyboard-shortcuts-section-CEaVUc9a.js.br +0 -0
- package/dist/web/assets/keyboard-shortcuts-section-CEaVUc9a.js.gz +0 -0
- package/dist/web/assets/language-servers-section-ePtEpnDc.js +2 -0
- package/dist/web/assets/language-servers-section-ePtEpnDc.js.br +0 -0
- package/dist/web/assets/language-servers-section-ePtEpnDc.js.gz +0 -0
- package/dist/web/assets/lsp-client-XzmR3Brr.js +1 -0
- package/dist/web/assets/lsp-client-XzmR3Brr.js.br +0 -0
- package/dist/web/assets/lsp-client-XzmR3Brr.js.gz +0 -0
- package/dist/web/assets/markdown-renderer-CTtDap-l.js +1 -0
- package/dist/web/assets/{markdown-renderer-BHtYqkYZ.js → markdown-renderer-D05fAr57.js} +2 -2
- package/dist/web/assets/markdown-renderer-D05fAr57.js.br +0 -0
- package/dist/web/assets/markdown-renderer-D05fAr57.js.gz +0 -0
- package/dist/web/assets/{media-url-CzUJrREv.js → media-url-C6NumuN5.js} +1 -1
- package/dist/web/assets/metric-chart-canvas-DHJe0VER.js +1 -0
- package/dist/web/assets/metric-chart-canvas-DHJe0VER.js.br +0 -0
- package/dist/web/assets/metric-chart-canvas-DHJe0VER.js.gz +0 -0
- package/dist/web/assets/{mobile-bottom-sheet-CuNi2FRv.js → mobile-bottom-sheet-D4UyOatB.js} +1 -1
- package/dist/web/assets/mobile-bottom-sheet-D4UyOatB.js.br +0 -0
- package/dist/web/assets/mobile-bottom-sheet-D4UyOatB.js.gz +0 -0
- package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js +1 -0
- package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js.br +0 -0
- package/dist/web/assets/mobile-explorer-sheet-CcfGdGL8.js.gz +0 -0
- package/dist/web/assets/{new-design-dialog-DS_XrpTG.js → new-design-dialog-BgmQopJM.js} +1 -1
- package/dist/web/assets/new-design-dialog-BgmQopJM.js.br +0 -0
- package/dist/web/assets/new-design-dialog-BgmQopJM.js.gz +0 -0
- package/dist/web/assets/notification-store-q5QBklKA.js +1 -0
- package/dist/web/assets/{notifications-settings-section-C05WYqcE.js → notifications-settings-section-BBJ0r9OS.js} +1 -1
- package/dist/web/assets/notifications-settings-section-BBJ0r9OS.js.br +0 -0
- package/dist/web/assets/notifications-settings-section-BBJ0r9OS.js.gz +0 -0
- package/dist/web/assets/{onboarding-entry-CmUqv1kl.js → onboarding-entry-BYOYswsi.js} +1 -1
- package/dist/web/assets/onboarding-entry-BYOYswsi.js.br +0 -0
- package/dist/web/assets/onboarding-entry-BYOYswsi.js.gz +0 -0
- package/dist/web/assets/{onboarding-quick-orientation-DIhWv1CN.js → onboarding-quick-orientation-DPHYFMbA.js} +1 -1
- package/dist/web/assets/onboarding-quick-orientation-DPHYFMbA.js.br +0 -0
- package/dist/web/assets/onboarding-quick-orientation-DPHYFMbA.js.gz +0 -0
- package/dist/web/assets/overview-panel-pkPs44Tv.js +1 -0
- package/dist/web/assets/overview-panel-pkPs44Tv.js.br +0 -0
- package/dist/web/assets/overview-panel-pkPs44Tv.js.gz +0 -0
- package/dist/web/assets/{pdf-preview-qdXmMkOR.js → pdf-preview-c-L_kDAs.js} +1 -1
- package/dist/web/assets/pdf-preview-c-L_kDAs.js.br +0 -0
- package/dist/web/assets/pdf-preview-c-L_kDAs.js.gz +0 -0
- package/dist/web/assets/performance-panel-yPrq0DJV.js +3 -0
- package/dist/web/assets/performance-panel-yPrq0DJV.js.br +0 -0
- package/dist/web/assets/performance-panel-yPrq0DJV.js.gz +0 -0
- package/dist/web/assets/{postgres-viewer-Xvlun_n5.js → postgres-viewer-CnwDCMNd.js} +1 -1
- package/dist/web/assets/postgres-viewer-CnwDCMNd.js.br +0 -0
- package/dist/web/assets/postgres-viewer-CnwDCMNd.js.gz +0 -0
- package/dist/web/assets/{ppmbot-settings-section-D8AES1BA.js → ppmbot-settings-section-BDXoSIDp.js} +1 -1
- package/dist/web/assets/ppmbot-settings-section-BDXoSIDp.js.br +0 -0
- package/dist/web/assets/ppmbot-settings-section-BDXoSIDp.js.gz +0 -0
- package/dist/web/assets/{pptx-export-CG6MRNok.js → pptx-export-D0RDY48h.js} +4 -4
- package/dist/web/assets/pptx-export-D0RDY48h.js.br +0 -0
- package/dist/web/assets/pptx-export-D0RDY48h.js.gz +0 -0
- package/dist/web/assets/{problems-panel-DTBG4beI.js → problems-panel-BgY8oyo9.js} +1 -1
- package/dist/web/assets/problems-panel-BgY8oyo9.js.br +0 -0
- package/dist/web/assets/problems-panel-BgY8oyo9.js.gz +0 -0
- package/dist/web/assets/process-row-format-CaaMcHzn.js +1 -0
- package/dist/web/assets/process-table-BOwDtXuG.js +1 -0
- package/dist/web/assets/process-table-BOwDtXuG.js.br +0 -0
- package/dist/web/assets/process-table-BOwDtXuG.js.gz +0 -0
- package/dist/web/assets/{project-framework-store-XxFXcUpb.js → project-framework-store-UDEMu28U.js} +1 -1
- package/dist/web/assets/{project-store-C5gJXkvb.js → project-store-DGa31y5B.js} +1 -1
- package/dist/web/assets/project-store-DGa31y5B.js.br +0 -0
- package/dist/web/assets/project-store-DGa31y5B.js.gz +0 -0
- package/dist/web/assets/{proxy-settings-section-CqtmbeRj.js → proxy-settings-section-Db6Kc6xG.js} +1 -1
- package/dist/web/assets/proxy-settings-section-Db6Kc6xG.js.br +0 -0
- package/dist/web/assets/proxy-settings-section-Db6Kc6xG.js.gz +0 -0
- package/dist/web/assets/{query-audit-section-UKG_smyt.js → query-audit-section-C0PAXhfT.js} +1 -1
- package/dist/web/assets/query-audit-section-C0PAXhfT.js.br +0 -0
- package/dist/web/assets/query-audit-section-C0PAXhfT.js.gz +0 -0
- package/dist/web/assets/{remote-desktop-clipboard-notice-Djt6cpNL.js → remote-desktop-clipboard-notice-DOVtobj_.js} +1 -1
- package/dist/web/assets/remote-desktop-clipboard-notice-DOVtobj_.js.br +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-DOVtobj_.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js +2 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-DXlU3msM.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js +1 -0
- package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-ClV4YTLU.js.gz +0 -0
- package/dist/web/assets/{remote-desktop-readiness-gate-DNJF8TcF.js → remote-desktop-readiness-gate-BsfoJzdc.js} +1 -1
- package/dist/web/assets/remote-desktop-readiness-gate-BsfoJzdc.js.br +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-BsfoJzdc.js.gz +0 -0
- package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js +1 -0
- package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js.br +0 -0
- package/dist/web/assets/remote-desktop-window-content-kDaXl1_Q.js.gz +0 -0
- package/dist/web/assets/{schedules-settings-section-BKoPovy2.js → schedules-settings-section-CvbjQM8z.js} +1 -1
- package/dist/web/assets/schedules-settings-section-CvbjQM8z.js.br +0 -0
- package/dist/web/assets/schedules-settings-section-CvbjQM8z.js.gz +0 -0
- package/dist/web/assets/{scroll-area-XonvWYn_.js → scroll-area-sjOeAfoD.js} +1 -1
- package/dist/web/assets/scroll-area-sjOeAfoD.js.br +0 -0
- package/dist/web/assets/scroll-area-sjOeAfoD.js.gz +0 -0
- package/dist/web/assets/{separator-sQj04Ari.js → separator-9A3PCG1t.js} +1 -1
- package/dist/web/assets/services-panel-CimW47P8.js +1 -0
- package/dist/web/assets/services-panel-CimW47P8.js.br +0 -0
- package/dist/web/assets/services-panel-CimW47P8.js.gz +0 -0
- package/dist/web/assets/settings-body-BTXNtpWL.js +2 -0
- package/dist/web/assets/settings-body-BTXNtpWL.js.br +0 -0
- package/dist/web/assets/settings-body-BTXNtpWL.js.gz +0 -0
- package/dist/web/assets/settings-store-DvftLqzy.js +2 -0
- package/dist/web/assets/settings-store-DvftLqzy.js.br +0 -0
- package/dist/web/assets/settings-store-DvftLqzy.js.gz +0 -0
- package/dist/web/assets/settings-tab-CGhaRXjs.js +1 -0
- package/dist/web/assets/settings-window-content--Uyg_Psr.js +1 -0
- package/dist/web/assets/sortable-header-DUW9T1Hz.js +1 -0
- package/dist/web/assets/sortable-header-DUW9T1Hz.js.br +0 -0
- package/dist/web/assets/sortable-header-DUW9T1Hz.js.gz +0 -0
- package/dist/web/assets/{sql-query-editor-BjIMi9Wk.js → sql-query-editor-Dn-cgDrW.js} +1 -1
- package/dist/web/assets/sql-query-editor-Dn-cgDrW.js.br +0 -0
- package/dist/web/assets/sql-query-editor-Dn-cgDrW.js.gz +0 -0
- package/dist/web/assets/{sqlite-viewer-BNcA6Irq.js → sqlite-viewer-B0NfaMjq.js} +1 -1
- package/dist/web/assets/sqlite-viewer-B0NfaMjq.js.br +0 -0
- package/dist/web/assets/sqlite-viewer-B0NfaMjq.js.gz +0 -0
- package/dist/web/assets/system-monitor-body-CxCfRQFb.js +2 -0
- package/dist/web/assets/system-monitor-body-CxCfRQFb.js.br +0 -0
- package/dist/web/assets/system-monitor-body-CxCfRQFb.js.gz +0 -0
- package/dist/web/assets/system-monitor-tab-Cb3EZUdp.js +1 -0
- package/dist/web/assets/system-monitor-window-content-51CA-2PH.js +1 -0
- package/dist/web/assets/{tab-host-window-content-CIRGNCvi.js → tab-host-window-content-CSrcmKNG.js} +1 -1
- package/dist/web/assets/tab-host-window-content-CSrcmKNG.js.br +0 -0
- package/dist/web/assets/tab-host-window-content-CSrcmKNG.js.gz +0 -0
- package/dist/web/assets/{team-member-sheet-CwXpLi3X.js → team-member-sheet-D4X6nh-x.js} +2 -2
- package/dist/web/assets/team-member-sheet-D4X6nh-x.js.br +0 -0
- package/dist/web/assets/team-member-sheet-D4X6nh-x.js.gz +0 -0
- package/dist/web/assets/{team-member-window-content-4swiiDz7.js → team-member-window-content-BxkbGVIL.js} +1 -1
- package/dist/web/assets/team-member-window-content-BxkbGVIL.js.br +0 -0
- package/dist/web/assets/team-member-window-content-BxkbGVIL.js.gz +0 -0
- package/dist/web/assets/{terminal-tab-BGcdtMMT.js → terminal-tab-BYo34IqU.js} +3 -3
- package/dist/web/assets/terminal-tab-BYo34IqU.js.br +0 -0
- package/dist/web/assets/terminal-tab-BYo34IqU.js.gz +0 -0
- package/dist/web/assets/{tool-cards-D0-krtA2.js → tool-cards-DvXjOped.js} +4 -4
- package/dist/web/assets/tool-cards-DvXjOped.js.br +0 -0
- package/dist/web/assets/tool-cards-DvXjOped.js.gz +0 -0
- package/dist/web/assets/{use-blob-url-CmavyEP8.js → use-blob-url-CISBWKG5.js} +1 -1
- package/dist/web/assets/use-inline-blame-Br6mheS4.js +16 -0
- package/dist/web/assets/use-inline-blame-Br6mheS4.js.br +0 -0
- package/dist/web/assets/use-inline-blame-Br6mheS4.js.gz +0 -0
- package/dist/web/assets/use-lsp-BpJmvQ0n.js +6 -0
- package/dist/web/assets/use-lsp-BpJmvQ0n.js.br +0 -0
- package/dist/web/assets/use-lsp-BpJmvQ0n.js.gz +0 -0
- package/dist/web/assets/{use-monaco-theme-C88KphGx.js → use-monaco-theme-UGOzyIhv.js} +1 -1
- package/dist/web/assets/use-process-kill-CyiiUD1E.js +1 -0
- package/dist/web/assets/use-process-kill-CyiiUD1E.js.br +0 -0
- package/dist/web/assets/use-process-kill-CyiiUD1E.js.gz +0 -0
- package/dist/web/assets/{use-websocket-Chk9guIU.js → use-websocket-Dpl21cHG.js} +1 -1
- package/dist/web/assets/{vendor-ui-BHh12_0v.js → vendor-ui-P9Ym7hCv.js} +1 -1
- package/dist/web/assets/vendor-ui-P9Ym7hCv.js.br +0 -0
- package/dist/web/assets/vendor-ui-P9Ym7hCv.js.gz +0 -0
- package/dist/web/assets/video-preview-D6Jw-IZK.js +1 -0
- package/dist/web/assets/video-preview-D6Jw-IZK.js.br +0 -0
- package/dist/web/assets/video-preview-D6Jw-IZK.js.gz +0 -0
- package/dist/web/assets/voice-settings-section-CcHQDYzN.js +1 -0
- package/dist/web/assets/voice-settings-section-CcHQDYzN.js.br +0 -0
- package/dist/web/assets/voice-settings-section-CcHQDYzN.js.gz +0 -0
- package/dist/web/assets/ws-auth-CqI8-aoA.js +1 -0
- package/dist/web/index.html +20 -20
- package/dist/web/index.html.br +0 -0
- package/dist/web/index.html.gz +0 -0
- package/dist/web/sw.js +1 -1
- package/dist/web/sw.js.br +0 -0
- package/dist/web/sw.js.gz +0 -0
- package/docs/deployment-guide.md +23 -0
- package/package.json +1 -1
- package/release-from-worktree.sh +224 -0
- package/src/cli/commands/config-cmd.ts +12 -0
- package/src/providers/claude-agent-sdk.ts +65 -2
- package/src/providers/codex-app-server/codex-jsonrpc-client.ts +16 -1
- package/src/providers/codex-app-server/codex-provider.ts +39 -7
- package/src/providers/provider-probe.ts +63 -0
- package/src/providers/registry.ts +109 -29
- package/src/server/index.ts +9 -0
- package/src/server/middleware/auth.ts +5 -1
- package/src/server/routes/cross-origin-guard.ts +20 -0
- package/src/server/routes/git.ts +40 -4
- package/src/server/routes/lsp.ts +97 -4
- package/src/server/routes/resources.ts +72 -9
- package/src/server/routes/settings.ts +19 -1
- package/src/server/routes/speech.ts +66 -0
- package/src/server/routes/system-services.ts +76 -0
- package/src/server/routes/tunnel.ts +33 -1
- package/src/server/ws/chat.ts +74 -3
- package/src/services/codex-account-login.ts +26 -2
- package/src/services/codex-reset-credit.service.ts +16 -3
- package/src/services/compaction-savings.ts +127 -0
- package/src/services/db.service.ts +123 -8
- package/src/services/fs-ops/fs-ops-trash.service.ts +22 -9
- package/src/services/git-refs/for-each-ref.ts +118 -0
- package/src/services/git.service.ts +25 -2
- package/src/services/host-info/spawn-runner.ts +48 -4
- package/src/services/jsonl-transcript-parser.ts +7 -42
- package/src/services/lsp/lsp-install.ts +289 -0
- package/src/services/lsp/lsp-manager.ts +160 -29
- package/src/services/lsp/server-registry.ts +120 -4
- package/src/services/named-tunnel/named-tunnel-config.ts +8 -2
- package/src/services/named-tunnel/named-tunnel-setup.service.ts +4 -0
- package/src/services/read-lines.ts +54 -0
- package/src/services/speech-to-text/whisper-catalog.ts +142 -0
- package/src/services/speech-to-text/whisper-download.ts +113 -0
- package/src/services/speech-to-text/whisper-hallucinations.ts +51 -0
- package/src/services/speech-to-text/whisper-install.service.ts +247 -0
- package/src/services/speech-to-text/whisper-paths.ts +62 -0
- package/src/services/speech-to-text/whisper-transcribe.service.ts +117 -0
- package/src/services/supervisor.ts +94 -11
- package/src/services/system-metrics/cpu-details-linux.ts +252 -0
- package/src/services/system-metrics/cpu-memory-collector.ts +140 -18
- package/src/services/system-metrics/device-collector-linux.ts +31 -0
- package/src/services/system-metrics/device-collector-types.ts +40 -0
- package/src/services/system-metrics/disk-devices-linux.ts +156 -0
- package/src/services/system-metrics/disk-inventory-linux.ts +150 -0
- package/src/services/system-metrics/fans-linux.ts +51 -0
- package/src/services/system-metrics/gpu-api-versions.ts +120 -0
- package/src/services/system-metrics/gpu-devices-linux.ts +370 -0
- package/src/services/system-metrics/gpu-fdinfo-linux.ts +253 -0
- package/src/services/system-metrics/hardware-inventory.ts +50 -0
- package/src/services/system-metrics/linux-fs.ts +43 -0
- package/src/services/system-metrics/memory-darwin.ts +91 -0
- package/src/services/system-metrics/memory-linux.ts +156 -0
- package/src/services/system-metrics/net-devices-linux.ts +114 -0
- package/src/services/system-metrics/net-inventory-linux.ts +100 -0
- package/src/services/system-metrics/partitions-linux.ts +158 -0
- package/src/services/system-metrics/process-collector-linux.ts +58 -6
- package/src/services/system-metrics/process-collector-types.ts +8 -1
- package/src/services/system-metrics/process-details-darwin.ts +166 -0
- package/src/services/system-metrics/process-details-linux.ts +150 -0
- package/src/services/system-metrics/process-grouping.ts +2 -1
- package/src/services/system-metrics/process-rows-builder.ts +2 -0
- package/src/services/system-metrics/process-swap-linux.ts +37 -0
- package/src/services/system-metrics/signal-executor.ts +84 -0
- package/src/services/system-metrics/signal-request-handler.ts +92 -0
- package/src/services/system-metrics/system-metrics-platform.ts +30 -4
- package/src/services/system-metrics/system-metrics-tick.ts +73 -4
- package/src/services/system-metrics/system-metrics.service.ts +87 -2
- package/src/services/system-metrics/udev-db.ts +40 -0
- package/src/services/system-services/app-cgroup-linux.ts +115 -0
- package/src/services/system-services/app-icon-service.ts +31 -0
- package/src/services/system-services/app-icons-linux.ts +124 -0
- package/src/services/system-services/apps-linux.ts +174 -0
- package/src/services/system-services/desktop-entry.ts +103 -0
- package/src/services/system-services/service-guard.ts +124 -0
- package/src/services/system-services/systemd-collector.ts +203 -0
- package/src/services/system-services/systemd-parse.ts +162 -0
- package/src/shared/prompt-cache-idle.ts +197 -0
- package/src/shared/turn-usage.ts +85 -1
- package/src/types/chat.ts +27 -0
- package/src/types/config.ts +14 -0
- package/src/types/git.ts +41 -0
- package/src/types/system-hardware.ts +137 -0
- package/src/types/system-metrics.ts +231 -2
- package/src/types/system-services.ts +73 -0
- package/src/web/components/branch-review/branch-review-tab.tsx +20 -20
- package/src/web/components/branch-review/branch-review-tree-row.tsx +1 -13
- package/src/web/components/chat/chat-tab.tsx +3 -0
- package/src/web/components/chat/compaction-divider.tsx +48 -0
- package/src/web/components/chat/idle-cache-notice.tsx +67 -0
- package/src/web/components/chat/message-input.tsx +48 -13
- package/src/web/components/chat/message-list.tsx +15 -0
- package/src/web/components/chat/prompt-cache-chip.tsx +74 -0
- package/src/web/components/editor/code-editor.tsx +1 -0
- package/src/web/components/editor/editor-language-service.tsx +11 -3
- package/src/web/components/editor/lsp-status.tsx +115 -13
- package/src/web/components/git/branch-picker.tsx +419 -0
- package/src/web/components/git/branch-select.tsx +34 -0
- package/src/web/components/git/create-worktree-dialog.tsx +17 -16
- package/src/web/components/git/git-repo-picker.tsx +28 -40
- package/src/web/components/layout/status-bar.tsx +42 -19
- package/src/web/components/settings/accounts/account-card.tsx +5 -1
- package/src/web/components/settings/ai-settings-section.tsx +67 -3
- package/src/web/components/settings/appearance-settings-section.tsx +2 -28
- package/src/web/components/settings/language-servers-section.tsx +362 -0
- package/src/web/components/settings/settings-categories.ts +8 -3
- package/src/web/components/settings/settings-section-content.tsx +2 -0
- package/src/web/components/settings/voice-settings-section.tsx +283 -0
- package/src/web/components/system/apps/app-row.tsx +110 -0
- package/src/web/components/system/apps/app-rows.ts +140 -0
- package/src/web/components/system/apps/apps-panel.tsx +129 -0
- package/src/web/components/system/metric-chart-canvas.tsx +79 -3
- package/src/web/components/system/overview-cards/card-shell.tsx +54 -0
- package/src/web/components/system/overview-cards/cpu-card.tsx +11 -6
- package/src/web/components/system/overview-cards/disk-card.tsx +11 -6
- package/src/web/components/system/overview-cards/gpu-card.tsx +16 -6
- package/src/web/components/system/overview-cards/mem-card.tsx +11 -6
- package/src/web/components/system/overview-cards/net-card.tsx +11 -6
- package/src/web/components/system/overview-device-target.ts +69 -0
- package/src/web/components/system/overview-panel.tsx +15 -1
- package/src/web/components/system/performance/cpu-core-grid.tsx +74 -0
- package/src/web/components/system/performance/cpu-detail.tsx +220 -0
- package/src/web/components/system/performance/detail-parts.tsx +149 -0
- package/src/web/components/system/performance/device-list.ts +139 -0
- package/src/web/components/system/performance/disk-detail.tsx +64 -0
- package/src/web/components/system/performance/fans-detail.tsx +35 -0
- package/src/web/components/system/performance/gpu-detail.tsx +116 -0
- package/src/web/components/system/performance/memory-detail.tsx +109 -0
- package/src/web/components/system/performance/nic-detail.tsx +55 -0
- package/src/web/components/system/performance/partition-list.tsx +79 -0
- package/src/web/components/system/performance/performance-panel.tsx +206 -0
- package/src/web/components/system/performance/use-hardware-inventory.ts +48 -0
- package/src/web/components/system/process-columns-grid.ts +5 -3
- package/src/web/components/system/process-details-dialog.tsx +116 -0
- package/src/web/components/system/process-group-row.tsx +6 -1
- package/src/web/components/system/process-row-format.ts +6 -0
- package/src/web/components/system/process-row-menu.tsx +72 -0
- package/src/web/components/system/process-row.tsx +7 -1
- package/src/web/components/system/process-table-model.ts +1 -1
- package/src/web/components/system/process-table-sort.ts +8 -4
- package/src/web/components/system/process-table-toolbar.tsx +10 -2
- package/src/web/components/system/process-table-totals.ts +3 -0
- package/src/web/components/system/process-table.tsx +25 -2
- package/src/web/components/system/services/service-action-confirm.tsx +100 -0
- package/src/web/components/system/services/service-columns.ts +103 -0
- package/src/web/components/system/services/service-details-sheet.tsx +97 -0
- package/src/web/components/system/services/service-resources.ts +105 -0
- package/src/web/components/system/services/service-row.tsx +146 -0
- package/src/web/components/system/services/service-rows.ts +92 -0
- package/src/web/components/system/services/service-sort.ts +90 -0
- package/src/web/components/system/services/services-header.tsx +51 -0
- package/src/web/components/system/services/services-panel.tsx +207 -0
- package/src/web/components/system/services/use-services.ts +92 -0
- package/src/web/components/system/sortable-header.tsx +13 -8
- package/src/web/components/system/sysmon-preferences.tsx +85 -0
- package/src/web/components/system/system-monitor-body.tsx +101 -43
- package/src/web/components/system/system-monitor-window-content.tsx +2 -3
- package/src/web/components/system/use-process-signal.ts +87 -0
- package/src/web/components/tunnels/public-tunnel-switch.tsx +82 -0
- package/src/web/components/tunnels/tunnel-manager-tab.tsx +4 -0
- package/src/web/components/ui/dialog.tsx +14 -1
- package/src/web/components/ui/search-select.tsx +279 -0
- package/src/web/components/ui/start-ellipsis.tsx +18 -0
- package/src/web/hooks/use-chat.ts +28 -0
- package/src/web/hooks/use-global-keybindings.ts +7 -5
- package/src/web/hooks/use-lsp.ts +23 -2
- package/src/web/hooks/use-minute-clock.ts +20 -0
- package/src/web/hooks/use-whisper-voice-input.ts +113 -0
- package/src/web/lib/api-tunnels.ts +19 -0
- package/src/web/lib/branch-select-items.ts +29 -0
- package/src/web/lib/cpu-graph-mode.ts +90 -0
- package/src/web/lib/format-bytes.ts +14 -0
- package/src/web/lib/git-ref-picker.ts +120 -0
- package/src/web/lib/lsp/lsp-client.ts +32 -0
- package/src/web/lib/search-select-rows.ts +55 -0
- package/src/web/lib/temperature.ts +27 -0
- package/src/web/lib/voice-wav.ts +69 -0
- package/src/web/stores/git-status-store.ts +31 -17
- package/src/web/stores/keybindings-store.ts +14 -1
- package/src/web/stores/settings-store.ts +65 -0
- package/src/web/styles/globals.css +11 -0
- package/dist/web/assets/accounts-settings-section-DUVO32SQ.js +0 -1
- package/dist/web/assets/accounts-settings-section-DUVO32SQ.js.br +0 -0
- package/dist/web/assets/accounts-settings-section-DUVO32SQ.js.gz +0 -0
- package/dist/web/assets/ai-resource-editor-Dn_wB-o5.js.br +0 -0
- package/dist/web/assets/ai-resource-editor-Dn_wB-o5.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-CEbW8jRy.js +0 -1
- package/dist/web/assets/ai-settings-section-CEbW8jRy.js.br +0 -0
- package/dist/web/assets/ai-settings-section-CEbW8jRy.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-D-mwEYFZ.js +0 -1
- package/dist/web/assets/api-client-BgedDTvo.js +0 -1
- package/dist/web/assets/api-client-c8YOpTlT.js.br +0 -0
- package/dist/web/assets/api-client-c8YOpTlT.js.gz +0 -0
- package/dist/web/assets/api-settings-BmvNoCbn.js.br +0 -0
- package/dist/web/assets/api-settings-BmvNoCbn.js.gz +0 -0
- package/dist/web/assets/api-settings-Bti1-Zn3.js +0 -1
- package/dist/web/assets/appearance-settings-section-tw6TpFb6.js +0 -1
- package/dist/web/assets/appearance-settings-section-tw6TpFb6.js.br +0 -0
- package/dist/web/assets/appearance-settings-section-tw6TpFb6.js.gz +0 -0
- package/dist/web/assets/audio-preview-vaG2cB-k.js.br +0 -0
- package/dist/web/assets/audio-preview-vaG2cB-k.js.gz +0 -0
- package/dist/web/assets/branch-review-tab-MBuMWp_i.js +0 -1
- package/dist/web/assets/branch-review-tab-MBuMWp_i.js.br +0 -0
- package/dist/web/assets/branch-review-tab-MBuMWp_i.js.gz +0 -0
- package/dist/web/assets/button-Ci9EUgqd.js.br +0 -0
- package/dist/web/assets/button-Ci9EUgqd.js.gz +0 -0
- package/dist/web/assets/chat-preparation-cache-BSIQGiWx.js.br +0 -0
- package/dist/web/assets/chat-preparation-cache-BSIQGiWx.js.gz +0 -0
- package/dist/web/assets/chat-tab-DVvnqhw6.js +0 -1
- package/dist/web/assets/chat-tab-DVvnqhw6.js.br +0 -0
- package/dist/web/assets/chat-tab-DVvnqhw6.js.gz +0 -0
- package/dist/web/assets/chat-tab-DaEHva22.js +0 -15
- package/dist/web/assets/chat-tab-DaEHva22.js.br +0 -0
- package/dist/web/assets/chat-tab-DaEHva22.js.gz +0 -0
- package/dist/web/assets/code-editor-Bu9lhTVp.js +0 -7
- package/dist/web/assets/code-editor-Bu9lhTVp.js.br +0 -0
- package/dist/web/assets/code-editor-Bu9lhTVp.js.gz +0 -0
- package/dist/web/assets/codex-reset-credit-button-CbmE5mRX.js +0 -1
- package/dist/web/assets/codex-reset-credit-button-CbmE5mRX.js.br +0 -0
- package/dist/web/assets/codex-reset-credit-button-CbmE5mRX.js.gz +0 -0
- package/dist/web/assets/conflict-editor-BA3y-qSH.js.br +0 -0
- package/dist/web/assets/conflict-editor-BA3y-qSH.js.gz +0 -0
- package/dist/web/assets/context-menu-CjYTq8DI.js +0 -1
- package/dist/web/assets/context-menu-CjYTq8DI.js.br +0 -0
- package/dist/web/assets/context-menu-CjYTq8DI.js.gz +0 -0
- package/dist/web/assets/csv-preview-BioxkrQF.js.br +0 -0
- package/dist/web/assets/csv-preview-BioxkrQF.js.gz +0 -0
- package/dist/web/assets/data-grid-overlay-editor-CQRVKr7y.js.br +0 -0
- package/dist/web/assets/data-grid-overlay-editor-CQRVKr7y.js.gz +0 -0
- package/dist/web/assets/database-viewer-BSoJ0E6p.js.br +0 -0
- package/dist/web/assets/database-viewer-BSoJ0E6p.js.gz +0 -0
- package/dist/web/assets/design-export-client-ChMcMoqW.js.br +0 -0
- package/dist/web/assets/design-export-client-ChMcMoqW.js.gz +0 -0
- package/dist/web/assets/design-responsive-dialog-DNBhJJLf.js.br +0 -0
- package/dist/web/assets/design-responsive-dialog-DNBhJJLf.js.gz +0 -0
- package/dist/web/assets/design-tab-iU2CviE3.js +0 -33
- package/dist/web/assets/design-tab-iU2CviE3.js.br +0 -0
- package/dist/web/assets/design-tab-iU2CviE3.js.gz +0 -0
- package/dist/web/assets/designs-sidebar-panel-DHh5QsH9.js.br +0 -0
- package/dist/web/assets/designs-sidebar-panel-DHh5QsH9.js.gz +0 -0
- package/dist/web/assets/dialog-B8clVkyi.js +0 -1
- package/dist/web/assets/dialog-B8clVkyi.js.br +0 -0
- package/dist/web/assets/dialog-B8clVkyi.js.gz +0 -0
- package/dist/web/assets/diff-viewer-lctWoSmG.js.br +0 -0
- package/dist/web/assets/diff-viewer-lctWoSmG.js.gz +0 -0
- package/dist/web/assets/docx-preview-C9XdKEj1.js.br +0 -0
- package/dist/web/assets/docx-preview-C9XdKEj1.js.gz +0 -0
- package/dist/web/assets/editor-language-service-fPG56hQO.js +0 -1
- package/dist/web/assets/editor-language-service-fPG56hQO.js.br +0 -0
- package/dist/web/assets/editor-language-service-fPG56hQO.js.gz +0 -0
- package/dist/web/assets/explorer-body-BgF7FsxI.js +0 -2
- package/dist/web/assets/explorer-body-BgF7FsxI.js.br +0 -0
- package/dist/web/assets/explorer-body-BgF7FsxI.js.gz +0 -0
- package/dist/web/assets/explorer-window-content-C21w_7lf.js +0 -1
- package/dist/web/assets/explorer-window-content-C21w_7lf.js.br +0 -0
- package/dist/web/assets/explorer-window-content-C21w_7lf.js.gz +0 -0
- package/dist/web/assets/extension-manager-section-rbkXsZVR.js.br +0 -0
- package/dist/web/assets/extension-manager-section-rbkXsZVR.js.gz +0 -0
- package/dist/web/assets/extension-webview-uPO0WgCq.js.br +0 -0
- package/dist/web/assets/extension-webview-uPO0WgCq.js.gz +0 -0
- package/dist/web/assets/file-icons-gx_FBOXY.js.br +0 -0
- package/dist/web/assets/file-icons-gx_FBOXY.js.gz +0 -0
- package/dist/web/assets/file-store-D9KE0kQC.js.br +0 -0
- package/dist/web/assets/file-store-D9KE0kQC.js.gz +0 -0
- package/dist/web/assets/files-settings-section-CT7mDb0L.js.br +0 -0
- package/dist/web/assets/files-settings-section-CT7mDb0L.js.gz +0 -0
- package/dist/web/assets/format-bytes-DmSHAKFe.js +0 -1
- package/dist/web/assets/format-file-meta-mQwA6SuY.js.br +0 -0
- package/dist/web/assets/format-file-meta-mQwA6SuY.js.gz +0 -0
- package/dist/web/assets/fs-api-DL36slbd.js.br +0 -0
- package/dist/web/assets/fs-api-DL36slbd.js.gz +0 -0
- package/dist/web/assets/general-settings-section-DANPfMRN.js.br +0 -0
- package/dist/web/assets/general-settings-section-DANPfMRN.js.gz +0 -0
- package/dist/web/assets/git-log-panel-BJPkLiEw.js.br +0 -0
- package/dist/web/assets/git-log-panel-BJPkLiEw.js.gz +0 -0
- package/dist/web/assets/git-repo-store-DSypNj19.js.br +0 -0
- package/dist/web/assets/git-repo-store-DSypNj19.js.gz +0 -0
- package/dist/web/assets/glide-data-grid-R4PcAntf.js.br +0 -0
- package/dist/web/assets/glide-data-grid-R4PcAntf.js.gz +0 -0
- package/dist/web/assets/group-chat-tab-BXMdo8w9.js +0 -1
- package/dist/web/assets/group-chat-tab-BXMdo8w9.js.br +0 -0
- package/dist/web/assets/group-chat-tab-BXMdo8w9.js.gz +0 -0
- package/dist/web/assets/index-C8nGqkKN.js +0 -52
- package/dist/web/assets/index-C8nGqkKN.js.br +0 -0
- package/dist/web/assets/index-C8nGqkKN.js.gz +0 -0
- package/dist/web/assets/index-DvClbTQx.css +0 -1
- package/dist/web/assets/index-DvClbTQx.css.br +0 -0
- package/dist/web/assets/index-DvClbTQx.css.gz +0 -0
- package/dist/web/assets/keybindings-store-BGKlQQAv.js +0 -1
- package/dist/web/assets/keyboard-shortcuts-section-BKej4mUf.js.br +0 -0
- package/dist/web/assets/keyboard-shortcuts-section-BKej4mUf.js.gz +0 -0
- package/dist/web/assets/markdown-renderer-BHtYqkYZ.js.br +0 -0
- package/dist/web/assets/markdown-renderer-BHtYqkYZ.js.gz +0 -0
- package/dist/web/assets/markdown-renderer-vDNuKjel.js +0 -1
- package/dist/web/assets/mobile-bottom-sheet-CuNi2FRv.js.br +0 -0
- package/dist/web/assets/mobile-bottom-sheet-CuNi2FRv.js.gz +0 -0
- package/dist/web/assets/mobile-explorer-sheet-DtvxS7-r.js +0 -1
- package/dist/web/assets/mobile-explorer-sheet-DtvxS7-r.js.br +0 -0
- package/dist/web/assets/mobile-explorer-sheet-DtvxS7-r.js.gz +0 -0
- package/dist/web/assets/new-design-dialog-DS_XrpTG.js.br +0 -0
- package/dist/web/assets/new-design-dialog-DS_XrpTG.js.gz +0 -0
- package/dist/web/assets/notification-store-Dnnj20Ky.js +0 -1
- package/dist/web/assets/notifications-settings-section-C05WYqcE.js.br +0 -0
- package/dist/web/assets/notifications-settings-section-C05WYqcE.js.gz +0 -0
- package/dist/web/assets/onboarding-entry-CmUqv1kl.js.br +0 -0
- package/dist/web/assets/onboarding-entry-CmUqv1kl.js.gz +0 -0
- package/dist/web/assets/onboarding-quick-orientation-DIhWv1CN.js.br +0 -0
- package/dist/web/assets/onboarding-quick-orientation-DIhWv1CN.js.gz +0 -0
- package/dist/web/assets/overview-panel-BZAW_nag.js +0 -1
- package/dist/web/assets/overview-panel-BZAW_nag.js.br +0 -0
- package/dist/web/assets/overview-panel-BZAW_nag.js.gz +0 -0
- package/dist/web/assets/pdf-preview-qdXmMkOR.js.br +0 -0
- package/dist/web/assets/pdf-preview-qdXmMkOR.js.gz +0 -0
- package/dist/web/assets/postgres-viewer-Xvlun_n5.js.br +0 -0
- package/dist/web/assets/postgres-viewer-Xvlun_n5.js.gz +0 -0
- package/dist/web/assets/ppmbot-settings-section-D8AES1BA.js.br +0 -0
- package/dist/web/assets/ppmbot-settings-section-D8AES1BA.js.gz +0 -0
- package/dist/web/assets/pptx-export-CG6MRNok.js.br +0 -0
- package/dist/web/assets/pptx-export-CG6MRNok.js.gz +0 -0
- package/dist/web/assets/problems-panel-DTBG4beI.js.br +0 -0
- package/dist/web/assets/problems-panel-DTBG4beI.js.gz +0 -0
- package/dist/web/assets/process-table-D_gR2XA6.js +0 -1
- package/dist/web/assets/process-table-D_gR2XA6.js.br +0 -0
- package/dist/web/assets/process-table-D_gR2XA6.js.gz +0 -0
- package/dist/web/assets/project-store-C5gJXkvb.js.br +0 -0
- package/dist/web/assets/project-store-C5gJXkvb.js.gz +0 -0
- package/dist/web/assets/proxy-settings-section-CqtmbeRj.js.br +0 -0
- package/dist/web/assets/proxy-settings-section-CqtmbeRj.js.gz +0 -0
- package/dist/web/assets/query-audit-section-UKG_smyt.js.br +0 -0
- package/dist/web/assets/query-audit-section-UKG_smyt.js.gz +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-Djt6cpNL.js.br +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-Djt6cpNL.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-BQxhJUkm.js +0 -2
- package/dist/web/assets/remote-desktop-mobile-sheet-BQxhJUkm.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-BQxhJUkm.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-DGnT8RY7.js +0 -1
- package/dist/web/assets/remote-desktop-mobile-view-DGnT8RY7.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-DGnT8RY7.js.gz +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-DNJF8TcF.js.br +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-DNJF8TcF.js.gz +0 -0
- package/dist/web/assets/remote-desktop-window-content-Ds0DKmM0.js +0 -1
- package/dist/web/assets/remote-desktop-window-content-Ds0DKmM0.js.br +0 -0
- package/dist/web/assets/remote-desktop-window-content-Ds0DKmM0.js.gz +0 -0
- package/dist/web/assets/schedules-settings-section-BKoPovy2.js.br +0 -0
- package/dist/web/assets/schedules-settings-section-BKoPovy2.js.gz +0 -0
- package/dist/web/assets/scroll-area-XonvWYn_.js.br +0 -0
- package/dist/web/assets/scroll-area-XonvWYn_.js.gz +0 -0
- package/dist/web/assets/settings-body-k2qPgRFe.js +0 -2
- package/dist/web/assets/settings-body-k2qPgRFe.js.br +0 -0
- package/dist/web/assets/settings-body-k2qPgRFe.js.gz +0 -0
- package/dist/web/assets/settings-store-Br5c1efC.js +0 -2
- package/dist/web/assets/settings-store-Br5c1efC.js.br +0 -0
- package/dist/web/assets/settings-store-Br5c1efC.js.gz +0 -0
- package/dist/web/assets/settings-tab-Bb23VdBu.js +0 -1
- package/dist/web/assets/settings-window-content-ClarWusz.js +0 -1
- package/dist/web/assets/sql-query-editor-BjIMi9Wk.js.br +0 -0
- package/dist/web/assets/sql-query-editor-BjIMi9Wk.js.gz +0 -0
- package/dist/web/assets/sqlite-viewer-BNcA6Irq.js.br +0 -0
- package/dist/web/assets/sqlite-viewer-BNcA6Irq.js.gz +0 -0
- package/dist/web/assets/system-monitor-body-D0T3ggt2.js +0 -2
- package/dist/web/assets/system-monitor-body-D0T3ggt2.js.br +0 -0
- package/dist/web/assets/system-monitor-body-D0T3ggt2.js.gz +0 -0
- package/dist/web/assets/system-monitor-tab-I1Igmoey.js +0 -1
- package/dist/web/assets/system-monitor-window-content-C5SeUv1H.js +0 -1
- package/dist/web/assets/tab-host-window-content-CIRGNCvi.js.br +0 -0
- package/dist/web/assets/tab-host-window-content-CIRGNCvi.js.gz +0 -0
- package/dist/web/assets/team-member-sheet-CwXpLi3X.js.br +0 -0
- package/dist/web/assets/team-member-sheet-CwXpLi3X.js.gz +0 -0
- package/dist/web/assets/team-member-window-content-4swiiDz7.js.br +0 -0
- package/dist/web/assets/team-member-window-content-4swiiDz7.js.gz +0 -0
- package/dist/web/assets/terminal-tab-BGcdtMMT.js.br +0 -0
- package/dist/web/assets/terminal-tab-BGcdtMMT.js.gz +0 -0
- package/dist/web/assets/tool-cards-D0-krtA2.js.br +0 -0
- package/dist/web/assets/tool-cards-D0-krtA2.js.gz +0 -0
- package/dist/web/assets/use-inline-blame-pKaXyGU-.js +0 -16
- package/dist/web/assets/use-inline-blame-pKaXyGU-.js.br +0 -0
- package/dist/web/assets/use-inline-blame-pKaXyGU-.js.gz +0 -0
- package/dist/web/assets/use-lsp-71azTXQz.js +0 -6
- package/dist/web/assets/use-lsp-71azTXQz.js.br +0 -0
- package/dist/web/assets/use-lsp-71azTXQz.js.gz +0 -0
- package/dist/web/assets/vendor-ui-BHh12_0v.js.br +0 -0
- package/dist/web/assets/vendor-ui-BHh12_0v.js.gz +0 -0
- package/dist/web/assets/video-preview-DxEX-uGo.js +0 -1
- package/dist/web/assets/video-preview-DxEX-uGo.js.br +0 -0
- package/dist/web/assets/video-preview-DxEX-uGo.js.gz +0 -0
- package/dist/web/assets/ws-auth-kXgsX2Js.js +0 -1
- /package/dist/web/assets/{__vite-browser-external-BpSQWxcq.js → __vite-browser-external-BILfYaAs.js} +0 -0
- /package/dist/web/assets/{run-in-terminal-HIdNgYim.js → run-in-terminal-2pSiup8e.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-DLDtzLib.js → vendor-xterm-DF1JTfsy.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-DLDtzLib.js.br → vendor-xterm-DF1JTfsy.js.br} +0 -0
- /package/dist/web/assets/{vendor-xterm-DLDtzLib.js.gz → vendor-xterm-DF1JTfsy.js.gz} +0 -0
|
@@ -32,6 +32,14 @@ export interface LanguageServerDefinition {
|
|
|
32
32
|
rootMarkers: string[];
|
|
33
33
|
/** Shown verbatim when the command cannot be found. */
|
|
34
34
|
installHint: string;
|
|
35
|
+
/**
|
|
36
|
+
* How the Install button installs this server, when PPM can install it at all.
|
|
37
|
+
*
|
|
38
|
+
* Unset for a server that needs a system package manager — `clangd`, `lua-language-server`
|
|
39
|
+
* and `solargraph` mean pacman, apt, brew or a gem, i.e. a password and a choice PPM has no
|
|
40
|
+
* business making. Those keep a command to copy and no button.
|
|
41
|
+
*/
|
|
42
|
+
install?: LanguageServerInstall;
|
|
35
43
|
/**
|
|
36
44
|
* The npm package PPM depends on for this server, when it ships one.
|
|
37
45
|
*
|
|
@@ -42,6 +50,25 @@ export interface LanguageServerDefinition {
|
|
|
42
50
|
initializationOptions?: Record<string, unknown>;
|
|
43
51
|
}
|
|
44
52
|
|
|
53
|
+
/**
|
|
54
|
+
* What the Install button runs.
|
|
55
|
+
*
|
|
56
|
+
* `bun` and `go` both put the server inside PPM's own directory, so nothing the user installed
|
|
57
|
+
* is touched and `rm -rf` is the uninstall. `rustup` is the exception and has to be: a
|
|
58
|
+
* rust-analyzer belongs to a toolchain, and a private copy would be the wrong one as soon as a
|
|
59
|
+
* project pins a different toolchain.
|
|
60
|
+
*
|
|
61
|
+
* PPM never installs the *toolchain*. `go` and `rustup` are offered only where the host
|
|
62
|
+
* already has them — see `canInstall` in `lsp-install.ts`.
|
|
63
|
+
*/
|
|
64
|
+
export type LanguageServerInstall =
|
|
65
|
+
/** `bun add <packages>`; the first package provides `command`, the rest are what it needs. */
|
|
66
|
+
| { with: "bun"; packages: string[] }
|
|
67
|
+
/** `go install <module>` with `GOBIN` pointed at PPM's own bin directory. */
|
|
68
|
+
| { with: "go"; module: string }
|
|
69
|
+
/** `rustup component add <component>`, in whichever toolchain the project selects. */
|
|
70
|
+
| { with: "rustup"; component: string };
|
|
71
|
+
|
|
45
72
|
/**
|
|
46
73
|
* File extension to LSP language id.
|
|
47
74
|
*
|
|
@@ -110,6 +137,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
|
|
|
110
137
|
// start against it with "provides no tsserver" — which reads like a broken
|
|
111
138
|
// install rather than the wrong major version.
|
|
112
139
|
installHint: "bun add -g typescript-language-server typescript@5",
|
|
140
|
+
install: { with: "bun", packages: ["typescript-language-server", "typescript@5"] },
|
|
113
141
|
// Shipped with PPM, so this one works on a fresh install with nothing else done. The
|
|
114
142
|
// project's own copy still wins where there is one — a repository pinned to TypeScript 4
|
|
115
143
|
// has to be analysed by its own server, not by whatever PPM happens to carry.
|
|
@@ -153,6 +181,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
|
|
|
153
181
|
args: ["--stdio"],
|
|
154
182
|
rootMarkers: ["pyproject.toml", "setup.py", "setup.cfg", "requirements.txt", "Pipfile"],
|
|
155
183
|
installHint: "bun add -g pyright",
|
|
184
|
+
install: { with: "bun", packages: ["pyright"] },
|
|
156
185
|
},
|
|
157
186
|
{
|
|
158
187
|
id: "gopls",
|
|
@@ -162,6 +191,9 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
|
|
|
162
191
|
args: [],
|
|
163
192
|
rootMarkers: ["go.work", "go.mod"],
|
|
164
193
|
installHint: "go install golang.org/x/tools/gopls@latest",
|
|
194
|
+
// Built by the host's own Go, into PPM's directory: `GOBIN` is what decides where the
|
|
195
|
+
// binary lands, so `~/go/bin` is left exactly as the user arranged it. 10.6 s here.
|
|
196
|
+
install: { with: "go", module: "golang.org/x/tools/gopls@latest" },
|
|
165
197
|
},
|
|
166
198
|
{
|
|
167
199
|
id: "rust-analyzer",
|
|
@@ -171,6 +203,11 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
|
|
|
171
203
|
args: [],
|
|
172
204
|
rootMarkers: ["Cargo.toml"],
|
|
173
205
|
installHint: "rustup component add rust-analyzer",
|
|
206
|
+
// The one server PPM does not keep in its own directory: rust-analyzer belongs to a
|
|
207
|
+
// *toolchain*, and a copy of its own would be the wrong one the moment a project pins a
|
|
208
|
+
// different one. `rustup which` is then both the lookup and the installed-check — it exits
|
|
209
|
+
// non-zero with "unknown binary" when the component is absent, in 3 ms.
|
|
210
|
+
install: { with: "rustup", component: "rust-analyzer" },
|
|
174
211
|
},
|
|
175
212
|
{
|
|
176
213
|
id: "clangd",
|
|
@@ -189,6 +226,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
|
|
|
189
226
|
args: ["--stdio"],
|
|
190
227
|
rootMarkers: ["package.json"],
|
|
191
228
|
installHint: "bun add -g vscode-langservers-extracted",
|
|
229
|
+
install: { with: "bun", packages: ["vscode-langservers-extracted"] },
|
|
192
230
|
},
|
|
193
231
|
{
|
|
194
232
|
id: "html",
|
|
@@ -198,6 +236,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
|
|
|
198
236
|
args: ["--stdio"],
|
|
199
237
|
rootMarkers: ["package.json"],
|
|
200
238
|
installHint: "bun add -g vscode-langservers-extracted",
|
|
239
|
+
install: { with: "bun", packages: ["vscode-langservers-extracted"] },
|
|
201
240
|
},
|
|
202
241
|
{
|
|
203
242
|
id: "css",
|
|
@@ -207,6 +246,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
|
|
|
207
246
|
args: ["--stdio"],
|
|
208
247
|
rootMarkers: ["package.json"],
|
|
209
248
|
installHint: "bun add -g vscode-langservers-extracted",
|
|
249
|
+
install: { with: "bun", packages: ["vscode-langservers-extracted"] },
|
|
210
250
|
},
|
|
211
251
|
{
|
|
212
252
|
id: "yaml",
|
|
@@ -216,6 +256,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
|
|
|
216
256
|
args: ["--stdio"],
|
|
217
257
|
rootMarkers: [],
|
|
218
258
|
installHint: "bun add -g yaml-language-server",
|
|
259
|
+
install: { with: "bun", packages: ["yaml-language-server"] },
|
|
219
260
|
},
|
|
220
261
|
{
|
|
221
262
|
id: "bash",
|
|
@@ -225,6 +266,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
|
|
|
225
266
|
args: ["start"],
|
|
226
267
|
rootMarkers: [],
|
|
227
268
|
installHint: "bun add -g bash-language-server",
|
|
269
|
+
install: { with: "bun", packages: ["bash-language-server"] },
|
|
228
270
|
},
|
|
229
271
|
{
|
|
230
272
|
id: "intelephense",
|
|
@@ -234,6 +276,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
|
|
|
234
276
|
args: ["--stdio"],
|
|
235
277
|
rootMarkers: ["composer.json"],
|
|
236
278
|
installHint: "bun add -g intelephense",
|
|
279
|
+
install: { with: "bun", packages: ["intelephense"] },
|
|
237
280
|
},
|
|
238
281
|
{
|
|
239
282
|
id: "solargraph",
|
|
@@ -261,6 +304,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
|
|
|
261
304
|
args: ["--stdio"],
|
|
262
305
|
rootMarkers: ["package.json"],
|
|
263
306
|
installHint: "bun add -g @vue/language-server",
|
|
307
|
+
install: { with: "bun", packages: ["@vue/language-server"] },
|
|
264
308
|
},
|
|
265
309
|
{
|
|
266
310
|
id: "svelte",
|
|
@@ -270,6 +314,7 @@ export const LANGUAGE_SERVERS: LanguageServerDefinition[] = [
|
|
|
270
314
|
args: ["--stdio"],
|
|
271
315
|
rootMarkers: ["package.json"],
|
|
272
316
|
installHint: "bun add -g svelte-language-server",
|
|
317
|
+
install: { with: "bun", packages: ["svelte-language-server"] },
|
|
273
318
|
},
|
|
274
319
|
];
|
|
275
320
|
|
|
@@ -282,6 +327,26 @@ export function serverById(id: string): LanguageServerDefinition | undefined {
|
|
|
282
327
|
return LANGUAGE_SERVERS.find((s) => s.id === id);
|
|
283
328
|
}
|
|
284
329
|
|
|
330
|
+
/**
|
|
331
|
+
* The other servers that an uninstall of this one would also take away.
|
|
332
|
+
*
|
|
333
|
+
* One npm package can provide several servers — `vscode-langservers-extracted` is JSON, HTML
|
|
334
|
+
* and CSS at once — so `bun remove` of it removes all three whichever row the button was on.
|
|
335
|
+
* That is not a thing to discover afterwards, so the Settings pane names them before asking.
|
|
336
|
+
* Nothing shares a `go` module or a rustup component, so those answer with nothing.
|
|
337
|
+
*/
|
|
338
|
+
export function serversSharingInstall(definition: LanguageServerDefinition): LanguageServerDefinition[] {
|
|
339
|
+
const plan = definition.install;
|
|
340
|
+
if (plan?.with !== "bun") return [];
|
|
341
|
+
const pkg = packageName(plan.packages[0] ?? "");
|
|
342
|
+
return LANGUAGE_SERVERS.filter(
|
|
343
|
+
(s) =>
|
|
344
|
+
s.id !== definition.id &&
|
|
345
|
+
s.install?.with === "bun" &&
|
|
346
|
+
packageName(s.install.packages[0] ?? "") === pkg,
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
|
|
285
350
|
/**
|
|
286
351
|
* Directories to search, nearest first, from the file's own directory up to and
|
|
287
352
|
* including the project root.
|
|
@@ -386,16 +451,67 @@ export function bundledServerEntry(
|
|
|
386
451
|
): string | null {
|
|
387
452
|
const pkg = definition.bundledPackage;
|
|
388
453
|
if (!pkg) return null;
|
|
389
|
-
|
|
454
|
+
try {
|
|
455
|
+
return binEntry(resolve(`${pkg}/package.json`), definition.command);
|
|
456
|
+
} catch {
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* The entry script of an npm server the Install button put in PPM's own directory.
|
|
463
|
+
*
|
|
464
|
+
* Built as a path *under* `installDir` rather than resolved through `require`: Node resolution
|
|
465
|
+
* climbs out of the directory it starts in, so a stray `~/node_modules` would answer for a
|
|
466
|
+
* package PPM never installed — and whatever answers here is executed.
|
|
467
|
+
*/
|
|
468
|
+
export function installedServerEntry(definition: LanguageServerDefinition, installDir: string): string | null {
|
|
469
|
+
if (definition.install?.with !== "bun") return null;
|
|
470
|
+
const spec = definition.install.packages[0];
|
|
471
|
+
if (!spec) return null;
|
|
472
|
+
const pkgDir = path.join(installDir, "node_modules", ...packageName(spec).split("/"));
|
|
473
|
+
return binEntry(path.join(pkgDir, "package.json"), definition.command);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Where a compiled server the Install button built would be — PPM's own `bin` directory.
|
|
478
|
+
*
|
|
479
|
+
* That is `GOBIN` for the install, so the binary is PPM's to find and to delete, and the
|
|
480
|
+
* user's `~/go/bin` is left as they arranged it. A plain path: whether it exists is the
|
|
481
|
+
* caller's `exists()`, the same as for every other candidate.
|
|
482
|
+
*/
|
|
483
|
+
export function installedBinaryPath(
|
|
484
|
+
definition: LanguageServerDefinition,
|
|
485
|
+
installDir: string,
|
|
486
|
+
platform: NodeJS.Platform = process.platform,
|
|
487
|
+
): string | null {
|
|
488
|
+
if (definition.install?.with !== "go") return null;
|
|
489
|
+
return path.join(installDir, "bin", platform === "win32" ? `${definition.command}.exe` : definition.command);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/** `typescript@5` → `typescript`, keeping a scoped package's own leading `@`. */
|
|
493
|
+
export function packageName(spec: string): string {
|
|
494
|
+
const at = spec.indexOf("@", 1);
|
|
495
|
+
return at === -1 ? spec : spec.slice(0, at);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* `bin[command]` from a package manifest, as an absolute path.
|
|
500
|
+
*
|
|
501
|
+
* Both callers want the package's **entry script** and not npm's `.bin` shim: that shim starts
|
|
502
|
+
* `#!/usr/bin/env node`, and someone who installed PPM with bun may have no `node` on the
|
|
503
|
+
* machine at all — measured as exit **127** with `env: 'node': No such file or directory`,
|
|
504
|
+
* after the server had already been reported as installed. The manager runs the entry with bun.
|
|
505
|
+
*/
|
|
506
|
+
function binEntry(manifestPath: string, command: string): string | null {
|
|
390
507
|
let manifest: { bin?: string | Record<string, string> };
|
|
391
508
|
try {
|
|
392
|
-
manifestPath = resolve(`${pkg}/package.json`);
|
|
393
509
|
manifest = JSON.parse(readFileSync(manifestPath, "utf8")) as typeof manifest;
|
|
394
510
|
} catch {
|
|
395
|
-
return null;
|
|
511
|
+
return null; // not installed, or a manifest we cannot read
|
|
396
512
|
}
|
|
397
513
|
// `bin` is either a bare string — the package's own name — or a map of command to path.
|
|
398
|
-
const relative = typeof manifest.bin === "string" ? manifest.bin : manifest.bin?.[
|
|
514
|
+
const relative = typeof manifest.bin === "string" ? manifest.bin : manifest.bin?.[command];
|
|
399
515
|
if (!relative) return null;
|
|
400
516
|
return path.resolve(path.dirname(manifestPath), relative);
|
|
401
517
|
}
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
export type TunnelMode = "quick" | "named";
|
|
10
10
|
|
|
11
11
|
export interface ResolvedTunnelConfig {
|
|
12
|
+
/** Master switch — `false` means spawn no tunnel at all, whatever `mode` says. */
|
|
13
|
+
enabled: boolean;
|
|
12
14
|
mode: TunnelMode;
|
|
13
15
|
hostname: string | null;
|
|
14
16
|
tunnelName: string | null;
|
|
@@ -18,7 +20,7 @@ export interface ResolvedTunnelConfig {
|
|
|
18
20
|
dismissed: boolean;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
const QUICK: Omit<ResolvedTunnelConfig, "dismissed"> = {
|
|
23
|
+
const QUICK: Omit<ResolvedTunnelConfig, "dismissed" | "enabled"> = {
|
|
22
24
|
mode: "quick", hostname: null, tunnelName: null, token: null, zoneID: null, accountID: null,
|
|
23
25
|
};
|
|
24
26
|
|
|
@@ -35,6 +37,9 @@ export function resolveTunnelConfig(raw: unknown): ResolvedTunnelConfig {
|
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
const dismissed = obj != null && typeof obj.dismissed === "boolean" ? obj.dismissed : false;
|
|
40
|
+
// Absent means a row older than the master switch, back when the tunnel was
|
|
41
|
+
// unconditional — absent is therefore on, never off.
|
|
42
|
+
const enabled = obj != null && typeof obj.enabled === "boolean" ? obj.enabled : true;
|
|
38
43
|
|
|
39
44
|
// Named mode requires BOTH the stored mode flag AND all four identity fields —
|
|
40
45
|
// checking fields alone would resurrect a tunnel the user explicitly disabled,
|
|
@@ -46,10 +51,11 @@ export function resolveTunnelConfig(raw: unknown): ResolvedTunnelConfig {
|
|
|
46
51
|
nonEmptyString(obj.accountID);
|
|
47
52
|
|
|
48
53
|
if (!named || obj == null) {
|
|
49
|
-
return { ...QUICK, dismissed };
|
|
54
|
+
return { ...QUICK, enabled, dismissed };
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
return {
|
|
58
|
+
enabled,
|
|
53
59
|
mode: "named",
|
|
54
60
|
hostname: obj.namedTunnelHostname as string,
|
|
55
61
|
tunnelName: nonEmptyString(obj.namedTunnelName) ? obj.namedTunnelName : null,
|
|
@@ -159,6 +159,10 @@ async function runSetupInner(hostname: string): Promise<SetupOutcome> {
|
|
|
159
159
|
|
|
160
160
|
broadcastGlobalEvent({ type: "tunnel:setup_step", step: "apply", message: "applying configuration" });
|
|
161
161
|
configService.set("tunnel", {
|
|
162
|
+
// Carry the master switch across rather than defaulting it: configuring a
|
|
163
|
+
// domain is not consent to start sharing, and this write would otherwise
|
|
164
|
+
// silently turn a deliberately-off tunnel back on.
|
|
165
|
+
enabled: configService.get("tunnel").enabled,
|
|
162
166
|
mode: "named",
|
|
163
167
|
namedTunnelName: tunnelName,
|
|
164
168
|
namedTunnelHostname: hostname,
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streaming line reader for the JSONL transcripts.
|
|
3
|
+
*
|
|
4
|
+
* Its own module because two readers need it — the full message parser and the
|
|
5
|
+
* compaction scan — and having the second import it from the first would make the
|
|
6
|
+
* two files a cycle.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Yield a file's lines without holding the file in memory.
|
|
11
|
+
*
|
|
12
|
+
* `Bun.file().text()` plus `split("\n")` costs the whole transcript twice over —
|
|
13
|
+
* 277MB resident for a 77MB file, which is what forced a cap low enough to
|
|
14
|
+
* reject real sessions. Peak here is one chunk plus one line.
|
|
15
|
+
*
|
|
16
|
+
* `fromByte` reads a tail window instead of the whole file, for the callers that
|
|
17
|
+
* have to bound what they parse. See `fullParseWindow` in
|
|
18
|
+
* `jsonl-transcript-parser.ts` for why a bound is a window rather than a refusal.
|
|
19
|
+
*/
|
|
20
|
+
export async function* readLines(filePath: string, fromByte = 0): AsyncGenerator<string> {
|
|
21
|
+
const decoder = new TextDecoder();
|
|
22
|
+
// Explicit reader rather than `for await` over the stream: the DOM lib's
|
|
23
|
+
// ReadableStream is not typed as async-iterable, and the `finally` is what
|
|
24
|
+
// releases it when a caller breaks early on `beforeUuid`.
|
|
25
|
+
// One byte *before* the offset, so the first line the split produces is
|
|
26
|
+
// always the tail of the record the offset fell inside — the empty string
|
|
27
|
+
// when it fell exactly on a newline. That makes the drop below unconditional
|
|
28
|
+
// instead of a boundary case, and a boundary case here silently costs a whole
|
|
29
|
+
// record rather than a fragment.
|
|
30
|
+
const file = fromByte > 0 ? Bun.file(filePath).slice(fromByte - 1) : Bun.file(filePath);
|
|
31
|
+
const reader = file.stream().getReader();
|
|
32
|
+
// A fragment is not always unparseable — the tail of one record is sometimes
|
|
33
|
+
// a complete smaller document — so it has to go by position rather than be
|
|
34
|
+
// left for `JSON.parse` to reject, or it enters as an invented message.
|
|
35
|
+
let dropPartial = fromByte > 0;
|
|
36
|
+
let buffered = "";
|
|
37
|
+
try {
|
|
38
|
+
while (true) {
|
|
39
|
+
const { done, value } = await reader.read();
|
|
40
|
+
if (done) break;
|
|
41
|
+
buffered += decoder.decode(value, { stream: true });
|
|
42
|
+
const lines = buffered.split("\n");
|
|
43
|
+
buffered = lines.pop() ?? "";
|
|
44
|
+
for (const line of lines) {
|
|
45
|
+
if (dropPartial) { dropPartial = false; continue; }
|
|
46
|
+
yield line;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} finally {
|
|
50
|
+
reader.releaseLock();
|
|
51
|
+
}
|
|
52
|
+
buffered += decoder.decode();
|
|
53
|
+
if (buffered && !dropPartial) yield buffered;
|
|
54
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What "install Whisper" downloads: one whisper.cpp build per platform, one
|
|
3
|
+
* speech model, and the VAD model that goes with every model.
|
|
4
|
+
*
|
|
5
|
+
* Pure and parameterised so the whole matrix is unit-testable without touching
|
|
6
|
+
* `process.*` or the network. Every entry is pinned by tag/revision AND by
|
|
7
|
+
* SHA-256, because this code downloads an executable onto the user's machine.
|
|
8
|
+
*
|
|
9
|
+
* The VAD model is not optional. Whisper invents speech out of silence, and in
|
|
10
|
+
* Vietnamese it invents the same YouTube outro every time — six seconds of
|
|
11
|
+
* digital silence transcribed as "Hãy subscribe cho kênh Ghiền Mì Gõ Để không
|
|
12
|
+
* bỏ lỡ những video hấp dẫn" on both `small` and `large-v3-turbo`, and pink
|
|
13
|
+
* noise as "Cảm ơn các bạn đã theo dõi và hẹn gặp lại." With Silero VAD in
|
|
14
|
+
* front, both come back empty (and in 0.3s instead of seconds).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** whisper.cpp release that the prebuilt binaries come from. */
|
|
18
|
+
export const WHISPER_BUILD = "b5130";
|
|
19
|
+
/** Whisper version inside that build, for display only. */
|
|
20
|
+
export const WHISPER_VERSION = "1.9.4";
|
|
21
|
+
|
|
22
|
+
const RELEASE_BASE = `https://github.com/ggml-org/whisper.cpp/releases/download/${WHISPER_BUILD}`;
|
|
23
|
+
|
|
24
|
+
/** Pinned commits of the Hugging Face repos the models are fetched from. */
|
|
25
|
+
const MODEL_REPO_REV = "5359861c739e955e79d9a303bcbc70fb988958b1";
|
|
26
|
+
const VAD_REPO_REV = "9ffd54a1e1ee413ddf265af9913beaf518d1639b";
|
|
27
|
+
|
|
28
|
+
export interface WhisperAsset {
|
|
29
|
+
/** Archive file name as published in the release. */
|
|
30
|
+
file: string;
|
|
31
|
+
url: string;
|
|
32
|
+
sha256: string;
|
|
33
|
+
ext: "tar.gz" | "zip";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Prebuilt whisper.cpp per platform.
|
|
38
|
+
*
|
|
39
|
+
* macOS is deliberately absent: the release ships an xcframework (a library for
|
|
40
|
+
* Swift apps), never a `whisper-cli`, so there is nothing to download and
|
|
41
|
+
* unpack. A Mac uses Homebrew's `whisper.cpp` formula instead — see
|
|
42
|
+
* `MACOS_INSTALL_HINT` — and PPM then finds `whisper-cli` on PATH.
|
|
43
|
+
*/
|
|
44
|
+
const ASSETS: Record<string, WhisperAsset> = {
|
|
45
|
+
"linux-x64": {
|
|
46
|
+
file: "whisper-bin-ubuntu-x64.tar.gz",
|
|
47
|
+
url: `${RELEASE_BASE}/whisper-bin-ubuntu-x64.tar.gz`,
|
|
48
|
+
sha256: "53e7fd8b5764edad916b8848dd0af6abb1ff1d3b86c899e79c78652412536c32",
|
|
49
|
+
ext: "tar.gz",
|
|
50
|
+
},
|
|
51
|
+
"linux-arm64": {
|
|
52
|
+
file: "whisper-bin-ubuntu-arm64.tar.gz",
|
|
53
|
+
url: `${RELEASE_BASE}/whisper-bin-ubuntu-arm64.tar.gz`,
|
|
54
|
+
sha256: "93532a0e3777f26f041ffa358ee77dd88b1a33a86847c1990745327ff335a5d6",
|
|
55
|
+
ext: "tar.gz",
|
|
56
|
+
},
|
|
57
|
+
"win32-x64": {
|
|
58
|
+
file: "whisper-bin-x64.zip",
|
|
59
|
+
url: `${RELEASE_BASE}/whisper-bin-x64.zip`,
|
|
60
|
+
sha256: "f9ec6c52a2e949b62ab51fa21d0d497958f9e41c3010c157c4e42932d5316f3c",
|
|
61
|
+
ext: "zip",
|
|
62
|
+
},
|
|
63
|
+
"win32-arm64": {
|
|
64
|
+
file: "whisper-bin-win-cpu-arm64.zip",
|
|
65
|
+
url: `${RELEASE_BASE}/whisper-bin-win-cpu-arm64.zip`,
|
|
66
|
+
sha256: "799543b926ab5b6c2d60cab269a2092e0ae8d27820e9e15429e59de3699546fc",
|
|
67
|
+
ext: "zip",
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const MACOS_INSTALL_HINT = "brew install whisper.cpp";
|
|
72
|
+
|
|
73
|
+
/** The published build for a platform/arch pair, or null when there is none. */
|
|
74
|
+
export function whisperAssetFor(platform: NodeJS.Platform, arch: string): WhisperAsset | null {
|
|
75
|
+
return ASSETS[`${platform}-${arch}`] ?? null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface WhisperModel {
|
|
79
|
+
id: string;
|
|
80
|
+
/** File name in the Hugging Face repo, and on disk. */
|
|
81
|
+
file: string;
|
|
82
|
+
label: string;
|
|
83
|
+
/** One line under the label in Settings. */
|
|
84
|
+
note: string;
|
|
85
|
+
bytes: number;
|
|
86
|
+
sha256: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Three rungs, measured on a 10s Vietnamese clip (i9-12900K, 16 threads):
|
|
91
|
+
* `base` 0.9s but "sửa giúp" came back "sửa dụp"; `small` 2.2s and readable;
|
|
92
|
+
* `large-v3-turbo` 5.5s and the only one that kept English identifiers
|
|
93
|
+
* ("handle ... toggle ... message input") intact. Quantized weights, since a
|
|
94
|
+
* q5 file is a third of the size for no accuracy difference anyone dictating a
|
|
95
|
+
* chat message would notice.
|
|
96
|
+
*/
|
|
97
|
+
export const WHISPER_MODELS: WhisperModel[] = [
|
|
98
|
+
{
|
|
99
|
+
id: "base-q5_1",
|
|
100
|
+
file: "ggml-base-q5_1.bin",
|
|
101
|
+
label: "Base",
|
|
102
|
+
note: "Fastest, weakest — usable for English, rough in Vietnamese",
|
|
103
|
+
bytes: 59_707_625,
|
|
104
|
+
sha256: "422f1ae452ade6f30a004d7e5c6a43195e4433bc370bf23fac9cc591f01a8898",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: "small-q5_1",
|
|
108
|
+
file: "ggml-small-q5_1.bin",
|
|
109
|
+
label: "Small",
|
|
110
|
+
note: "Middle ground — readable Vietnamese, garbles English words",
|
|
111
|
+
bytes: 190_085_487,
|
|
112
|
+
sha256: "ae85e4a935d7a567bd102fe55afc16bb595bdb618e11b2fc7591bc08120411bb",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: "large-v3-turbo-q5_0",
|
|
116
|
+
file: "ggml-large-v3-turbo-q5_0.bin",
|
|
117
|
+
label: "Large v3 Turbo",
|
|
118
|
+
note: "Best Vietnamese, keeps English terms — a few seconds per sentence",
|
|
119
|
+
bytes: 574_041_195,
|
|
120
|
+
sha256: "394221709cd5ad1f40c46e6031ca61bce88931e6e088c188294c6d5a55ffa7e2",
|
|
121
|
+
},
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
export const DEFAULT_MODEL_ID = "large-v3-turbo-q5_0";
|
|
125
|
+
|
|
126
|
+
export const VAD_MODEL = {
|
|
127
|
+
file: "ggml-silero-v5.1.2.bin",
|
|
128
|
+
bytes: 885_098,
|
|
129
|
+
sha256: "29940d98d42b91fbd05ce489f3ecf7c72f0a42f027e4875919a28fb4c04ea2cf",
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export function modelById(id: string): WhisperModel | null {
|
|
133
|
+
return WHISPER_MODELS.find((m) => m.id === id) ?? null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function modelUrl(model: WhisperModel): string {
|
|
137
|
+
return `https://huggingface.co/ggerganov/whisper.cpp/resolve/${MODEL_REPO_REV}/${model.file}`;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function vadModelUrl(): string {
|
|
141
|
+
return `https://huggingface.co/ggml-org/whisper-vad/resolve/${VAD_REPO_REV}/${VAD_MODEL.file}`;
|
|
142
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streaming download with a SHA-256 gate.
|
|
3
|
+
*
|
|
4
|
+
* A model is 574 MB, so it is hashed while it streams rather than read back
|
|
5
|
+
* afterwards, and it lands on a `.part` file that is only renamed once the hash
|
|
6
|
+
* matches: an interrupted or tampered download can never be mistaken for an
|
|
7
|
+
* installed one, and a retry starts clean.
|
|
8
|
+
*/
|
|
9
|
+
import { createHash } from "node:crypto";
|
|
10
|
+
import { mkdirSync, renameSync, rmSync } from "node:fs";
|
|
11
|
+
import { dirname } from "node:path";
|
|
12
|
+
|
|
13
|
+
export type FetchFn = typeof fetch;
|
|
14
|
+
|
|
15
|
+
export interface DownloadOptions {
|
|
16
|
+
url: string;
|
|
17
|
+
dest: string;
|
|
18
|
+
/** Lowercase hex. The download is discarded when the bytes hash to anything else. */
|
|
19
|
+
sha256: string;
|
|
20
|
+
/** Called as bytes arrive; `total` is 0 when the server sends no Content-Length. */
|
|
21
|
+
onProgress?: (received: number, total: number) => void;
|
|
22
|
+
fetchFn?: FetchFn;
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* How long the transfer may produce no bytes at all before it is abandoned.
|
|
28
|
+
*
|
|
29
|
+
* Idle rather than wall-clock: the largest model here is 574 MB, and any total-time
|
|
30
|
+
* bound that a slow line can exceed would abort a download that was working. What is
|
|
31
|
+
* never legitimate is silence — a half-open socket after a dropped wifi link or a
|
|
32
|
+
* tunnel that went away never errors and never yields, so without this the `for await`
|
|
33
|
+
* below simply never returns and the install never settles.
|
|
34
|
+
*/
|
|
35
|
+
const STALL_TIMEOUT_MS = 60_000;
|
|
36
|
+
|
|
37
|
+
export async function downloadVerified(opts: DownloadOptions): Promise<void> {
|
|
38
|
+
const { url, dest, sha256, onProgress, signal } = opts;
|
|
39
|
+
const fetchFn = opts.fetchFn ?? fetch;
|
|
40
|
+
const part = `${dest}.part`;
|
|
41
|
+
|
|
42
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
43
|
+
rmSync(part, { force: true });
|
|
44
|
+
|
|
45
|
+
// The caller's signal and the stall timer both have to reach the body stream, and
|
|
46
|
+
// `fetch` takes one signal — so an internal controller carries both.
|
|
47
|
+
const stall = new AbortController();
|
|
48
|
+
const forwardAbort = () => stall.abort(signal?.reason);
|
|
49
|
+
signal?.addEventListener("abort", forwardAbort, { once: true });
|
|
50
|
+
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
51
|
+
const armStallTimer = (): void => {
|
|
52
|
+
if (timer) clearTimeout(timer);
|
|
53
|
+
timer = setTimeout(
|
|
54
|
+
() => stall.abort(new Error(`download stalled: no bytes for ${STALL_TIMEOUT_MS}ms (${url})`)),
|
|
55
|
+
STALL_TIMEOUT_MS,
|
|
56
|
+
);
|
|
57
|
+
timer.unref?.();
|
|
58
|
+
};
|
|
59
|
+
const disarm = (): void => {
|
|
60
|
+
if (timer) clearTimeout(timer);
|
|
61
|
+
timer = null;
|
|
62
|
+
signal?.removeEventListener("abort", forwardAbort);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
let res: Response;
|
|
66
|
+
armStallTimer();
|
|
67
|
+
try {
|
|
68
|
+
res = await fetchFn(url, { redirect: "follow", signal: stall.signal });
|
|
69
|
+
} catch (e) {
|
|
70
|
+
disarm();
|
|
71
|
+
throw stall.signal.aborted && stall.signal.reason instanceof Error ? stall.signal.reason : e;
|
|
72
|
+
}
|
|
73
|
+
if (!res.ok) { disarm(); throw new Error(`download failed: HTTP ${res.status} (${url})`); }
|
|
74
|
+
if (!res.body) { disarm(); throw new Error(`download failed: empty body (${url})`); }
|
|
75
|
+
|
|
76
|
+
const total = Number(res.headers.get("content-length") ?? 0) || 0;
|
|
77
|
+
const hash = createHash("sha256");
|
|
78
|
+
const sink = Bun.file(part).writer();
|
|
79
|
+
let received = 0;
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
for await (const chunk of res.body as unknown as AsyncIterable<Uint8Array>) {
|
|
83
|
+
armStallTimer();
|
|
84
|
+
hash.update(chunk);
|
|
85
|
+
sink.write(chunk);
|
|
86
|
+
received += chunk.byteLength;
|
|
87
|
+
onProgress?.(received, total);
|
|
88
|
+
}
|
|
89
|
+
await sink.end();
|
|
90
|
+
disarm();
|
|
91
|
+
} catch (e) {
|
|
92
|
+
disarm();
|
|
93
|
+
try {
|
|
94
|
+
await sink.end();
|
|
95
|
+
} catch {
|
|
96
|
+
// Sink already torn down by the failure itself.
|
|
97
|
+
}
|
|
98
|
+
rmSync(part, { force: true });
|
|
99
|
+
// An abort raised by the stall timer carries the reason worth reporting; the
|
|
100
|
+
// stream's own `AbortError` says only that somebody cancelled.
|
|
101
|
+
throw stall.signal.aborted && stall.signal.reason instanceof Error ? stall.signal.reason : e;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const actual = hash.digest("hex");
|
|
105
|
+
if (actual !== sha256.toLowerCase()) {
|
|
106
|
+
rmSync(part, { force: true });
|
|
107
|
+
throw new Error(`checksum mismatch for ${url}: expected ${sha256}, got ${actual}`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Windows refuses a rename onto an existing file, so clear the target first.
|
|
111
|
+
rmSync(dest, { force: true });
|
|
112
|
+
renameSync(part, dest);
|
|
113
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sentences Whisper invents when it is handed audio with no speech in it.
|
|
3
|
+
*
|
|
4
|
+
* The model was trained on YouTube subtitles, so the likeliest continuation of
|
|
5
|
+
* "a Vietnamese clip with nothing being said" is that channel's sign-off — and
|
|
6
|
+
* it is not a rare edge case: with `--vad` off, *every* non-speech clip
|
|
7
|
+
* measured on large-v3-turbo (digital silence, white noise at four levels,
|
|
8
|
+
* 50 Hz hum, a 440 Hz tone, brown noise, keyboard clicks, a cough, a breath)
|
|
9
|
+
* came back as the same one sentence, byte for byte:
|
|
10
|
+
*
|
|
11
|
+
* silence/noise/hum/tone/typing/cough → "Hãy subscribe cho kênh Ghiền Mì
|
|
12
|
+
* Gõ Để không bỏ lỡ những video hấp dẫn"
|
|
13
|
+
* room tone → "Cảm ơn các bạn đã theo dõi và hẹn gặp lại."
|
|
14
|
+
*
|
|
15
|
+
* The VAD model is what normally stops this (those same clips come back empty
|
|
16
|
+
* with it on), so this list is the second line of defence for the audio VAD
|
|
17
|
+
* does let through — a fan, a distant TV, a word spoken too far from the mic.
|
|
18
|
+
* It is deliberately short and measured rather than guessed: add a sentence
|
|
19
|
+
* here only after seeing this model produce it from a clip with no speech.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** Same shape as the list: lowercased, punctuation dropped, spaces collapsed. */
|
|
23
|
+
function normalize(line: string): string {
|
|
24
|
+
return line
|
|
25
|
+
.toLowerCase()
|
|
26
|
+
.replace(/[.,!?;:"'`*\-_()[\]…]/g, " ")
|
|
27
|
+
.replace(/\s+/g, " ")
|
|
28
|
+
.trim();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const INVENTED = [
|
|
32
|
+
"Hãy subscribe cho kênh Ghiền Mì Gõ Để không bỏ lỡ những video hấp dẫn",
|
|
33
|
+
"Cảm ơn các bạn đã theo dõi và hẹn gặp lại.",
|
|
34
|
+
].map(normalize);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The channel name is the fingerprint: the sign-off comes back with small
|
|
38
|
+
* wording changes, and nobody dictating into a chat box says it at all.
|
|
39
|
+
*/
|
|
40
|
+
const FINGERPRINT = normalize("Ghiền Mì Gõ");
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* True for a whole segment the model made up. Whole lines only — `-nt` prints
|
|
44
|
+
* one line per segment, so dropping a line drops exactly the invented
|
|
45
|
+
* sentence and leaves the real ones either side of it alone.
|
|
46
|
+
*/
|
|
47
|
+
export function isInventedLine(line: string): boolean {
|
|
48
|
+
const normalized = normalize(line);
|
|
49
|
+
if (normalized.length === 0) return false;
|
|
50
|
+
return INVENTED.includes(normalized) || normalized.includes(FINGERPRINT);
|
|
51
|
+
}
|