@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
|
@@ -16,14 +16,20 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { stat } from "node:fs/promises";
|
|
18
18
|
import path from "node:path";
|
|
19
|
+
import { resolveBunPath } from "../autostart-generator.ts";
|
|
20
|
+
import { canInstall, lspInstallDir, rustupServerPath } from "./lsp-install.ts";
|
|
19
21
|
import { LspSession, type LspSessionState } from "./lsp-session.ts";
|
|
20
22
|
import {
|
|
21
23
|
LANGUAGE_SERVERS,
|
|
22
24
|
ancestorDirs,
|
|
23
25
|
bundledServerEntry,
|
|
24
26
|
candidateCommandPaths,
|
|
27
|
+
installedBinaryPath,
|
|
28
|
+
installedServerEntry,
|
|
25
29
|
lspLanguageForPath,
|
|
30
|
+
serversSharingInstall,
|
|
26
31
|
type LanguageServerDefinition,
|
|
32
|
+
type LanguageServerInstall,
|
|
27
33
|
} from "./server-registry.ts";
|
|
28
34
|
|
|
29
35
|
/** How long a session with no subscribers is kept before being shut down. */
|
|
@@ -52,10 +58,34 @@ export type LspUnavailableReason = "no-language" | "not-installed" | "failed";
|
|
|
52
58
|
export interface LspUnavailable {
|
|
53
59
|
reason: LspUnavailableReason;
|
|
54
60
|
/** The server that would have served it, when one is known. */
|
|
55
|
-
server?: {
|
|
61
|
+
server?: {
|
|
62
|
+
id: string;
|
|
63
|
+
displayName: string;
|
|
64
|
+
installHint: string;
|
|
65
|
+
installable: boolean;
|
|
66
|
+
/** What the button would use, so the editor can say what pressing it does. */
|
|
67
|
+
installWith?: "bun" | "go" | "rustup";
|
|
68
|
+
};
|
|
56
69
|
message: string;
|
|
57
70
|
}
|
|
58
71
|
|
|
72
|
+
/**
|
|
73
|
+
* What the editor needs to name a missing server, and to decide whether to offer to install it.
|
|
74
|
+
*
|
|
75
|
+
* `installable` is the host's answer rather than the editor's guess, and it is not the registry's
|
|
76
|
+
* either: `go install` needs a Go on this machine and `rustup component add` needs a rustup, so
|
|
77
|
+
* the same server is installable on one host and a command to copy on the next.
|
|
78
|
+
*/
|
|
79
|
+
function serverSummary(definition: LanguageServerDefinition): NonNullable<LspUnavailable["server"]> {
|
|
80
|
+
return {
|
|
81
|
+
id: definition.id,
|
|
82
|
+
displayName: definition.displayName,
|
|
83
|
+
installHint: definition.installHint,
|
|
84
|
+
installable: canInstall(definition),
|
|
85
|
+
installWith: definition.install?.with,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
59
89
|
export function isUnavailable(result: LspHandle | LspUnavailable): result is LspUnavailable {
|
|
60
90
|
return "reason" in result;
|
|
61
91
|
}
|
|
@@ -68,6 +98,33 @@ interface Entry {
|
|
|
68
98
|
lastUsed: number;
|
|
69
99
|
}
|
|
70
100
|
|
|
101
|
+
/**
|
|
102
|
+
* The bun that runs a server's entry script.
|
|
103
|
+
*
|
|
104
|
+
* Not `process.execPath`: that is bun only while PPM runs from source. A compiled PPM is its
|
|
105
|
+
* own executable, so spawning it with a script path reaches PPM's *CLI* — the same trap that
|
|
106
|
+
* made a compiled PPM answer `<ppm> x @openai/codex app-server` with "unknown command". `null`
|
|
107
|
+
* on a host with no bun at all, where such a copy cannot be run and must not be called
|
|
108
|
+
* installed.
|
|
109
|
+
*/
|
|
110
|
+
function bunRuntime(): string | null {
|
|
111
|
+
try {
|
|
112
|
+
return resolveBunPath();
|
|
113
|
+
} catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Where a server was found, in the order `resolveCommand` looks.
|
|
120
|
+
*
|
|
121
|
+
* It exists for the Remove button: PPM may delete what PPM installed and nothing else.
|
|
122
|
+
* `project` is the repository's copy, `path` is one the user installed themselves, and
|
|
123
|
+
* `bundled` is PPM's own dependency — removing any of those would be PPM tidying up after
|
|
124
|
+
* someone else, and for `bundled` it would break the TypeScript server a fresh install has.
|
|
125
|
+
*/
|
|
126
|
+
export type ServerOrigin = "project" | "rustup" | "path" | "ppm" | "bundled";
|
|
127
|
+
|
|
71
128
|
async function exists(candidate: string): Promise<boolean> {
|
|
72
129
|
try {
|
|
73
130
|
await stat(candidate);
|
|
@@ -107,6 +164,8 @@ export class LspManager {
|
|
|
107
164
|
private readonly servers: LanguageServerDefinition[] = LANGUAGE_SERVERS,
|
|
108
165
|
private readonly idleGraceMs: number = IDLE_GRACE_MS,
|
|
109
166
|
private readonly maxSessions: number = MAX_SESSIONS,
|
|
167
|
+
/** Called rather than held, so `PPM_HOME` is read when a server is looked for, not at import. */
|
|
168
|
+
private readonly installDir: () => string = lspInstallDir,
|
|
110
169
|
) {}
|
|
111
170
|
|
|
112
171
|
onNotification(listener: (key: string, method: string, params: unknown) => void): () => void {
|
|
@@ -136,8 +195,8 @@ export class LspManager {
|
|
|
136
195
|
|
|
137
196
|
let lastMissing: LanguageServerDefinition | null = null;
|
|
138
197
|
for (const definition of candidates) {
|
|
139
|
-
const
|
|
140
|
-
if (!
|
|
198
|
+
const resolved = await this.resolveCommand(definition, dirs);
|
|
199
|
+
if (!resolved) {
|
|
141
200
|
lastMissing = definition;
|
|
142
201
|
continue;
|
|
143
202
|
}
|
|
@@ -146,7 +205,7 @@ export class LspManager {
|
|
|
146
205
|
|
|
147
206
|
this.claim(key);
|
|
148
207
|
try {
|
|
149
|
-
const session = await this.startOrReuse(key, definition, command, rootPath);
|
|
208
|
+
const session = await this.startOrReuse(key, definition, resolved.command, rootPath);
|
|
150
209
|
// Subscribe *then* trim, so the session this call is about to hand out is never the
|
|
151
210
|
// one the cap takes away.
|
|
152
211
|
if (!this.subscribe(key, subscriber)) {
|
|
@@ -161,7 +220,7 @@ export class LspManager {
|
|
|
161
220
|
} catch (e) {
|
|
162
221
|
return {
|
|
163
222
|
reason: "failed",
|
|
164
|
-
server:
|
|
223
|
+
server: serverSummary(definition),
|
|
165
224
|
message: e instanceof Error ? e.message : String(e),
|
|
166
225
|
};
|
|
167
226
|
} finally {
|
|
@@ -172,7 +231,7 @@ export class LspManager {
|
|
|
172
231
|
const missing = lastMissing ?? candidates[0]!;
|
|
173
232
|
return {
|
|
174
233
|
reason: "not-installed",
|
|
175
|
-
server:
|
|
234
|
+
server: serverSummary(missing),
|
|
176
235
|
message: `${missing.displayName} is not installed.`,
|
|
177
236
|
};
|
|
178
237
|
}
|
|
@@ -322,25 +381,51 @@ export class LspManager {
|
|
|
322
381
|
*
|
|
323
382
|
* The project's own copy first, because a repository pinned to TypeScript 4 has to be
|
|
324
383
|
* analysed by its own server — the same reason VS Code offers "Use Workspace Version".
|
|
325
|
-
* Then
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
384
|
+
* Then rustup, which owns its answer completely (below). Then `PATH`, which is whatever the
|
|
385
|
+
* user deliberately installed. Then PPM's own directory: what the Install button put there,
|
|
386
|
+
* and then the copy PPM ships, which is the floor rather than a preference — it is how a
|
|
387
|
+
* fresh install has a working TypeScript server with nothing else done, and it must never win
|
|
388
|
+
* over either of the two choices someone actually made.
|
|
329
389
|
*/
|
|
330
|
-
private async resolveCommand(
|
|
390
|
+
private async resolveCommand(
|
|
391
|
+
definition: LanguageServerDefinition,
|
|
392
|
+
dirs: string[],
|
|
393
|
+
): Promise<{ command: string[]; origin: ServerOrigin } | null> {
|
|
331
394
|
const candidates = candidateCommandPaths(definition.command, dirs);
|
|
332
395
|
for (const candidate of candidates.slice(0, -1)) {
|
|
333
|
-
if (await exists(candidate)) return [candidate];
|
|
396
|
+
if (await exists(candidate)) return { command: [candidate], origin: "project" };
|
|
334
397
|
}
|
|
398
|
+
// rust-analyzer is a toolchain component rather than a file PPM owns, so rustup is asked
|
|
399
|
+
// where it is — in the file's own directory, so a repository pinning a toolchain gets that
|
|
400
|
+
// toolchain's server. This has to come *before* PATH, because `~/.cargo/bin/rust-analyzer`
|
|
401
|
+
// is a rustup proxy that exists whether or not the component does: found on PATH it reports
|
|
402
|
+
// an installed server, and spawning it prints "unknown binary" and exits, which is a broken
|
|
403
|
+
// server rather than the missing one the Install button is offered for. Costs nothing for
|
|
404
|
+
// every other server — it answers null on sight of a definition that is not rustup's.
|
|
405
|
+
const fromRustup = await rustupServerPath(definition, dirs[0] ?? process.cwd());
|
|
406
|
+
if (fromRustup) return { command: [fromRustup], origin: "rustup" };
|
|
407
|
+
|
|
335
408
|
// The last candidate is the bare command, which means PATH.
|
|
336
409
|
const onPath = Bun.which(definition.command);
|
|
337
|
-
if (onPath) return [onPath];
|
|
410
|
+
if (onPath) return { command: [onPath], origin: "path" };
|
|
411
|
+
|
|
412
|
+
// What the Install button built with the host's Go: a real binary in PPM's own directory,
|
|
413
|
+
// spawned as itself.
|
|
414
|
+
const binary = installedBinaryPath(definition, this.installDir());
|
|
415
|
+
if (binary && (await exists(binary))) return { command: [binary], origin: "ppm" };
|
|
338
416
|
|
|
339
|
-
|
|
340
|
-
// Run by the runtime PPM is already using, not through npm's `.bin` shim: that shim is
|
|
417
|
+
// Both of PPM's npm copies are entry scripts rather than npm's `.bin` shims: that shim is
|
|
341
418
|
// `#!/usr/bin/env node`, and someone who installed PPM with bun may have no node at all —
|
|
342
419
|
// which fails as exit code 127 at spawn time, long after the server looked installed.
|
|
343
|
-
|
|
420
|
+
for (const [entry, origin] of [
|
|
421
|
+
[installedServerEntry(definition, this.installDir()), "ppm"],
|
|
422
|
+
[bundledServerEntry(definition), "bundled"],
|
|
423
|
+
] as const) {
|
|
424
|
+
if (!entry || !(await exists(entry))) continue;
|
|
425
|
+
const runtime = bunRuntime();
|
|
426
|
+
return runtime ? { command: [runtime, entry], origin } : null;
|
|
427
|
+
}
|
|
428
|
+
return null;
|
|
344
429
|
}
|
|
345
430
|
|
|
346
431
|
/**
|
|
@@ -382,24 +467,70 @@ export class LspManager {
|
|
|
382
467
|
}
|
|
383
468
|
|
|
384
469
|
/**
|
|
385
|
-
* Which of the registered servers
|
|
470
|
+
* Which of the registered servers could actually be used.
|
|
386
471
|
*
|
|
387
|
-
* Answers the editor's "why is nothing happening" question directly, with the
|
|
388
|
-
*
|
|
472
|
+
* Answers the editor's "why is nothing happening" question directly, with the install
|
|
473
|
+
* command for anything missing. With no `projectPath` it answers for the *machine* — no
|
|
474
|
+
* project `node_modules/.bin` is consulted — which is what the Settings pane asks, since it
|
|
475
|
+
* is not open on any one project.
|
|
389
476
|
*/
|
|
390
|
-
async availability(projectPath
|
|
391
|
-
Array<{
|
|
477
|
+
async availability(projectPath?: string): Promise<
|
|
478
|
+
Array<{
|
|
479
|
+
id: string;
|
|
480
|
+
displayName: string;
|
|
481
|
+
languages: string[];
|
|
482
|
+
installed: boolean;
|
|
483
|
+
installHint: string;
|
|
484
|
+
installable: boolean;
|
|
485
|
+
installWith?: LanguageServerInstall["with"];
|
|
486
|
+
origin?: ServerOrigin;
|
|
487
|
+
/** Whether PPM may remove it — that is, whether PPM is what put it there. */
|
|
488
|
+
removable: boolean;
|
|
489
|
+
/** Servers the same removal would also take, because one npm package provides several. */
|
|
490
|
+
alsoRemoves?: string[];
|
|
491
|
+
}>
|
|
392
492
|
> {
|
|
393
|
-
const dirs = [projectPath];
|
|
493
|
+
const dirs = projectPath ? [projectPath] : [];
|
|
394
494
|
return Promise.all(
|
|
395
|
-
this.servers.map(async (definition) =>
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
495
|
+
this.servers.map(async (definition) => {
|
|
496
|
+
const resolved = await this.resolveCommand(definition, dirs);
|
|
497
|
+
const origin = resolved?.origin;
|
|
498
|
+
const removable = origin === "ppm" || origin === "rustup";
|
|
499
|
+
const shared = removable ? serversSharingInstall(definition).map((s) => s.displayName) : [];
|
|
500
|
+
return {
|
|
501
|
+
id: definition.id,
|
|
502
|
+
displayName: definition.displayName,
|
|
503
|
+
languages: definition.languages,
|
|
504
|
+
installed: resolved !== null,
|
|
505
|
+
installHint: definition.installHint,
|
|
506
|
+
installable: canInstall(definition),
|
|
507
|
+
installWith: definition.install?.with,
|
|
508
|
+
origin,
|
|
509
|
+
removable,
|
|
510
|
+
...(shared.length > 0 ? { alsoRemoves: shared } : {}),
|
|
511
|
+
};
|
|
512
|
+
}),
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Stop this server's idle sessions, for an uninstall that is about to delete it.
|
|
518
|
+
*
|
|
519
|
+
* Only the ones nobody is holding. A session with a subscriber is an editor open on it, and
|
|
520
|
+
* taking that away answers every later request with "the language server is no longer
|
|
521
|
+
* running" until the tab is closed and reopened — the same reason `enforceSessionCap` leaves
|
|
522
|
+
* held sessions alone. One that keeps running is running on files it already opened, which
|
|
523
|
+
* is harmless everywhere except Windows, where it is also what refuses the unlink.
|
|
524
|
+
*/
|
|
525
|
+
async stopIdle(serverId: string): Promise<void> {
|
|
526
|
+
const doomed = [...this.entries.entries()].filter(
|
|
527
|
+
([, entry]) => entry.session.definition.id === serverId && entry.subscribers.size === 0,
|
|
402
528
|
);
|
|
529
|
+
for (const [key, entry] of doomed) {
|
|
530
|
+
if (entry.idleTimer) clearTimeout(entry.idleTimer);
|
|
531
|
+
this.entries.delete(key);
|
|
532
|
+
}
|
|
533
|
+
await Promise.all(doomed.map(([, entry]) => entry.session.dispose()));
|
|
403
534
|
}
|
|
404
535
|
|
|
405
536
|
/**
|
|
@@ -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
|
+
}
|