@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
|
@@ -28,7 +28,9 @@ import { BottomSheet } from "@/components/ui/mobile-bottom-sheet";
|
|
|
28
28
|
import { GitRepoBar, GitRepoChoice, GitNoRepo } from "@/components/git/git-repo-picker";
|
|
29
29
|
import { FileIcon } from "@/lib/file-icons";
|
|
30
30
|
import { buildTree, compactTree } from "@/lib/git-file-tree";
|
|
31
|
-
import {
|
|
31
|
+
import { TreeRow } from "./branch-review-tree-row";
|
|
32
|
+
import { StartEllipsis } from "@/components/ui/start-ellipsis";
|
|
33
|
+
import { BranchSelect } from "@/components/git/branch-select";
|
|
32
34
|
import {
|
|
33
35
|
Check, ChevronDown, ChevronRight, FileText, Loader2, RefreshCw, ListChecks, ArrowRight,
|
|
34
36
|
} from "@/lib/icons";
|
|
@@ -246,30 +248,28 @@ export function BranchReviewTab({ metadata }: BranchReviewTabProps) {
|
|
|
246
248
|
)}
|
|
247
249
|
|
|
248
250
|
{/*
|
|
249
|
-
|
|
250
|
-
hundreds of branches,
|
|
251
|
-
|
|
251
|
+
A searchable picker rather than a native `<select>`: the list is the
|
|
252
|
+
whole problem here — hundreds of branches, all sharing a prefix — and a
|
|
253
|
+
native picker cannot be filtered. See `branch-select.tsx`.
|
|
252
254
|
*/}
|
|
253
255
|
<div className="flex items-center gap-2 px-2 py-1.5 border-b border-border shrink-0 flex-wrap">
|
|
254
|
-
<
|
|
256
|
+
<BranchSelect
|
|
255
257
|
value={base}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
</select>
|
|
258
|
+
branches={branches}
|
|
259
|
+
onChange={setBase}
|
|
260
|
+
label="Base branch"
|
|
261
|
+
testId="branch-review-base"
|
|
262
|
+
className="max-w-[38%]"
|
|
263
|
+
/>
|
|
263
264
|
<ArrowRight className="size-3.5 text-text-3 shrink-0" />
|
|
264
|
-
<
|
|
265
|
+
<BranchSelect
|
|
265
266
|
value={head}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
</select>
|
|
267
|
+
branches={branches}
|
|
268
|
+
onChange={setHead}
|
|
269
|
+
label="Branch to review"
|
|
270
|
+
testId="branch-review-head"
|
|
271
|
+
className="max-w-[38%]"
|
|
272
|
+
/>
|
|
273
273
|
|
|
274
274
|
<div className="ml-auto flex items-center gap-2">
|
|
275
275
|
<span className="text-xs text-text-2 tabular-nums" data-testid="branch-review-progress">
|
|
@@ -18,6 +18,7 @@ import { Check, ChevronDown, ChevronRight } from "@/lib/icons";
|
|
|
18
18
|
import { FileIcon } from "@/lib/file-icons";
|
|
19
19
|
import { isReviewed, type ReviewState } from "@/lib/branch-review-state";
|
|
20
20
|
import type { TreeNode } from "@/lib/git-file-tree";
|
|
21
|
+
import { StartEllipsis } from "@/components/ui/start-ellipsis";
|
|
21
22
|
import type { BranchDiffFile } from "../../../types/git";
|
|
22
23
|
|
|
23
24
|
export const STATUS_COLORS: Record<BranchDiffFile["status"], string> = {
|
|
@@ -32,19 +33,6 @@ export const STATUS_COLORS: Record<BranchDiffFile["status"], string> = {
|
|
|
32
33
|
/** Indent per nesting level, matching the Source Control tree. */
|
|
33
34
|
export const TREE_INDENT = 14;
|
|
34
35
|
|
|
35
|
-
/**
|
|
36
|
-
* Ellipsize from the start, so the end of a path — the part that differs —
|
|
37
|
-
* survives. Same trick as the Source Control panel: a right-to-left box cuts at
|
|
38
|
-
* its left edge, and `<bdi>` keeps the name itself reading left to right.
|
|
39
|
-
*/
|
|
40
|
-
export function StartEllipsis({ children }: { children: string }) {
|
|
41
|
-
return (
|
|
42
|
-
<span dir="rtl" className="truncate text-left min-w-0 flex-1">
|
|
43
|
-
<bdi>{children}</bdi>
|
|
44
|
-
</span>
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
36
|
export interface TreeRowProps {
|
|
49
37
|
node: TreeNode;
|
|
50
38
|
depth: number;
|
|
@@ -301,6 +301,7 @@ function ChatTabContent({ metadata, tabId, onNewSession, onFork, historyFilter }
|
|
|
301
301
|
pendingApproval,
|
|
302
302
|
contextWindowPct,
|
|
303
303
|
compactStatus,
|
|
304
|
+
promptCache,
|
|
304
305
|
mcpNeedsAuth,
|
|
305
306
|
statusMessage,
|
|
306
307
|
sessionTitle,
|
|
@@ -1027,6 +1028,7 @@ function ChatTabContent({ metadata, tabId, onNewSession, onFork, historyFilter }
|
|
|
1027
1028
|
connectingElapsed={connectingElapsed}
|
|
1028
1029
|
statusMessage={statusMessage}
|
|
1029
1030
|
compactStatus={compactStatus}
|
|
1031
|
+
promptCache={promptCache}
|
|
1030
1032
|
projectName={projectName}
|
|
1031
1033
|
onFork={!isStreaming ? handleFork : undefined}
|
|
1032
1034
|
onEdit={!isStreaming ? handleEdit : undefined}
|
|
@@ -1158,6 +1160,7 @@ function ChatTabContent({ metadata, tabId, onNewSession, onFork, historyFilter }
|
|
|
1158
1160
|
onEffortChange={setEffort}
|
|
1159
1161
|
thinking={thinking}
|
|
1160
1162
|
onThinkingChange={setThinking}
|
|
1163
|
+
promptCache={promptCache}
|
|
1161
1164
|
/>
|
|
1162
1165
|
)}
|
|
1163
1166
|
</div>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Layers } from "@/lib/icons";
|
|
2
|
+
import type { CompactionInfo } from "../../../types/chat";
|
|
3
|
+
import { fmtTokens } from "../../../shared/turn-usage";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The rule above a compact summary, saying what that compaction did.
|
|
7
|
+
*
|
|
8
|
+
* Compaction is the largest thing that happens to a chat and the only one with no
|
|
9
|
+
* visible cause: most of the history stops being sent, the next turn's prefix
|
|
10
|
+
* collapses, and all the transcript shows for it is a long summary message that
|
|
11
|
+
* reads like something the assistant chose to write. Naming it — and how much it
|
|
12
|
+
* dropped — is what makes the rest of the conversation legible.
|
|
13
|
+
*
|
|
14
|
+
* Deliberately not interactive. Loading the messages it replaced is already the job
|
|
15
|
+
* of the scroll-to-top expansion right above it, and a second control for the same
|
|
16
|
+
* thing would be two affordances competing over one gesture.
|
|
17
|
+
*/
|
|
18
|
+
export function CompactionDivider({ compaction }: { compaction: CompactionInfo }) {
|
|
19
|
+
const { trigger, preTokens, postTokens, savedTokens, durationMs } = compaction;
|
|
20
|
+
|
|
21
|
+
const detail = [
|
|
22
|
+
trigger === "manual" ? "Ran with /compact" : "Ran automatically on a full context window",
|
|
23
|
+
`${fmtTokens(preTokens)} → ${fmtTokens(postTokens)} tokens`,
|
|
24
|
+
...(durationMs != null ? [`took ${formatDuration(durationMs)}`] : []),
|
|
25
|
+
].join(" · ");
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="flex items-center gap-2 pt-2 text-[11px] text-text-subtle" title={detail}>
|
|
29
|
+
<div className="h-px flex-1 bg-border" />
|
|
30
|
+
<span className="flex shrink-0 items-center gap-1.5">
|
|
31
|
+
<Layers className="size-3.5" />
|
|
32
|
+
{/* `tabular-nums` so the figure does not jitter when a re-read changes it. */}
|
|
33
|
+
<span className="tabular-nums">
|
|
34
|
+
Compacted session · saved {fmtTokens(savedTokens)} tokens
|
|
35
|
+
</span>
|
|
36
|
+
</span>
|
|
37
|
+
<div className="h-px flex-1 bg-border" />
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Coarse on purpose: this is a footnote, and a compaction is never sub-second. */
|
|
43
|
+
function formatDuration(ms: number): string {
|
|
44
|
+
const seconds = Math.round(ms / 1000);
|
|
45
|
+
if (seconds < 60) return `${seconds}s`;
|
|
46
|
+
const minutes = Math.floor(seconds / 60);
|
|
47
|
+
return `${minutes}m ${seconds % 60}s`;
|
|
48
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Clock } from "@/lib/icons";
|
|
2
|
+
import { useMinuteClock } from "@/hooks/use-minute-clock";
|
|
3
|
+
import type { PromptCacheState } from "../../../shared/prompt-cache-idle";
|
|
4
|
+
import { idleCacheNotice, formatIdleDuration, formatContextTokens } from "../../../shared/prompt-cache-idle";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* How long the session has been idle, when that has stopped being free.
|
|
8
|
+
*
|
|
9
|
+
* Sits above the composer rather than in the transcript: it describes what the *next*
|
|
10
|
+
* message will cost, not anything that has happened, and the transcript is a record of
|
|
11
|
+
* what did. It disappears on its own the moment a turn starts, because by then the
|
|
12
|
+
* decision it exists to inform has been made.
|
|
13
|
+
*
|
|
14
|
+
* Says one of two things. A compaction replaced the conversation, so the cache holds a prefix
|
|
15
|
+
* that will never be sent again — that is reported without a token figure, because the
|
|
16
|
+
* summary it produced has not been through an API call yet and nothing has measured it.
|
|
17
|
+
* Otherwise the cache simply lapsed, and the transcript still standing is what gets re-sent.
|
|
18
|
+
*
|
|
19
|
+
* Names a token figure only when one was measured. `modelUsage` cannot supply it — the SDK
|
|
20
|
+
* accumulates it across the session and across subagents, which is what once printed "1.0M
|
|
21
|
+
* tokens" against a window of the same size — so the number comes from the turn's last
|
|
22
|
+
* top-level assistant message instead (`TurnUsage.contextTokens`). Turns recorded before PPM
|
|
23
|
+
* measured that carry none, and the sentence has to stand without it.
|
|
24
|
+
*
|
|
25
|
+
* Owns its outer padding so that "no notice" costs no layout: the caller renders this
|
|
26
|
+
* unconditionally, and a wrapper with padding around nothing is a gap above the composer
|
|
27
|
+
* that appears for no reason.
|
|
28
|
+
*/
|
|
29
|
+
export function IdleCacheNotice({ promptCache }: { promptCache: PromptCacheState | null }) {
|
|
30
|
+
const notice = idleCacheNotice(promptCache, useMinuteClock());
|
|
31
|
+
if (!notice) return null;
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
// Same `px-4 pt-4 pb-4` as the approval/thinking block below, so the notice keeps the
|
|
35
|
+
// composer's breathing room instead of sitting on top of it.
|
|
36
|
+
<div className="px-4 pt-4 pb-4 select-none">
|
|
37
|
+
{/* `w-fit` rather than a full-width row: this is one sentence, and a thin bordered
|
|
38
|
+
box stretched across an ultrawide reads as a broken layout. It still falls back
|
|
39
|
+
to the available width — and wraps — on a phone. */}
|
|
40
|
+
<div className="flex w-fit items-start gap-2 rounded-md border border-border bg-surface px-2.5 py-2 text-[11px] text-text-secondary">
|
|
41
|
+
<Clock className="mt-px size-3.5 shrink-0 text-text-subtle" />
|
|
42
|
+
{notice.reason === "compacted" ? (
|
|
43
|
+
<span>
|
|
44
|
+
The conversation was compacted{" "}
|
|
45
|
+
<span className="tabular-nums">{formatIdleDuration(notice.idleMs)}</span> ago, so the
|
|
46
|
+
prompt cache no longer covers it and your next message will re-cache it.
|
|
47
|
+
</span>
|
|
48
|
+
) : (
|
|
49
|
+
<span>
|
|
50
|
+
Idle <span className="tabular-nums">{formatIdleDuration(notice.idleMs)}</span>. The
|
|
51
|
+
prompt cache has likely expired, so your next message re-sends{" "}
|
|
52
|
+
{notice.contextTokens != null ? (
|
|
53
|
+
<>
|
|
54
|
+
about{" "}
|
|
55
|
+
<span className="tabular-nums">{formatContextTokens(notice.contextTokens)}</span>{" "}
|
|
56
|
+
tokens
|
|
57
|
+
</>
|
|
58
|
+
) : (
|
|
59
|
+
"the whole transcript"
|
|
60
|
+
)}{" "}
|
|
61
|
+
at full price.
|
|
62
|
+
</span>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
@@ -3,6 +3,8 @@ import { useProjectStore } from "@/stores/project-store";
|
|
|
3
3
|
import { useState, useRef, useCallback, useEffect, memo, type KeyboardEvent, type DragEvent, type ClipboardEvent } from "react";
|
|
4
4
|
import { ArrowUp, Square, Paperclip, Loader2, Mic, MicOff, Zap, ListOrdered, Clock, Bot, X } from "@/lib/icons";
|
|
5
5
|
import { useVoiceInput } from "@/hooks/use-voice-input";
|
|
6
|
+
import { useWhisperVoiceInput } from "@/hooks/use-whisper-voice-input";
|
|
7
|
+
import { useSettingsStore } from "@/stores/settings-store";
|
|
6
8
|
import { api, projectUrl, getAuthToken } from "@/lib/api-client";
|
|
7
9
|
import { downscaleImage } from "@/lib/image-resize";
|
|
8
10
|
import { INLINE_IMAGE_LIMITS } from "@/lib/image-resize-limits";
|
|
@@ -20,6 +22,8 @@ import type { SlashItem } from "./slash-command-picker";
|
|
|
20
22
|
import { fetchSlashItems, clearSlashItemsCache } from "@/lib/slash-items-cache";
|
|
21
23
|
import type { FileNode } from "../../../types/project";
|
|
22
24
|
import { useFileStore } from "@/stores/file-store";
|
|
25
|
+
import { PromptCacheChip } from "./prompt-cache-chip";
|
|
26
|
+
import type { PromptCacheState } from "../../../shared/prompt-cache-idle";
|
|
23
27
|
|
|
24
28
|
/**
|
|
25
29
|
* Base64 payload for an image file, or undefined when it cannot be read.
|
|
@@ -136,6 +140,8 @@ interface MessageInputProps {
|
|
|
136
140
|
thinking?: boolean;
|
|
137
141
|
/** Thinking toggle handler */
|
|
138
142
|
onThinkingChange?: (enabled: boolean) => void;
|
|
143
|
+
/** This session's prompt-cache clock, for the countdown chip */
|
|
144
|
+
promptCache?: PromptCacheState | null;
|
|
139
145
|
}
|
|
140
146
|
|
|
141
147
|
export const MessageInput = memo(function MessageInput({
|
|
@@ -172,6 +178,7 @@ export const MessageInput = memo(function MessageInput({
|
|
|
172
178
|
onEffortChange,
|
|
173
179
|
thinking,
|
|
174
180
|
onThinkingChange,
|
|
181
|
+
promptCache,
|
|
175
182
|
configurationPending = false,
|
|
176
183
|
}: MessageInputProps) {
|
|
177
184
|
// Uncontrolled textarea: value lives in DOM + ref, not React state.
|
|
@@ -248,8 +255,16 @@ export const MessageInput = memo(function MessageInput({
|
|
|
248
255
|
[getUserHistory, writeTextareas, getVisibleTextarea],
|
|
249
256
|
);
|
|
250
257
|
|
|
251
|
-
// Voice input
|
|
252
|
-
|
|
258
|
+
// Voice input. Two engines behind the same button: the browser's own
|
|
259
|
+
// recogniser (text appears as you speak, but Chrome/Edge/Safari only) and
|
|
260
|
+
// Whisper running on the PPM host (any browser, answers once at the end).
|
|
261
|
+
// Settings picks, per device; an engine the device cannot do falls back.
|
|
262
|
+
const voiceEngine = useSettingsStore((s) => s.voiceEngine);
|
|
263
|
+
const browserVoice = useVoiceInput();
|
|
264
|
+
const whisperVoice = useWhisperVoiceInput();
|
|
265
|
+
const useWhisper = voiceEngine === "whisper" && whisperVoice.supported;
|
|
266
|
+
const voice = useWhisper ? whisperVoice : browserVoice;
|
|
267
|
+
const isTranscribing = useWhisper && whisperVoice.isTranscribing;
|
|
253
268
|
// Store pre-voice text so voice appends to existing input
|
|
254
269
|
const preVoiceTextRef = useRef("");
|
|
255
270
|
const voiceResultCb = useCallback((text: string) => {
|
|
@@ -268,13 +283,20 @@ export const MessageInput = memo(function MessageInput({
|
|
|
268
283
|
}
|
|
269
284
|
}, [writeTextareas, getVisibleTextarea]);
|
|
270
285
|
const handleVoiceToggle = useCallback(() => {
|
|
286
|
+
// The shortcut reaches this while Whisper is still working on the last
|
|
287
|
+
// recording, where the button is already disabled.
|
|
288
|
+
if (isTranscribing) return;
|
|
271
289
|
if (voice.isListening) {
|
|
272
290
|
voice.stop();
|
|
273
291
|
} else {
|
|
274
292
|
preVoiceTextRef.current = valueRef.current.trim();
|
|
275
293
|
voice.start(voiceResultCb);
|
|
276
294
|
}
|
|
277
|
-
}, [voice.isListening, voice.start, voice.stop, voiceResultCb]);
|
|
295
|
+
}, [voice.isListening, voice.start, voice.stop, voiceResultCb, isTranscribing]);
|
|
296
|
+
|
|
297
|
+
const micLabel = isTranscribing
|
|
298
|
+
? "Transcribing"
|
|
299
|
+
: voice.isListening ? "Stop voice input" : "Start voice input";
|
|
278
300
|
|
|
279
301
|
// Listen for global keyboard shortcut (Cmd+Shift+V) to toggle voice.
|
|
280
302
|
// Guarded so that only the focused panel's chat reacts — every chat tab stays
|
|
@@ -691,7 +713,13 @@ export const MessageInput = memo(function MessageInput({
|
|
|
691
713
|
slashPickerOpenRef.current = false;
|
|
692
714
|
onFileStateChange?.(false, "");
|
|
693
715
|
filePickerOpenRef.current = false;
|
|
694
|
-
|
|
716
|
+
// Sending closes the mic. Whisper's recording is dropped rather than
|
|
717
|
+
// transcribed: its text would arrive seconds later, into the box the
|
|
718
|
+
// message just left.
|
|
719
|
+
if (voice.isListening) {
|
|
720
|
+
if (useWhisper) whisperVoice.cancel();
|
|
721
|
+
else voice.stop();
|
|
722
|
+
}
|
|
695
723
|
onSend(content, readyAttachments, isStreaming ? priority : undefined);
|
|
696
724
|
writeTextareas("");
|
|
697
725
|
// Revoke preview URLs
|
|
@@ -707,7 +735,8 @@ export const MessageInput = memo(function MessageInput({
|
|
|
707
735
|
if (textareaRef.current) textareaRef.current.style.height = "auto";
|
|
708
736
|
if (mobileTextareaRef.current) mobileTextareaRef.current.style.height = "auto";
|
|
709
737
|
}
|
|
710
|
-
}, [attachments, agentTag, onSend, onSlashStateChange, onFileStateChange, isStreaming, priority, writeTextareas
|
|
738
|
+
}, [attachments, agentTag, onSend, onSlashStateChange, onFileStateChange, isStreaming, priority, writeTextareas,
|
|
739
|
+
voice.isListening, voice.stop, whisperVoice.cancel, useWhisper]);
|
|
711
740
|
|
|
712
741
|
const handleSend = useCallback(() => {
|
|
713
742
|
if (disabled) return;
|
|
@@ -933,7 +962,7 @@ export const MessageInput = memo(function MessageInput({
|
|
|
933
962
|
{/* Attachment chips (inside container, aligned with input) */}
|
|
934
963
|
<AttachmentChips attachments={attachments} onRemove={removeAttachment} />
|
|
935
964
|
{/* Mobile: mode chip + provider selector row */}
|
|
936
|
-
<div className="flex items-center gap-1 px-2 pt-2 md:hidden relative">
|
|
965
|
+
<div className="flex flex-wrap items-center gap-1 px-2 pt-2 md:hidden relative">
|
|
937
966
|
{!configurationPending && <>
|
|
938
967
|
<ModeChip
|
|
939
968
|
mode={permissionMode ?? "bypassPermissions"}
|
|
@@ -967,6 +996,7 @@ export const MessageInput = memo(function MessageInput({
|
|
|
967
996
|
/>
|
|
968
997
|
)}
|
|
969
998
|
{isStreaming && <PriorityToggle value={priority} onChange={setPriority} />}
|
|
999
|
+
<PromptCacheChip promptCache={promptCache ?? null} />
|
|
970
1000
|
</div>
|
|
971
1001
|
{/* Mobile: single row — attach + textarea + mic + send */}
|
|
972
1002
|
<div className="flex items-end gap-1 md:hidden px-2 py-2">
|
|
@@ -996,15 +1026,17 @@ export const MessageInput = memo(function MessageInput({
|
|
|
996
1026
|
<button
|
|
997
1027
|
type="button"
|
|
998
1028
|
onClick={(e) => { e.stopPropagation(); handleVoiceToggle(); }}
|
|
999
|
-
disabled={disabled}
|
|
1029
|
+
disabled={disabled || isTranscribing}
|
|
1000
1030
|
className={`flex items-center justify-center size-8 shrink-0 rounded-[10px] transition-colors disabled:opacity-50 ${
|
|
1001
1031
|
voice.isListening
|
|
1002
1032
|
? "bg-error text-white animate-pulse"
|
|
1003
1033
|
: "text-text-3 hover:text-text-primary"
|
|
1004
1034
|
}`}
|
|
1005
|
-
aria-label={
|
|
1035
|
+
aria-label={micLabel}
|
|
1006
1036
|
>
|
|
1007
|
-
{
|
|
1037
|
+
{isTranscribing
|
|
1038
|
+
? <Loader2 className="size-4 animate-spin" />
|
|
1039
|
+
: voice.isListening ? <MicOff className="size-4" /> : <Mic className="size-4" />}
|
|
1008
1040
|
</button>
|
|
1009
1041
|
)}
|
|
1010
1042
|
{showCancel ? (
|
|
@@ -1030,7 +1062,7 @@ export const MessageInput = memo(function MessageInput({
|
|
|
1030
1062
|
{/* Desktop: chips row (permission + model) then a single input row
|
|
1031
1063
|
(paperclip | textarea | mic | send) — design PPMWorkspace composer. */}
|
|
1032
1064
|
<div className="hidden md:block">
|
|
1033
|
-
<div className="flex items-center gap-1.5 px-2.5 pt-2.5">
|
|
1065
|
+
<div className="flex flex-wrap items-center gap-1.5 px-2.5 pt-2.5">
|
|
1034
1066
|
{/* Mode indicator chip */}
|
|
1035
1067
|
{!configurationPending && <div className="relative">
|
|
1036
1068
|
<ModeChip
|
|
@@ -1066,6 +1098,7 @@ export const MessageInput = memo(function MessageInput({
|
|
|
1066
1098
|
/>
|
|
1067
1099
|
)}
|
|
1068
1100
|
{isStreaming && <PriorityToggle value={priority} onChange={setPriority} />}
|
|
1101
|
+
<PromptCacheChip promptCache={promptCache ?? null} />
|
|
1069
1102
|
</div>
|
|
1070
1103
|
<div className="flex items-end gap-2 px-2.5 py-2">
|
|
1071
1104
|
<button
|
|
@@ -1094,15 +1127,17 @@ export const MessageInput = memo(function MessageInput({
|
|
|
1094
1127
|
<button
|
|
1095
1128
|
type="button"
|
|
1096
1129
|
onClick={(e) => { e.stopPropagation(); handleVoiceToggle(); }}
|
|
1097
|
-
disabled={disabled}
|
|
1130
|
+
disabled={disabled || isTranscribing}
|
|
1098
1131
|
className={`flex items-center justify-center size-[34px] shrink-0 rounded-[10px] transition-colors disabled:opacity-50 ${
|
|
1099
1132
|
voice.isListening
|
|
1100
1133
|
? "bg-error text-white animate-pulse"
|
|
1101
1134
|
: "text-text-3 hover:text-text-primary hover:bg-surface-elevated"
|
|
1102
1135
|
}`}
|
|
1103
|
-
aria-label={
|
|
1136
|
+
aria-label={micLabel}
|
|
1104
1137
|
>
|
|
1105
|
-
{
|
|
1138
|
+
{isTranscribing
|
|
1139
|
+
? <Loader2 className="size-[17px] animate-spin" />
|
|
1140
|
+
: voice.isListening ? <MicOff className="size-[17px]" /> : <Mic className="size-[17px]" />}
|
|
1106
1141
|
</button>
|
|
1107
1142
|
)}
|
|
1108
1143
|
{showCancel ? (
|
|
@@ -18,6 +18,9 @@ import { extractJsonlPath } from "./pre-compact-button";
|
|
|
18
18
|
import { MarkdownContent } from "./message-markdown";
|
|
19
19
|
import { UserBubble } from "./message-user-bubble";
|
|
20
20
|
import { InterleavedEvents, ThinkingIndicator } from "./message-events";
|
|
21
|
+
import { CompactionDivider } from "./compaction-divider";
|
|
22
|
+
import { IdleCacheNotice } from "./idle-cache-notice";
|
|
23
|
+
import type { PromptCacheState } from "../../../shared/prompt-cache-idle";
|
|
21
24
|
import { RenderErrorBoundary } from "@/components/shared/markdown-error-boundary";
|
|
22
25
|
|
|
23
26
|
import {
|
|
@@ -50,6 +53,8 @@ interface MessageListProps {
|
|
|
50
53
|
connectingElapsed?: number;
|
|
51
54
|
statusMessage?: string | null;
|
|
52
55
|
compactStatus?: "compacting" | null;
|
|
56
|
+
/** Prompt-cache clock for the idle re-cache notice; null when PPM cannot measure it. */
|
|
57
|
+
promptCache?: PromptCacheState | null;
|
|
53
58
|
projectName?: string;
|
|
54
59
|
/** Called when user clicks Fork/Rewind — opens new forked chat tab */
|
|
55
60
|
onFork?: (userMessage: string, messageId?: string) => void;
|
|
@@ -127,6 +132,7 @@ export function MessageList({
|
|
|
127
132
|
connectingElapsed,
|
|
128
133
|
statusMessage,
|
|
129
134
|
compactStatus,
|
|
135
|
+
promptCache,
|
|
130
136
|
projectName,
|
|
131
137
|
onFork,
|
|
132
138
|
onEdit,
|
|
@@ -454,6 +460,10 @@ export function MessageList({
|
|
|
454
460
|
data-msg-index={globalIdx}
|
|
455
461
|
className="px-4 pt-4 select-none"
|
|
456
462
|
>
|
|
463
|
+
{/* Above the summary rather than beside it: the rule is what marks
|
|
464
|
+
where the conversation was cut, and the summary is the first
|
|
465
|
+
message on the new side of it. */}
|
|
466
|
+
{msg.compaction && <CompactionDivider compaction={msg.compaction} />}
|
|
457
467
|
<RenderErrorBoundary fallbackContent={msg.content}>
|
|
458
468
|
<MessageBubble
|
|
459
469
|
message={msg}
|
|
@@ -479,6 +489,11 @@ export function MessageList({
|
|
|
479
489
|
</div>
|
|
480
490
|
);
|
|
481
491
|
})}
|
|
492
|
+
{/* Idle only: once a turn starts the cache question is already answered, and the
|
|
493
|
+
thinking indicator below owns that space. */}
|
|
494
|
+
{!isStreaming && !pendingApproval && (
|
|
495
|
+
<IdleCacheNotice promptCache={promptCache ?? null} />
|
|
496
|
+
)}
|
|
482
497
|
{hasTrailing && (
|
|
483
498
|
<div className="px-4 pt-4 pb-4 space-y-4 select-none">
|
|
484
499
|
{pendingApproval && (
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Clock } from "@/lib/icons";
|
|
2
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
|
3
|
+
import { useMinuteClock } from "@/hooks/use-minute-clock";
|
|
4
|
+
import type { PromptCacheState } from "../../../shared/prompt-cache-idle";
|
|
5
|
+
import {
|
|
6
|
+
promptCacheStatus,
|
|
7
|
+
formatCacheCountdown,
|
|
8
|
+
formatIdleDuration,
|
|
9
|
+
formatContextTokens,
|
|
10
|
+
} from "../../../shared/prompt-cache-idle";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* How long this session's prompt cache has left, in the composer's chip row.
|
|
14
|
+
*
|
|
15
|
+
* The banner above the composer only appears once the cache is already gone, which answers
|
|
16
|
+
* "why was that turn expensive" after the fact. This is the same fact while it can still be
|
|
17
|
+
* acted on — a countdown says the next message is cheap *now*, and going red says it is not.
|
|
18
|
+
*
|
|
19
|
+
* Reads as a chip rather than a control because there is nothing to click: the cache's clock
|
|
20
|
+
* is not a setting. Renders nothing at all when PPM has not measured the session, so a chat
|
|
21
|
+
* with no completed turn shows a row unchanged from before.
|
|
22
|
+
*
|
|
23
|
+
* The hover text is the only part that is hover-only, and deliberately so: everything it
|
|
24
|
+
* says is already on screen as the chip's own number and, once expired, as the banner. So
|
|
25
|
+
* touch loses a sentence of phrasing rather than a fact — which is why this needs no tap
|
|
26
|
+
* affordance and stays out of the composer's tab order.
|
|
27
|
+
*/
|
|
28
|
+
export function PromptCacheChip({ promptCache }: { promptCache: PromptCacheState | null }) {
|
|
29
|
+
const status = promptCacheStatus(promptCache, useMinuteClock());
|
|
30
|
+
if (status.kind === "unknown") return null;
|
|
31
|
+
|
|
32
|
+
const cold = status.kind === "cold";
|
|
33
|
+
const label = status.kind === "cold"
|
|
34
|
+
? formatIdleDuration(status.idleMs)
|
|
35
|
+
: formatCacheCountdown(status.remainingMs);
|
|
36
|
+
|
|
37
|
+
let detail: string;
|
|
38
|
+
if (status.kind !== "cold") {
|
|
39
|
+
detail = `Prompt cache warm, about ${label.replace(/m$/, " min")} left.`;
|
|
40
|
+
} else if (status.reason === "compacted") {
|
|
41
|
+
// No token figure here on purpose: what the next message re-caches is the summary the
|
|
42
|
+
// compaction just produced, and no API call has reported its size yet.
|
|
43
|
+
detail = `Prompt cache does not cover the compacted conversation. Compacted ${label} ago, so your next message will re-cache it.`;
|
|
44
|
+
} else {
|
|
45
|
+
detail = `Prompt cache expired ${label} ago. Your next message re-sends ${
|
|
46
|
+
status.contextTokens != null
|
|
47
|
+
? `about ${formatContextTokens(status.contextTokens)} tokens`
|
|
48
|
+
: "the whole transcript"
|
|
49
|
+
} at full price.`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<Tooltip>
|
|
54
|
+
<TooltipTrigger asChild>
|
|
55
|
+
<span
|
|
56
|
+
// Same shape as `ModeChip` and `PriorityToggle` beside it; only the colour carries
|
|
57
|
+
// the state, and only once the cache is gone — a countdown still running is not news.
|
|
58
|
+
className={`inline-flex items-center gap-1.5 px-[9px] py-1 rounded-full text-[11.5px] border transition-colors ${
|
|
59
|
+
cold
|
|
60
|
+
? "text-error border-error/40 bg-error/10"
|
|
61
|
+
: "text-text-2 bg-panel-2 border-border-soft"
|
|
62
|
+
}`}
|
|
63
|
+
>
|
|
64
|
+
<Clock className="size-3" />
|
|
65
|
+
{/* `tabular-nums` so a minute ticking over does not shift the chips beside it. */}
|
|
66
|
+
<span className="tabular-nums">{label}</span>
|
|
67
|
+
</span>
|
|
68
|
+
</TooltipTrigger>
|
|
69
|
+
<TooltipContent side="top" className="max-w-[240px] text-xs">
|
|
70
|
+
{detail}
|
|
71
|
+
</TooltipContent>
|
|
72
|
+
</Tooltip>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
@@ -860,6 +860,7 @@ export const CodeEditor = memo(function CodeEditor({ metadata, tabId }: CodeEdit
|
|
|
860
860
|
onToggle={setLspEnabled}
|
|
861
861
|
status={lsp.status}
|
|
862
862
|
diagnostics={lsp.diagnostics}
|
|
863
|
+
onInstall={lsp.install}
|
|
863
864
|
/>
|
|
864
865
|
)}
|
|
865
866
|
<EditorLanguagePicker value={effectiveLanguage} onChange={handleLanguageChange} />
|
|
@@ -23,6 +23,14 @@ import { useTabStore } from "@/stores/tab-store";
|
|
|
23
23
|
export interface EditorLspState {
|
|
24
24
|
status: LspDocumentStatus | null;
|
|
25
25
|
diagnostics: LspDiagnostic[];
|
|
26
|
+
/**
|
|
27
|
+
* Install the server this file has none of.
|
|
28
|
+
*
|
|
29
|
+
* Handed up rather than called from the toolbar directly: the indicator lives on the
|
|
30
|
+
* editor's static path, and one runtime import of the LSP client there would merge this
|
|
31
|
+
* whole chunk back into the editor's — see `editor-lsp-lazy-boundary.test.ts`.
|
|
32
|
+
*/
|
|
33
|
+
install?: (serverId: string) => Promise<void>;
|
|
26
34
|
}
|
|
27
35
|
|
|
28
36
|
const NO_LSP_STATE: EditorLspState = { status: null, diagnostics: [] };
|
|
@@ -39,7 +47,7 @@ interface EditorLanguageServiceProps {
|
|
|
39
47
|
export function EditorLanguageService({
|
|
40
48
|
editor, monaco, projectName, filePath, onState,
|
|
41
49
|
}: EditorLanguageServiceProps) {
|
|
42
|
-
const { status, diagnostics } = useLsp({ editor, monaco, projectName, filePath, enabled: true });
|
|
50
|
+
const { status, diagnostics, install } = useLsp({ editor, monaco, projectName, filePath, enabled: true });
|
|
43
51
|
|
|
44
52
|
// F12. Monaco's own binding would swap another file's model into this
|
|
45
53
|
// editor, leaving the tab titled and dirty-tracked as the old file. Disposed
|
|
@@ -64,8 +72,8 @@ export function EditorLanguageService({
|
|
|
64
72
|
onStateRef.current = onState;
|
|
65
73
|
|
|
66
74
|
useEffect(() => {
|
|
67
|
-
onStateRef.current({ status, diagnostics });
|
|
68
|
-
}, [status, diagnostics]);
|
|
75
|
+
onStateRef.current({ status, diagnostics, install });
|
|
76
|
+
}, [status, diagnostics, install]);
|
|
69
77
|
|
|
70
78
|
// The editor keeps drawing whatever it was last told, so a language service
|
|
71
79
|
// that is going away has to retract its own status.
|