@hienlh/ppm 0.23.11 → 0.23.12
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 +18 -0
- package/CLAUDE.md +13 -2
- 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 +37 -1
- package/bun.lock +34 -0
- package/dist/web/assets/accounts-settings-section-CGe5ikvs.js +1 -0
- package/dist/web/assets/accounts-settings-section-CGe5ikvs.js.br +0 -0
- package/dist/web/assets/accounts-settings-section-CGe5ikvs.js.gz +0 -0
- package/dist/web/assets/{agent-session-sheet-CBMsnl_p.js → agent-session-sheet-vBhfHYrC.js} +2 -2
- package/dist/web/assets/agent-session-sheet-vBhfHYrC.js.br +0 -0
- package/dist/web/assets/agent-session-sheet-vBhfHYrC.js.gz +0 -0
- package/dist/web/assets/{agent-session-window-content-D9C9FA7E.js → agent-session-window-content-BxIxDN5i.js} +1 -1
- package/dist/web/assets/agent-session-window-content-BxIxDN5i.js.br +0 -0
- package/dist/web/assets/agent-session-window-content-BxIxDN5i.js.gz +0 -0
- package/dist/web/assets/{ai-resource-editor-DhUVgDEG.js → ai-resource-editor-Y8clBPRv.js} +1 -1
- package/dist/web/assets/ai-resource-editor-Y8clBPRv.js.br +0 -0
- package/dist/web/assets/ai-resource-editor-Y8clBPRv.js.gz +0 -0
- package/dist/web/assets/{ai-settings-section-DOckWvp4.js → ai-settings-section-BB8vscte.js} +1 -1
- package/dist/web/assets/{ai-settings-section-CETpSpYd.js → ai-settings-section-Ck8uN_Bw.js} +1 -1
- package/dist/web/assets/ai-settings-section-Ck8uN_Bw.js.br +0 -0
- package/dist/web/assets/ai-settings-section-Ck8uN_Bw.js.gz +0 -0
- package/dist/web/assets/android-tab-BIOUVVoW.js +2 -0
- package/dist/web/assets/android-tab-BIOUVVoW.js.br +0 -0
- package/dist/web/assets/android-tab-BIOUVVoW.js.gz +0 -0
- package/dist/web/assets/{api-settings-JIgKfcCx.js → api-settings-D1axn9vm.js} +1 -1
- package/dist/web/assets/{appearance-settings-section-BJUiLUb7.js → appearance-settings-section-Bv5_n9lH.js} +1 -1
- package/dist/web/assets/appearance-settings-section-Bv5_n9lH.js.br +0 -0
- package/dist/web/assets/appearance-settings-section-Bv5_n9lH.js.gz +0 -0
- package/dist/web/assets/{apps-panel-1VElRgV3.js → apps-panel-DXHF0QEv.js} +1 -1
- package/dist/web/assets/apps-panel-DXHF0QEv.js.br +0 -0
- package/dist/web/assets/apps-panel-DXHF0QEv.js.gz +0 -0
- package/dist/web/assets/{audio-preview-DYkyHu5X.js → audio-preview-DpjOKEm4.js} +1 -1
- package/dist/web/assets/audio-preview-DpjOKEm4.js.br +0 -0
- package/dist/web/assets/audio-preview-DpjOKEm4.js.gz +0 -0
- package/dist/web/assets/branch-review-tab-4dgMNadQ.js +1 -0
- package/dist/web/assets/branch-review-tab-4dgMNadQ.js.br +0 -0
- package/dist/web/assets/branch-review-tab-4dgMNadQ.js.gz +0 -0
- package/dist/web/assets/chat-tab-Bbe_77oJ.js +15 -0
- package/dist/web/assets/chat-tab-Bbe_77oJ.js.br +0 -0
- package/dist/web/assets/chat-tab-Bbe_77oJ.js.gz +0 -0
- package/dist/web/assets/chat-tab-D3i5O3dO.js +1 -0
- package/dist/web/assets/chat-tab-D3i5O3dO.js.br +0 -0
- package/dist/web/assets/chat-tab-D3i5O3dO.js.gz +0 -0
- package/dist/web/assets/code-editor-DXsIWoQ1.js +7 -0
- package/dist/web/assets/code-editor-DXsIWoQ1.js.br +0 -0
- package/dist/web/assets/code-editor-DXsIWoQ1.js.gz +0 -0
- package/dist/web/assets/{codex-reset-credit-button-Fr45FUxi.js → codex-reset-credit-button-DRhievFQ.js} +1 -1
- package/dist/web/assets/codex-reset-credit-button-DRhievFQ.js.br +0 -0
- package/dist/web/assets/codex-reset-credit-button-DRhievFQ.js.gz +0 -0
- package/dist/web/assets/{conflict-editor-B-wdjSXI.js → conflict-editor-D_RImo_V.js} +3 -3
- package/dist/web/assets/conflict-editor-D_RImo_V.js.br +0 -0
- package/dist/web/assets/conflict-editor-D_RImo_V.js.gz +0 -0
- package/dist/web/assets/{csv-preview-B6RodObB.js → csv-preview-BuFdfLo3.js} +1 -1
- package/dist/web/assets/csv-preview-BuFdfLo3.js.br +0 -0
- package/dist/web/assets/csv-preview-BuFdfLo3.js.gz +0 -0
- package/dist/web/assets/{database-viewer-CdPBUQPY.js → database-viewer-ChcbYn9E.js} +1 -1
- package/dist/web/assets/database-viewer-ChcbYn9E.js.br +0 -0
- package/dist/web/assets/database-viewer-ChcbYn9E.js.gz +0 -0
- package/dist/web/assets/{design-settings-section-BpCpaBwL.js → design-settings-section-B_xOf51h.js} +1 -1
- package/dist/web/assets/design-settings-section-B_xOf51h.js.br +0 -0
- package/dist/web/assets/design-settings-section-B_xOf51h.js.gz +0 -0
- package/dist/web/assets/{design-skill-suggestion-DkT2E2IV.js → design-skill-suggestion-BbEDg15Z.js} +1 -1
- package/dist/web/assets/design-skill-suggestion-BbEDg15Z.js.br +0 -0
- package/dist/web/assets/design-skill-suggestion-BbEDg15Z.js.gz +0 -0
- package/dist/web/assets/{design-tab-BZb9eemI.js → design-tab-BQSYJ4cS.js} +6 -6
- package/dist/web/assets/design-tab-BQSYJ4cS.js.br +0 -0
- package/dist/web/assets/design-tab-BQSYJ4cS.js.gz +0 -0
- package/dist/web/assets/{designs-sidebar-panel-CF4tp6j-.js → designs-sidebar-panel-AiPaYfSU.js} +1 -1
- package/dist/web/assets/designs-sidebar-panel-AiPaYfSU.js.br +0 -0
- package/dist/web/assets/designs-sidebar-panel-AiPaYfSU.js.gz +0 -0
- package/dist/web/assets/{diff-viewer-BqEqwSw6.js → diff-viewer-BZ6glGK-.js} +1 -1
- package/dist/web/assets/diff-viewer-BZ6glGK-.js.br +0 -0
- package/dist/web/assets/diff-viewer-BZ6glGK-.js.gz +0 -0
- package/dist/web/assets/{edit-diff-preview-DD4HayXY.js → edit-diff-preview-D-FNLOU2.js} +1 -1
- package/dist/web/assets/edit-diff-preview-D-FNLOU2.js.br +0 -0
- package/dist/web/assets/edit-diff-preview-D-FNLOU2.js.gz +0 -0
- package/dist/web/assets/{editor-language-service-CkA5sEdV.js → editor-language-service-4sbsdqBV.js} +1 -1
- package/dist/web/assets/editor-language-service-4sbsdqBV.js.br +0 -0
- package/dist/web/assets/editor-language-service-4sbsdqBV.js.gz +0 -0
- package/dist/web/assets/explorer-body-DbgrG1fe.js +2 -0
- package/dist/web/assets/explorer-body-DbgrG1fe.js.br +0 -0
- package/dist/web/assets/explorer-body-DbgrG1fe.js.gz +0 -0
- package/dist/web/assets/{explorer-window-content-CRJ2eMZ4.js → explorer-window-content-BCjWvHpp.js} +1 -1
- package/dist/web/assets/explorer-window-content-BCjWvHpp.js.br +0 -0
- package/dist/web/assets/explorer-window-content-BCjWvHpp.js.gz +0 -0
- package/dist/web/assets/{extension-manager-section-DwQTdCII.js → extension-manager-section-DiMF4RnT.js} +1 -1
- package/dist/web/assets/extension-manager-section-DiMF4RnT.js.br +0 -0
- package/dist/web/assets/extension-manager-section-DiMF4RnT.js.gz +0 -0
- package/dist/web/assets/{extension-webview-CMq-VTLu.js → extension-webview-Coti6Vfw.js} +1 -1
- package/dist/web/assets/extension-webview-Coti6Vfw.js.br +0 -0
- package/dist/web/assets/extension-webview-Coti6Vfw.js.gz +0 -0
- package/dist/web/assets/file-store-Cm7-pHux.js +1 -0
- package/dist/web/assets/file-store-Cm7-pHux.js.br +0 -0
- package/dist/web/assets/file-store-Cm7-pHux.js.gz +0 -0
- package/dist/web/assets/{files-settings-section-B2lcyh-6.js → files-settings-section-ZTVwOwx0.js} +1 -1
- package/dist/web/assets/files-settings-section-ZTVwOwx0.js.br +0 -0
- package/dist/web/assets/files-settings-section-ZTVwOwx0.js.gz +0 -0
- package/dist/web/assets/{general-settings-section-Doepm2sH.js → general-settings-section-B7Hjx_fb.js} +1 -1
- package/dist/web/assets/general-settings-section-B7Hjx_fb.js.br +0 -0
- package/dist/web/assets/general-settings-section-B7Hjx_fb.js.gz +0 -0
- package/dist/web/assets/{git-log-panel-CJakNMDc.js → git-log-panel-CbcJ_YEH.js} +1 -1
- package/dist/web/assets/git-log-panel-CbcJ_YEH.js.br +0 -0
- package/dist/web/assets/git-log-panel-CbcJ_YEH.js.gz +0 -0
- package/dist/web/assets/{glide-data-grid-C_SeOhSq.js → glide-data-grid-BfByGSf1.js} +3 -3
- package/dist/web/assets/glide-data-grid-BfByGSf1.js.br +0 -0
- package/dist/web/assets/glide-data-grid-BfByGSf1.js.gz +0 -0
- package/dist/web/assets/group-chat-tab-DCo9OP3D.js +1 -0
- package/dist/web/assets/group-chat-tab-DCo9OP3D.js.br +0 -0
- package/dist/web/assets/group-chat-tab-DCo9OP3D.js.gz +0 -0
- package/dist/web/assets/{image-preview-C1Frlx22.js → image-preview-Cjlps7Pt.js} +1 -1
- package/dist/web/assets/index-CyDLBddf.js +52 -0
- package/dist/web/assets/index-CyDLBddf.js.br +0 -0
- package/dist/web/assets/index-CyDLBddf.js.gz +0 -0
- package/dist/web/assets/index-Dh5apC3I.css +1 -0
- package/dist/web/assets/index-Dh5apC3I.css.br +0 -0
- package/dist/web/assets/index-Dh5apC3I.css.gz +0 -0
- package/dist/web/assets/{jira-watcher-section-BmkIGQFV.js → jira-watcher-section-Dz_-sUC2.js} +1 -1
- package/dist/web/assets/keybindings-store-BTq5Z7XP.js +1 -0
- package/dist/web/assets/{keyboard-shortcuts-section-BgZe3QDr.js → keyboard-shortcuts-section-Ba5NYwlG.js} +1 -1
- package/dist/web/assets/keyboard-shortcuts-section-Ba5NYwlG.js.br +0 -0
- package/dist/web/assets/keyboard-shortcuts-section-Ba5NYwlG.js.gz +0 -0
- package/dist/web/assets/{language-servers-section-CCMzgOaE.js → language-servers-section-DJJ7SFXo.js} +2 -2
- package/dist/web/assets/language-servers-section-DJJ7SFXo.js.br +0 -0
- package/dist/web/assets/language-servers-section-DJJ7SFXo.js.gz +0 -0
- package/dist/web/assets/{lsp-client-B10suuaZ.js → lsp-client-Dr3vQ1bb.js} +1 -1
- package/dist/web/assets/lsp-client-Dr3vQ1bb.js.br +0 -0
- package/dist/web/assets/lsp-client-Dr3vQ1bb.js.gz +0 -0
- package/dist/web/assets/{markdown-renderer-AHHFS3jc.js → markdown-renderer-CmnqFfTU.js} +3 -3
- package/dist/web/assets/markdown-renderer-CmnqFfTU.js.br +0 -0
- package/dist/web/assets/markdown-renderer-CmnqFfTU.js.gz +0 -0
- package/dist/web/assets/markdown-renderer-LJdVMbGl.js +1 -0
- package/dist/web/assets/{mobile-explorer-sheet-CqCsLWSr.js → mobile-explorer-sheet-BiIhZtJ2.js} +1 -1
- package/dist/web/assets/mobile-explorer-sheet-BiIhZtJ2.js.br +0 -0
- package/dist/web/assets/mobile-explorer-sheet-BiIhZtJ2.js.gz +0 -0
- package/dist/web/assets/new-design-dialog-DI_hxvFV.js +1 -0
- package/dist/web/assets/new-design-dialog-DI_hxvFV.js.br +0 -0
- package/dist/web/assets/new-design-dialog-DI_hxvFV.js.gz +0 -0
- package/dist/web/assets/notification-store-9lBSplOV.js +1 -0
- package/dist/web/assets/{notifications-settings-section-CXgzH_bK.js → notifications-settings-section-0s-2OKRv.js} +1 -1
- package/dist/web/assets/notifications-settings-section-0s-2OKRv.js.br +0 -0
- package/dist/web/assets/notifications-settings-section-0s-2OKRv.js.gz +0 -0
- package/dist/web/assets/{overview-panel-BYB8mgRE.js → overview-panel-3htxfZS2.js} +1 -1
- package/dist/web/assets/overview-panel-3htxfZS2.js.br +0 -0
- package/dist/web/assets/overview-panel-3htxfZS2.js.gz +0 -0
- package/dist/web/assets/panel-store-B6PoCwBA.js +1 -0
- package/dist/web/assets/panel-store-B6PoCwBA.js.br +0 -0
- package/dist/web/assets/panel-store-B6PoCwBA.js.gz +0 -0
- package/dist/web/assets/{performance-panel-Dpuq3g0W.js → performance-panel-V8gpnnf7.js} +2 -2
- package/dist/web/assets/performance-panel-V8gpnnf7.js.br +0 -0
- package/dist/web/assets/performance-panel-V8gpnnf7.js.gz +0 -0
- package/dist/web/assets/{postgres-viewer-DW0Gkmow.js → postgres-viewer-sWS-ogTC.js} +1 -1
- package/dist/web/assets/postgres-viewer-sWS-ogTC.js.br +0 -0
- package/dist/web/assets/postgres-viewer-sWS-ogTC.js.gz +0 -0
- package/dist/web/assets/{ppmbot-settings-section-DFtlGoW6.js → ppmbot-settings-section-CT8vvlzk.js} +1 -1
- package/dist/web/assets/ppmbot-settings-section-CT8vvlzk.js.br +0 -0
- package/dist/web/assets/ppmbot-settings-section-CT8vvlzk.js.gz +0 -0
- package/dist/web/assets/{pptx-export-CNyG32Xr.js → pptx-export-Ugjv0hso.js} +4 -4
- package/dist/web/assets/pptx-export-Ugjv0hso.js.br +0 -0
- package/dist/web/assets/pptx-export-Ugjv0hso.js.gz +0 -0
- package/dist/web/assets/{problems-panel-V5zqpuXq.js → problems-panel-Gcy79pSS.js} +1 -1
- package/dist/web/assets/problems-panel-Gcy79pSS.js.br +0 -0
- package/dist/web/assets/problems-panel-Gcy79pSS.js.gz +0 -0
- package/dist/web/assets/{process-row-format-CiJJSf_V.js → process-row-format-u6y7lOee.js} +1 -1
- package/dist/web/assets/process-table-BUTIp9Oy.js +1 -0
- package/dist/web/assets/process-table-BUTIp9Oy.js.br +0 -0
- package/dist/web/assets/process-table-BUTIp9Oy.js.gz +0 -0
- package/dist/web/assets/{proxy-settings-section-B7AVlTfY.js → proxy-settings-section-Buv_8y54.js} +1 -1
- package/dist/web/assets/proxy-settings-section-Buv_8y54.js.br +0 -0
- package/dist/web/assets/proxy-settings-section-Buv_8y54.js.gz +0 -0
- package/dist/web/assets/{query-audit-section-gHmRfWKr.js → query-audit-section-N2DQtgJx.js} +1 -1
- package/dist/web/assets/query-audit-section-N2DQtgJx.js.br +0 -0
- package/dist/web/assets/query-audit-section-N2DQtgJx.js.gz +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-CRvJqmaz.js +1 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-CRvJqmaz.js.br +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-CRvJqmaz.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-BoYINLbJ.js +2 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-BoYINLbJ.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-BoYINLbJ.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-DPdP0yYu.js +1 -0
- package/dist/web/assets/remote-desktop-mobile-view-DPdP0yYu.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-DPdP0yYu.js.gz +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-BeQ_Jrp7.js +1 -0
- package/dist/web/assets/remote-desktop-readiness-gate-BeQ_Jrp7.js.br +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-BeQ_Jrp7.js.gz +0 -0
- package/dist/web/assets/remote-desktop-settings-section-Bs4sHS3l.js +1 -0
- package/dist/web/assets/remote-desktop-settings-section-Bs4sHS3l.js.br +0 -0
- package/dist/web/assets/remote-desktop-settings-section-Bs4sHS3l.js.gz +0 -0
- package/dist/web/assets/remote-desktop-window-content-DDr__JxQ.js +1 -0
- package/dist/web/assets/remote-desktop-window-content-DDr__JxQ.js.br +0 -0
- package/dist/web/assets/remote-desktop-window-content-DDr__JxQ.js.gz +0 -0
- package/dist/web/assets/{run-in-terminal-DKBcEGVu.js → run-in-terminal-DCBNtYHQ.js} +1 -1
- package/dist/web/assets/{schedules-settings-section-sYDAsBMO.js → schedules-settings-section-_cHX2qOa.js} +1 -1
- package/dist/web/assets/schedules-settings-section-_cHX2qOa.js.br +0 -0
- package/dist/web/assets/schedules-settings-section-_cHX2qOa.js.gz +0 -0
- package/dist/web/assets/{send-to-chat-CCdOrKc7.js → send-to-chat-dNqNV7Y4.js} +1 -1
- package/dist/web/assets/send-to-chat-dNqNV7Y4.js.br +0 -0
- package/dist/web/assets/send-to-chat-dNqNV7Y4.js.gz +0 -0
- package/dist/web/assets/{services-panel-CKa2aP1d.js → services-panel-Dm54cnW3.js} +1 -1
- package/dist/web/assets/services-panel-Dm54cnW3.js.br +0 -0
- package/dist/web/assets/services-panel-Dm54cnW3.js.gz +0 -0
- package/dist/web/assets/settings-body-DRRQNaDA.js +1 -0
- package/dist/web/assets/settings-body-DRRQNaDA.js.br +0 -0
- package/dist/web/assets/settings-body-DRRQNaDA.js.gz +0 -0
- package/dist/web/assets/settings-section-content-DRaHfvm8.js +1 -0
- package/dist/web/assets/settings-section-content-U3mIx6hF.js +2 -0
- package/dist/web/assets/settings-section-content-U3mIx6hF.js.br +0 -0
- package/dist/web/assets/settings-section-content-U3mIx6hF.js.gz +0 -0
- package/dist/web/assets/{settings-store-DfuiLq_9.js → settings-store-Cyuo8ceh.js} +2 -2
- package/dist/web/assets/settings-store-Cyuo8ceh.js.br +0 -0
- package/dist/web/assets/settings-store-Cyuo8ceh.js.gz +0 -0
- package/dist/web/assets/settings-tab-CB_BhHTK.js +1 -0
- package/dist/web/assets/settings-window-content-CgZIMNX8.js +1 -0
- package/dist/web/assets/{slash-command-picker-CLevA_Gf.js → slash-command-picker-CQlIqMW0.js} +1 -1
- package/dist/web/assets/slash-command-picker-CQlIqMW0.js.br +0 -0
- package/dist/web/assets/slash-command-picker-CQlIqMW0.js.gz +0 -0
- package/dist/web/assets/{sql-query-editor-Db8b0jEr.js → sql-query-editor--Z4bcqd8.js} +1 -1
- package/dist/web/assets/sql-query-editor--Z4bcqd8.js.br +0 -0
- package/dist/web/assets/sql-query-editor--Z4bcqd8.js.gz +0 -0
- package/dist/web/assets/{sqlite-viewer-VzYLMqkD.js → sqlite-viewer-CSmX3qaj.js} +1 -1
- package/dist/web/assets/sqlite-viewer-CSmX3qaj.js.br +0 -0
- package/dist/web/assets/sqlite-viewer-CSmX3qaj.js.gz +0 -0
- package/dist/web/assets/{system-monitor-body-BR60W_mG.js → system-monitor-body-LannpU6H.js} +2 -2
- package/dist/web/assets/system-monitor-body-LannpU6H.js.br +0 -0
- package/dist/web/assets/system-monitor-body-LannpU6H.js.gz +0 -0
- package/dist/web/assets/system-monitor-tab-BfVucwEF.js +1 -0
- package/dist/web/assets/{system-monitor-window-content-BLw1QBXo.js → system-monitor-window-content-kLNW9Ln3.js} +1 -1
- package/dist/web/assets/{tab-host-window-content-BL61SB5m.js → tab-host-window-content-II_FtOYM.js} +1 -1
- package/dist/web/assets/tab-host-window-content-II_FtOYM.js.br +0 -0
- package/dist/web/assets/tab-host-window-content-II_FtOYM.js.gz +0 -0
- package/dist/web/assets/{tab-store-CbPh8CAX.js → tab-store-DCpc0g0Q.js} +1 -1
- package/dist/web/assets/{terminal-tab-B4y6at4h.js → terminal-tab-CTe2polt.js} +1 -1
- package/dist/web/assets/terminal-tab-CTe2polt.js.br +0 -0
- package/dist/web/assets/terminal-tab-CTe2polt.js.gz +0 -0
- package/dist/web/assets/{tool-cards-K0r_yxI0.js → tool-cards-rxLXbBSm.js} +5 -5
- package/dist/web/assets/tool-cards-rxLXbBSm.js.br +0 -0
- package/dist/web/assets/tool-cards-rxLXbBSm.js.gz +0 -0
- package/dist/web/assets/use-h264-canvas-decoder-BfO9QrlH.js +1 -0
- package/dist/web/assets/use-h264-canvas-decoder-BfO9QrlH.js.br +0 -0
- package/dist/web/assets/use-h264-canvas-decoder-BfO9QrlH.js.gz +0 -0
- package/dist/web/assets/{use-inline-blame-BK23icsE.js → use-inline-blame-CxZ_QWzS.js} +3 -3
- package/dist/web/assets/use-inline-blame-CxZ_QWzS.js.br +0 -0
- package/dist/web/assets/use-inline-blame-CxZ_QWzS.js.gz +0 -0
- package/dist/web/assets/{use-lsp-CRdCPCKW.js → use-lsp-gCNE5A9K.js} +1 -1
- package/dist/web/assets/use-lsp-gCNE5A9K.js.br +0 -0
- package/dist/web/assets/use-lsp-gCNE5A9K.js.gz +0 -0
- package/dist/web/assets/{use-monaco-theme-CpXT2uh3.js → use-monaco-theme-DvNGcCvz.js} +1 -1
- package/dist/web/assets/{use-process-kill-BWYX03KF.js → use-process-kill-Cbiu1mbY.js} +1 -1
- package/dist/web/assets/use-process-kill-Cbiu1mbY.js.br +0 -0
- package/dist/web/assets/use-process-kill-Cbiu1mbY.js.gz +0 -0
- package/dist/web/assets/{use-websocket-CiWQKhHr.js → use-websocket-AC7EG1LK.js} +1 -1
- package/dist/web/assets/video-preview-C2Y61WUE.js +1 -0
- package/dist/web/assets/video-preview-C2Y61WUE.js.br +0 -0
- package/dist/web/assets/video-preview-C2Y61WUE.js.gz +0 -0
- package/dist/web/assets/{voice-settings-section-Ceihggqf.js → voice-settings-section-DCXZeLYI.js} +1 -1
- package/dist/web/assets/voice-settings-section-DCXZeLYI.js.br +0 -0
- package/dist/web/assets/voice-settings-section-DCXZeLYI.js.gz +0 -0
- package/dist/web/assets/{window-pip-registry-mDgwpAwP.js → window-pip-registry-9Y9LQQYS.js} +1 -1
- package/dist/web/index.html +50 -7
- 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/architecture/android-emulator-phase0-report-260921.md +310 -0
- package/docs/architecture/android-emulator-phase2-report-260921.md +163 -0
- package/docs/architecture/android-emulator-phase3-report-260921.md +203 -0
- package/docs/architecture/android-emulator-phase4-report-260921.md +191 -0
- package/docs/architecture/android-emulator-plan-260920.md +376 -0
- package/docs/architecture/plugins-and-tracing.md +48 -7
- package/package.json +4 -2
- package/scripts/gen-android-proto.ts +37 -0
- package/scripts/release.sh +3 -1
- package/src/cli/commands/chat-cmd.ts +2 -2
- package/src/providers/claude-agent-sdk-query-options.ts +28 -0
- package/src/providers/claude-agent-sdk.ts +153 -71
- package/src/providers/claude-warm-spare.ts +176 -0
- package/src/providers/provider.interface.ts +1 -0
- package/src/server/index.ts +53 -0
- package/src/server/middleware/gzip-json.ts +13 -1
- package/src/server/routes/android.ts +616 -0
- package/src/server/routes/chat.ts +31 -0
- package/src/server/routes/files.ts +52 -5
- package/src/server/routes/remote-desktop.ts +95 -2
- package/src/server/routes/trace.ts +66 -0
- package/src/server/ws/android.ts +101 -0
- package/src/server/ws/chat.ts +12 -17
- package/src/server/ws/global.ts +13 -1
- package/src/server/ws/remote-desktop.ts +6 -1
- package/src/services/android/android-apk.ts +387 -0
- package/src/services/android/android-capabilities.ts +154 -0
- package/src/services/android/android-flag.ts +12 -0
- package/src/services/android/android-grpc.ts +124 -0
- package/src/services/android/android-input.ts +129 -0
- package/src/services/android/android-logcat.ts +169 -0
- package/src/services/android/android-nonce.ts +50 -0
- package/src/services/android/android-operations.ts +124 -0
- package/src/services/android/android-screenshot.ts +53 -0
- package/src/services/android/android-session.ts +510 -0
- package/src/services/android/android-video.ts +495 -0
- package/src/services/android/avd-list.ts +131 -0
- package/src/services/android/avd-manager.ts +397 -0
- package/src/services/android/device-registry.ts +223 -0
- package/src/services/android/emulator-discovery.ts +160 -0
- package/src/services/android/emulator-launcher.ts +290 -0
- package/src/services/android/proto/emulator-controller-descriptor.ts +10 -0
- package/src/services/android/proto/emulator_controller.proto +1791 -0
- package/src/services/android/sdk-discovery.ts +178 -0
- package/src/services/android/system-images.ts +124 -0
- package/src/services/chat.service.ts +81 -4
- package/src/services/config.service.ts +1 -1
- package/src/services/file-filter.service.ts +2 -61
- package/src/services/file-glob.ts +67 -0
- package/src/services/file-index/file-index-runner.ts +169 -0
- package/src/services/file-index/file-index-worker.ts +73 -0
- package/src/services/file-index/index-search.ts +152 -0
- package/src/services/file-index/index-walk.ts +109 -0
- package/src/services/file-list-index.service.ts +189 -70
- package/src/services/file-watcher/linux-inotify.ts +238 -0
- package/src/services/file-watcher/watch-tree.ts +37 -6
- package/src/services/file-watcher.service.ts +40 -8
- package/src/services/file.service.ts +17 -6
- package/src/services/group-chat/group-chat.service.ts +1 -1
- package/src/services/jira-debug-session.service.ts +1 -1
- package/src/services/ppmbot/ppmbot-delegation.ts +1 -1
- package/src/services/ppmbot/ppmbot-service.ts +1 -1
- package/src/services/project-content-search.service.ts +45 -11
- package/src/services/proxy-agent-turn.ts +7 -3
- package/src/services/remote-desktop/mediamtx-catalog.ts +89 -0
- package/src/services/remote-desktop/mediamtx-config.ts +91 -0
- package/src/services/remote-desktop/mediamtx-install.service.ts +191 -0
- package/src/services/remote-desktop/mediamtx-paths.ts +51 -0
- package/src/services/remote-desktop/mediamtx-process.ts +152 -0
- package/src/services/remote-desktop/remote-desktop-capture-wayland.ts +312 -0
- package/src/services/remote-desktop/remote-desktop-capture.ts +60 -4
- package/src/services/remote-desktop/remote-desktop-portal.ts +529 -0
- package/src/services/remote-desktop/remote-desktop-requirements.ts +56 -20
- package/src/services/remote-desktop/remote-desktop-session.ts +77 -3
- package/src/services/remote-desktop/remote-desktop-whep-registry.ts +36 -0
- package/src/services/scheduler-runner.ts +2 -3
- package/src/services/session-trace/browser-trace-ingest.ts +131 -0
- package/src/services/session-trace/session-trace-cleanup.ts +65 -0
- package/src/services/session-trace/session-trace-db.ts +89 -0
- package/src/services/session-trace/session-trace-store.ts +132 -0
- package/src/services/session-trace/trace-coalescer.ts +86 -0
- package/src/services/session-trace/trace-recorder.ts +304 -0
- package/src/services/session-trace/trace-writer.ts +83 -0
- package/src/shared/android-avd.ts +53 -0
- package/src/shared/android-protocol.ts +184 -0
- package/src/shared/file-index-limits.ts +17 -0
- package/src/shared/session-trace.ts +61 -0
- package/src/types/chat.ts +17 -0
- package/src/types/config.ts +27 -0
- package/src/types/project.ts +9 -0
- package/src/web/app.tsx +5 -0
- package/src/web/components/android/android-apk-upload.ts +75 -0
- package/src/web/components/android/android-avd-create-dialog.tsx +305 -0
- package/src/web/components/android/android-avd-destroy-dialog.tsx +151 -0
- package/src/web/components/android/android-clipboard-panel.tsx +94 -0
- package/src/web/components/android/android-controls.tsx +128 -0
- package/src/web/components/android/android-coords.ts +99 -0
- package/src/web/components/android/android-device-list.tsx +329 -0
- package/src/web/components/android/android-install-panel.tsx +280 -0
- package/src/web/components/android/android-log-filter.ts +75 -0
- package/src/web/components/android/android-logcat-panel.tsx +214 -0
- package/src/web/components/android/android-screenshot-download.ts +56 -0
- package/src/web/components/android/android-tab.tsx +66 -0
- package/src/web/components/android/android-tools-drawer.tsx +76 -0
- package/src/web/components/android/android-viewer.tsx +200 -0
- package/src/web/components/android/android-ws-url.ts +21 -0
- package/src/web/components/android/open-android.ts +21 -0
- package/src/web/components/android/use-android-available.ts +29 -0
- package/src/web/components/android/use-android-keyboard.ts +111 -0
- package/src/web/components/android/use-android-session.ts +277 -0
- package/src/web/components/android/use-android-touch.ts +123 -0
- package/src/web/components/chat/chat-tab.tsx +28 -2
- package/src/web/components/chat/message-input.tsx +3 -5
- package/src/web/components/editor/compare-picker.tsx +12 -2
- package/src/web/components/explorer/file-tree.tsx +6 -7
- package/src/web/components/explorer/use-tree-row-dnd.ts +0 -2
- package/src/web/components/floating-window/window-content-registry.ts +8 -8
- package/src/web/components/layout/command-palette.tsx +31 -9
- package/src/web/components/layout/mobile-drawer.tsx +8 -1
- package/src/web/components/layout/nav-section-rail.tsx +8 -1
- package/src/web/components/layout/reparenting-tab.tsx +2 -2
- package/src/web/components/layout/tab-content.tsx +5 -0
- package/src/web/components/layout/tab-pool.tsx +31 -20
- package/src/web/components/remote-desktop/use-h264-canvas-decoder.ts +23 -1
- package/src/web/components/remote-desktop/use-remote-desktop-connection.ts +64 -6
- package/src/web/components/remote-desktop/use-webrtc-canvas-video.ts +255 -0
- package/src/web/components/root-error-boundary.tsx +5 -0
- package/src/web/components/settings/remote-desktop-settings-section.tsx +176 -0
- package/src/web/components/settings/settings-categories.ts +3 -0
- package/src/web/components/settings/settings-section-content.tsx +25 -18
- package/src/web/hooks/use-chat-prewarm.ts +53 -0
- package/src/web/hooks/use-chat.ts +18 -4
- package/src/web/hooks/use-file-index-invalidation.ts +7 -5
- package/src/web/hooks/use-global-events.ts +12 -1
- package/src/web/hooks/use-remote-file-search.ts +39 -0
- package/src/web/hooks/use-ui-preload.ts +38 -0
- package/src/web/index.html +43 -0
- package/src/web/lib/chunk-recovery.ts +5 -1
- package/src/web/lib/device-id.ts +39 -0
- package/src/web/lib/feature-badges.ts +2 -0
- package/src/web/lib/lazy-with-preload.tsx +43 -0
- package/src/web/lib/preload-ui.ts +60 -0
- package/src/web/lib/score-file-search.ts +27 -14
- package/src/web/lib/tab-type-icons.ts +2 -1
- package/src/web/lib/trace-boot.ts +8 -0
- package/src/web/lib/trace-client.ts +516 -0
- package/src/web/main.tsx +12 -0
- package/src/web/stores/file-store.ts +124 -18
- package/src/web/stores/panel-utils.ts +3 -0
- package/src/web/stores/tab-store.ts +2 -1
- package/src/web/stores/window-panel-persistence.ts +3 -0
- package/vite.config.ts +3 -0
- package/dist/web/assets/accounts-settings-section-DEIm-W-D.js +0 -1
- package/dist/web/assets/accounts-settings-section-DEIm-W-D.js.br +0 -0
- package/dist/web/assets/accounts-settings-section-DEIm-W-D.js.gz +0 -0
- package/dist/web/assets/agent-session-sheet-CBMsnl_p.js.br +0 -0
- package/dist/web/assets/agent-session-sheet-CBMsnl_p.js.gz +0 -0
- package/dist/web/assets/agent-session-window-content-D9C9FA7E.js.br +0 -0
- package/dist/web/assets/agent-session-window-content-D9C9FA7E.js.gz +0 -0
- package/dist/web/assets/ai-resource-editor-DhUVgDEG.js.br +0 -0
- package/dist/web/assets/ai-resource-editor-DhUVgDEG.js.gz +0 -0
- package/dist/web/assets/ai-settings-section-CETpSpYd.js.br +0 -0
- package/dist/web/assets/ai-settings-section-CETpSpYd.js.gz +0 -0
- package/dist/web/assets/appearance-settings-section-BJUiLUb7.js.br +0 -0
- package/dist/web/assets/appearance-settings-section-BJUiLUb7.js.gz +0 -0
- package/dist/web/assets/apps-panel-1VElRgV3.js.br +0 -0
- package/dist/web/assets/apps-panel-1VElRgV3.js.gz +0 -0
- package/dist/web/assets/audio-preview-DYkyHu5X.js.br +0 -0
- package/dist/web/assets/audio-preview-DYkyHu5X.js.gz +0 -0
- package/dist/web/assets/branch-review-tab-DhTMSpSU.js +0 -1
- package/dist/web/assets/branch-review-tab-DhTMSpSU.js.br +0 -0
- package/dist/web/assets/branch-review-tab-DhTMSpSU.js.gz +0 -0
- package/dist/web/assets/chat-tab-Cg3BKugo.js +0 -15
- package/dist/web/assets/chat-tab-Cg3BKugo.js.br +0 -0
- package/dist/web/assets/chat-tab-Cg3BKugo.js.gz +0 -0
- package/dist/web/assets/chat-tab-tbUDK__Y.js +0 -1
- package/dist/web/assets/chat-tab-tbUDK__Y.js.br +0 -0
- package/dist/web/assets/chat-tab-tbUDK__Y.js.gz +0 -0
- package/dist/web/assets/code-editor-6ZiQehbr.js +0 -7
- package/dist/web/assets/code-editor-6ZiQehbr.js.br +0 -0
- package/dist/web/assets/code-editor-6ZiQehbr.js.gz +0 -0
- package/dist/web/assets/codex-reset-credit-button-Fr45FUxi.js.br +0 -0
- package/dist/web/assets/codex-reset-credit-button-Fr45FUxi.js.gz +0 -0
- package/dist/web/assets/conflict-editor-B-wdjSXI.js.br +0 -0
- package/dist/web/assets/conflict-editor-B-wdjSXI.js.gz +0 -0
- package/dist/web/assets/csv-preview-B6RodObB.js.br +0 -0
- package/dist/web/assets/csv-preview-B6RodObB.js.gz +0 -0
- package/dist/web/assets/database-viewer-CdPBUQPY.js.br +0 -0
- package/dist/web/assets/database-viewer-CdPBUQPY.js.gz +0 -0
- package/dist/web/assets/design-settings-section-BpCpaBwL.js.br +0 -0
- package/dist/web/assets/design-settings-section-BpCpaBwL.js.gz +0 -0
- package/dist/web/assets/design-skill-suggestion-DkT2E2IV.js.br +0 -0
- package/dist/web/assets/design-skill-suggestion-DkT2E2IV.js.gz +0 -0
- package/dist/web/assets/design-tab-BZb9eemI.js.br +0 -0
- package/dist/web/assets/design-tab-BZb9eemI.js.gz +0 -0
- package/dist/web/assets/designs-sidebar-panel-CF4tp6j-.js.br +0 -0
- package/dist/web/assets/designs-sidebar-panel-CF4tp6j-.js.gz +0 -0
- package/dist/web/assets/diff-viewer-BqEqwSw6.js.br +0 -0
- package/dist/web/assets/diff-viewer-BqEqwSw6.js.gz +0 -0
- package/dist/web/assets/edit-diff-preview-DD4HayXY.js.br +0 -0
- package/dist/web/assets/edit-diff-preview-DD4HayXY.js.gz +0 -0
- package/dist/web/assets/editor-language-service-CkA5sEdV.js.br +0 -0
- package/dist/web/assets/editor-language-service-CkA5sEdV.js.gz +0 -0
- package/dist/web/assets/explorer-body-Ds7oKuz7.js +0 -2
- package/dist/web/assets/explorer-body-Ds7oKuz7.js.br +0 -0
- package/dist/web/assets/explorer-body-Ds7oKuz7.js.gz +0 -0
- package/dist/web/assets/explorer-window-content-CRJ2eMZ4.js.br +0 -0
- package/dist/web/assets/explorer-window-content-CRJ2eMZ4.js.gz +0 -0
- package/dist/web/assets/extension-manager-section-DwQTdCII.js.br +0 -0
- package/dist/web/assets/extension-manager-section-DwQTdCII.js.gz +0 -0
- package/dist/web/assets/extension-webview-CMq-VTLu.js.br +0 -0
- package/dist/web/assets/extension-webview-CMq-VTLu.js.gz +0 -0
- package/dist/web/assets/file-store-DY1_0nzY.js +0 -1
- package/dist/web/assets/file-store-DY1_0nzY.js.br +0 -0
- package/dist/web/assets/file-store-DY1_0nzY.js.gz +0 -0
- package/dist/web/assets/files-settings-section-B2lcyh-6.js.br +0 -0
- package/dist/web/assets/files-settings-section-B2lcyh-6.js.gz +0 -0
- package/dist/web/assets/general-settings-section-Doepm2sH.js.br +0 -0
- package/dist/web/assets/general-settings-section-Doepm2sH.js.gz +0 -0
- package/dist/web/assets/git-log-panel-CJakNMDc.js.br +0 -0
- package/dist/web/assets/git-log-panel-CJakNMDc.js.gz +0 -0
- package/dist/web/assets/glide-data-grid-C_SeOhSq.js.br +0 -0
- package/dist/web/assets/glide-data-grid-C_SeOhSq.js.gz +0 -0
- package/dist/web/assets/group-chat-tab--by1xCQW.js +0 -1
- package/dist/web/assets/group-chat-tab--by1xCQW.js.br +0 -0
- package/dist/web/assets/group-chat-tab--by1xCQW.js.gz +0 -0
- package/dist/web/assets/index-DhWjx5iR.js +0 -52
- package/dist/web/assets/index-DhWjx5iR.js.br +0 -0
- package/dist/web/assets/index-DhWjx5iR.js.gz +0 -0
- package/dist/web/assets/index-oIvYSKTT.css +0 -1
- package/dist/web/assets/index-oIvYSKTT.css.br +0 -0
- package/dist/web/assets/index-oIvYSKTT.css.gz +0 -0
- package/dist/web/assets/keybindings-store-30LYZU0l.js +0 -1
- package/dist/web/assets/keyboard-shortcuts-section-BgZe3QDr.js.br +0 -0
- package/dist/web/assets/keyboard-shortcuts-section-BgZe3QDr.js.gz +0 -0
- package/dist/web/assets/language-servers-section-CCMzgOaE.js.br +0 -0
- package/dist/web/assets/language-servers-section-CCMzgOaE.js.gz +0 -0
- package/dist/web/assets/lsp-client-B10suuaZ.js.br +0 -0
- package/dist/web/assets/lsp-client-B10suuaZ.js.gz +0 -0
- package/dist/web/assets/markdown-renderer-AHHFS3jc.js.br +0 -0
- package/dist/web/assets/markdown-renderer-AHHFS3jc.js.gz +0 -0
- package/dist/web/assets/markdown-renderer-DxnXtBoj.js +0 -1
- package/dist/web/assets/mobile-explorer-sheet-CqCsLWSr.js.br +0 -0
- package/dist/web/assets/mobile-explorer-sheet-CqCsLWSr.js.gz +0 -0
- package/dist/web/assets/new-design-dialog-B9tgnQXq.js +0 -1
- package/dist/web/assets/new-design-dialog-B9tgnQXq.js.br +0 -0
- package/dist/web/assets/new-design-dialog-B9tgnQXq.js.gz +0 -0
- package/dist/web/assets/notification-store-HUVzO_bp.js +0 -1
- package/dist/web/assets/notifications-settings-section-CXgzH_bK.js.br +0 -0
- package/dist/web/assets/notifications-settings-section-CXgzH_bK.js.gz +0 -0
- package/dist/web/assets/overview-panel-BYB8mgRE.js.br +0 -0
- package/dist/web/assets/overview-panel-BYB8mgRE.js.gz +0 -0
- package/dist/web/assets/panel-store-CWHPmHwj.js +0 -1
- package/dist/web/assets/panel-store-CWHPmHwj.js.br +0 -0
- package/dist/web/assets/panel-store-CWHPmHwj.js.gz +0 -0
- package/dist/web/assets/performance-panel-Dpuq3g0W.js.br +0 -0
- package/dist/web/assets/performance-panel-Dpuq3g0W.js.gz +0 -0
- package/dist/web/assets/postgres-viewer-DW0Gkmow.js.br +0 -0
- package/dist/web/assets/postgres-viewer-DW0Gkmow.js.gz +0 -0
- package/dist/web/assets/ppmbot-settings-section-DFtlGoW6.js.br +0 -0
- package/dist/web/assets/ppmbot-settings-section-DFtlGoW6.js.gz +0 -0
- package/dist/web/assets/pptx-export-CNyG32Xr.js.br +0 -0
- package/dist/web/assets/pptx-export-CNyG32Xr.js.gz +0 -0
- package/dist/web/assets/problems-panel-V5zqpuXq.js.br +0 -0
- package/dist/web/assets/problems-panel-V5zqpuXq.js.gz +0 -0
- package/dist/web/assets/process-table-DAj46HIl.js +0 -1
- package/dist/web/assets/process-table-DAj46HIl.js.br +0 -0
- package/dist/web/assets/process-table-DAj46HIl.js.gz +0 -0
- package/dist/web/assets/proxy-settings-section-B7AVlTfY.js.br +0 -0
- package/dist/web/assets/proxy-settings-section-B7AVlTfY.js.gz +0 -0
- package/dist/web/assets/query-audit-section-gHmRfWKr.js.br +0 -0
- package/dist/web/assets/query-audit-section-gHmRfWKr.js.gz +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-Cgoznh8L.js +0 -1
- package/dist/web/assets/remote-desktop-clipboard-notice-Cgoznh8L.js.br +0 -0
- package/dist/web/assets/remote-desktop-clipboard-notice-Cgoznh8L.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-X12QbPhO.js +0 -2
- package/dist/web/assets/remote-desktop-mobile-sheet-X12QbPhO.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-sheet-X12QbPhO.js.gz +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-DsSHawSK.js +0 -1
- package/dist/web/assets/remote-desktop-mobile-view-DsSHawSK.js.br +0 -0
- package/dist/web/assets/remote-desktop-mobile-view-DsSHawSK.js.gz +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-CHiQEd9Q.js +0 -1
- package/dist/web/assets/remote-desktop-readiness-gate-CHiQEd9Q.js.br +0 -0
- package/dist/web/assets/remote-desktop-readiness-gate-CHiQEd9Q.js.gz +0 -0
- package/dist/web/assets/remote-desktop-window-content-BnznIby3.js +0 -1
- package/dist/web/assets/remote-desktop-window-content-BnznIby3.js.br +0 -0
- package/dist/web/assets/remote-desktop-window-content-BnznIby3.js.gz +0 -0
- package/dist/web/assets/schedules-settings-section-sYDAsBMO.js.br +0 -0
- package/dist/web/assets/schedules-settings-section-sYDAsBMO.js.gz +0 -0
- package/dist/web/assets/send-to-chat-CCdOrKc7.js.br +0 -0
- package/dist/web/assets/send-to-chat-CCdOrKc7.js.gz +0 -0
- package/dist/web/assets/services-panel-CKa2aP1d.js.br +0 -0
- package/dist/web/assets/services-panel-CKa2aP1d.js.gz +0 -0
- package/dist/web/assets/settings-body-CEIF8lkl.js +0 -2
- package/dist/web/assets/settings-body-CEIF8lkl.js.br +0 -0
- package/dist/web/assets/settings-body-CEIF8lkl.js.gz +0 -0
- package/dist/web/assets/settings-store-DfuiLq_9.js.br +0 -0
- package/dist/web/assets/settings-store-DfuiLq_9.js.gz +0 -0
- package/dist/web/assets/settings-tab-Du5AUPni.js +0 -1
- package/dist/web/assets/settings-window-content-BTflfLez.js +0 -1
- package/dist/web/assets/slash-command-picker-CLevA_Gf.js.br +0 -0
- package/dist/web/assets/slash-command-picker-CLevA_Gf.js.gz +0 -0
- package/dist/web/assets/sql-query-editor-Db8b0jEr.js.br +0 -0
- package/dist/web/assets/sql-query-editor-Db8b0jEr.js.gz +0 -0
- package/dist/web/assets/sqlite-viewer-VzYLMqkD.js.br +0 -0
- package/dist/web/assets/sqlite-viewer-VzYLMqkD.js.gz +0 -0
- package/dist/web/assets/system-monitor-body-BR60W_mG.js.br +0 -0
- package/dist/web/assets/system-monitor-body-BR60W_mG.js.gz +0 -0
- package/dist/web/assets/system-monitor-tab-BYpantE2.js +0 -1
- package/dist/web/assets/tab-host-window-content-BL61SB5m.js.br +0 -0
- package/dist/web/assets/tab-host-window-content-BL61SB5m.js.gz +0 -0
- package/dist/web/assets/terminal-tab-B4y6at4h.js.br +0 -0
- package/dist/web/assets/terminal-tab-B4y6at4h.js.gz +0 -0
- package/dist/web/assets/tool-cards-K0r_yxI0.js.br +0 -0
- package/dist/web/assets/tool-cards-K0r_yxI0.js.gz +0 -0
- package/dist/web/assets/use-inline-blame-BK23icsE.js.br +0 -0
- package/dist/web/assets/use-inline-blame-BK23icsE.js.gz +0 -0
- package/dist/web/assets/use-lsp-CRdCPCKW.js.br +0 -0
- package/dist/web/assets/use-lsp-CRdCPCKW.js.gz +0 -0
- package/dist/web/assets/use-process-kill-BWYX03KF.js.br +0 -0
- package/dist/web/assets/use-process-kill-BWYX03KF.js.gz +0 -0
- package/dist/web/assets/video-preview-DugVkMB7.js +0 -1
- package/dist/web/assets/video-preview-DugVkMB7.js.br +0 -0
- package/dist/web/assets/video-preview-DugVkMB7.js.gz +0 -0
- package/dist/web/assets/voice-settings-section-Ceihggqf.js.br +0 -0
- package/dist/web/assets/voice-settings-section-Ceihggqf.js.gz +0 -0
- /package/dist/web/assets/{__vite-browser-external-B_XMEguz.js → __vite-browser-external-C5mXParC.js} +0 -0
- /package/dist/web/assets/{agent-session-sheet-store-DO682WSg.js → agent-session-sheet-store-_OeezCXB.js} +0 -0
- /package/dist/web/assets/{api-settings-CpO8SPk9.js → api-settings-Cc_CpfmC.js} +0 -0
- /package/dist/web/assets/{api-settings-CpO8SPk9.js.br → api-settings-Cc_CpfmC.js.br} +0 -0
- /package/dist/web/assets/{api-settings-CpO8SPk9.js.gz → api-settings-Cc_CpfmC.js.gz} +0 -0
- /package/dist/web/assets/{api-themes-CJipDH_l.js → api-themes-BtMBSjuM.js} +0 -0
- /package/dist/web/assets/{can-open-in-ppm-Bw_xiOXX.js → can-open-in-ppm-DeE2-kd5.js} +0 -0
- /package/dist/web/assets/{can-open-in-ppm-Bw_xiOXX.js.br → can-open-in-ppm-DeE2-kd5.js.br} +0 -0
- /package/dist/web/assets/{can-open-in-ppm-Bw_xiOXX.js.gz → can-open-in-ppm-DeE2-kd5.js.gz} +0 -0
- /package/dist/web/assets/{csv-parser-DcRWxcNV.js → csv-parser-CoxPdyLw.js} +0 -0
- /package/dist/web/assets/{csv-parser-DcRWxcNV.js.br → csv-parser-CoxPdyLw.js.br} +0 -0
- /package/dist/web/assets/{csv-parser-DcRWxcNV.js.gz → csv-parser-CoxPdyLw.js.gz} +0 -0
- /package/dist/web/assets/{design-export-client-CHffN3DM.js → design-export-client-BfdZB7xK.js} +0 -0
- /package/dist/web/assets/{design-export-client-CHffN3DM.js.br → design-export-client-BfdZB7xK.js.br} +0 -0
- /package/dist/web/assets/{design-export-client-CHffN3DM.js.gz → design-export-client-BfdZB7xK.js.gz} +0 -0
- /package/dist/web/assets/{design-responsive-dialog-DSCpv6O1.js → design-responsive-dialog-BiYy3ibS.js} +0 -0
- /package/dist/web/assets/{design-responsive-dialog-DSCpv6O1.js.br → design-responsive-dialog-BiYy3ibS.js.br} +0 -0
- /package/dist/web/assets/{design-responsive-dialog-DSCpv6O1.js.gz → design-responsive-dialog-BiYy3ibS.js.gz} +0 -0
- /package/dist/web/assets/{design-system-status-label-B_0I_3a8.js → design-system-status-label-ekiLyjKn.js} +0 -0
- /package/dist/web/assets/{docx-preview-B3eJyY2y.js → docx-preview-Dt6RQpfA.js} +0 -0
- /package/dist/web/assets/{docx-preview-B3eJyY2y.js.br → docx-preview-Dt6RQpfA.js.br} +0 -0
- /package/dist/web/assets/{docx-preview-B3eJyY2y.js.gz → docx-preview-Dt6RQpfA.js.gz} +0 -0
- /package/dist/web/assets/{editor-font-BNwo7zo5.js → editor-font-CBszn6vt.js} +0 -0
- /package/dist/web/assets/{format-bytes-CRZfxO2J.js → format-bytes-FQmpZ25A.js} +0 -0
- /package/dist/web/assets/{image-gallery-DC3gRAqk.js → image-gallery-B16hO6Ab.js} +0 -0
- /package/dist/web/assets/{image-preview-geometry-DN3DZQp0.js → image-preview-geometry-D4Ihz4UV.js} +0 -0
- /package/dist/web/assets/{lib-B9k5tn9s.js → lib-6APiJkU3.js} +0 -0
- /package/dist/web/assets/{lib-B9k5tn9s.js.br → lib-6APiJkU3.js.br} +0 -0
- /package/dist/web/assets/{lib-B9k5tn9s.js.gz → lib-6APiJkU3.js.gz} +0 -0
- /package/dist/web/assets/{libesm-5f7T4AHA.js → libesm-5wREk7JN.js} +0 -0
- /package/dist/web/assets/{libesm-5f7T4AHA.js.br → libesm-5wREk7JN.js.br} +0 -0
- /package/dist/web/assets/{libesm-5f7T4AHA.js.gz → libesm-5wREk7JN.js.gz} +0 -0
- /package/dist/web/assets/{media-url-CCGOIxzS.js → media-url-CrT-qulZ.js} +0 -0
- /package/dist/web/assets/{metric-chart-canvas-CjFbZuhk.js → metric-chart-canvas-D7f-LQ8x.js} +0 -0
- /package/dist/web/assets/{metric-chart-canvas-CjFbZuhk.js.br → metric-chart-canvas-D7f-LQ8x.js.br} +0 -0
- /package/dist/web/assets/{metric-chart-canvas-CjFbZuhk.js.gz → metric-chart-canvas-D7f-LQ8x.js.gz} +0 -0
- /package/dist/web/assets/{monaco-dotenv-language-Bwq3gQsi.js → monaco-dotenv-language-DbSss7YR.js} +0 -0
- /package/dist/web/assets/{onboarding-entry-CuH1Kqwu.js → onboarding-entry-CGFdGLLP.js} +0 -0
- /package/dist/web/assets/{onboarding-entry-CuH1Kqwu.js.br → onboarding-entry-CGFdGLLP.js.br} +0 -0
- /package/dist/web/assets/{onboarding-entry-CuH1Kqwu.js.gz → onboarding-entry-CGFdGLLP.js.gz} +0 -0
- /package/dist/web/assets/{pdf-preview-X8bdpfE9.js → pdf-preview-B8A4T-ES.js} +0 -0
- /package/dist/web/assets/{pdf-preview-X8bdpfE9.js.br → pdf-preview-B8A4T-ES.js.br} +0 -0
- /package/dist/web/assets/{pdf-preview-X8bdpfE9.js.gz → pdf-preview-B8A4T-ES.js.gz} +0 -0
- /package/dist/web/assets/{separator-DMu7VFQa.js → separator-dHj3Km--.js} +0 -0
- /package/dist/web/assets/{sortable-header-CipIP7aH.js → sortable-header-BOa8o7NJ.js} +0 -0
- /package/dist/web/assets/{sortable-header-CipIP7aH.js.br → sortable-header-BOa8o7NJ.js.br} +0 -0
- /package/dist/web/assets/{sortable-header-CipIP7aH.js.gz → sortable-header-BOa8o7NJ.js.gz} +0 -0
- /package/dist/web/assets/{use-blob-url-DjuRQWnR.js → use-blob-url-BC69n15x.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-Be4L1NHd.js → vendor-xterm-CfasyE0m.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-Be4L1NHd.js.br → vendor-xterm-CfasyE0m.js.br} +0 -0
- /package/dist/web/assets/{vendor-xterm-Be4L1NHd.js.gz → vendor-xterm-CfasyE0m.js.gz} +0 -0
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
1
2
|
import { WatchTree } from "./file-watcher/watch-tree.ts";
|
|
3
|
+
import { inotifyAvailable } from "./file-watcher/linux-inotify.ts";
|
|
2
4
|
|
|
3
5
|
const DEBOUNCE_MS = 500;
|
|
4
6
|
/**
|
|
5
7
|
* Directory budgets. These bound the directories PPM *covers*, which is not the same as
|
|
6
|
-
* the inotify watches it holds: measured on Linux, watching a directory costs
|
|
7
|
-
* descriptor for it plus one for every file inside — 4 directories holding 600 files
|
|
8
|
+
* the inotify watches it holds: measured on Linux, watching a directory with `fs.watch` costs
|
|
9
|
+
* one descriptor for it plus one for every file inside — 4 directories holding 600 files
|
|
8
10
|
* come to 604, recursive and non-recursive alike. So a directory cap bounds handles and
|
|
9
11
|
* walk cost, not descriptors; what keeps PPM inside the machine-wide 524288 ceiling is
|
|
10
|
-
* never registering `node_modules` in the first place.
|
|
12
|
+
* never registering `node_modules` in the first place. (Linux with glibc now watches through
|
|
13
|
+
* raw inotify instead, where a directory costs one watch and no descriptor — see
|
|
14
|
+
* `file-watcher/linux-inotify.ts`; the per-file cost is the `fs.watch` fallback's.)
|
|
11
15
|
*
|
|
12
16
|
* The per-project cap is hard. The total is best-effort: a tree keeps growing after
|
|
13
17
|
* it starts, through `syncChildDir` -> `cover`, up to its own `maxDirs` — and on
|
|
@@ -28,6 +32,36 @@ const MAX_DIRS_TOTAL = 30_000;
|
|
|
28
32
|
* watcher. A late project now gets a small budget and the truncation warning instead.
|
|
29
33
|
*/
|
|
30
34
|
const MIN_DIRS_PER_PROJECT = 1_000;
|
|
35
|
+
/**
|
|
36
|
+
* Raw inotify's caps. There a directory is one kernel watch and ~1.2 KB of heap, with no
|
|
37
|
+
* descriptor, and the caps above — sized for `fs.watch`'s per-file descriptors — cut
|
|
38
|
+
* nxsys-workspace off at 12,000 of its 28,684 directories, so a change past that point never
|
|
39
|
+
* arrived. Covering all of it measured 0.35 s with no pause over 2 ms, for 34 MB of heap
|
|
40
|
+
* against 13 MB at the old cap. What bounds this backend is `fs.inotify.max_user_watches`,
|
|
41
|
+
* which every program the user runs draws on (code-server alone held 308k of them here), so
|
|
42
|
+
* PPM takes at most a quarter of it — and a machine where that quarter is smaller than the
|
|
43
|
+
* `fs.watch` caps keeps those, which is what PPM already took there.
|
|
44
|
+
*/
|
|
45
|
+
const INOTIFY_MAX_DIRS_PER_PROJECT = 100_000;
|
|
46
|
+
const INOTIFY_MAX_DIRS_TOTAL = 250_000;
|
|
47
|
+
|
|
48
|
+
/** The per-project and total directory caps for a watching backend on a machine with this watch limit. */
|
|
49
|
+
export function watchBudgets(rawInotify: boolean, maxUserWatches: number): { perProject: number; total: number } {
|
|
50
|
+
const total = rawInotify ? Math.min(INOTIFY_MAX_DIRS_TOTAL, Math.floor(maxUserWatches / 4)) : 0;
|
|
51
|
+
if (total <= MAX_DIRS_TOTAL) return { perProject: MAX_DIRS_PER_PROJECT, total: MAX_DIRS_TOTAL };
|
|
52
|
+
return { perProject: Math.min(INOTIFY_MAX_DIRS_PER_PROJECT, total), total };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let budgets: { perProject: number; total: number } | undefined;
|
|
56
|
+
function hostBudgets(): { perProject: number; total: number } {
|
|
57
|
+
if (budgets) return budgets;
|
|
58
|
+
const rawInotify = inotifyAvailable();
|
|
59
|
+
let maxUserWatches = 0; // unreadable: keep the `fs.watch` caps
|
|
60
|
+
if (rawInotify) {
|
|
61
|
+
try { maxUserWatches = Number(readFileSync("/proc/sys/fs/inotify/max_user_watches", "utf8").trim()) || 0; } catch {}
|
|
62
|
+
}
|
|
63
|
+
return (budgets = watchBudgets(rawInotify, maxUserWatches));
|
|
64
|
+
}
|
|
31
65
|
|
|
32
66
|
type ChangeCallback = (projectName: string, path: string) => void;
|
|
33
67
|
|
|
@@ -60,7 +94,7 @@ export function onFileChange(cb: ChangeCallback): void {
|
|
|
60
94
|
* reached so far. The walk hands the event loop back every few hundred directories, so its
|
|
61
95
|
* count climbs for seconds — and a second project opened during one used to size its budget
|
|
62
96
|
* against that unfinished number, which is how two projects starting together could each be
|
|
63
|
-
* told there was room and overshoot
|
|
97
|
+
* told there was room and overshoot the total between them. Over-counting is the safe
|
|
64
98
|
* direction: the reservation is released the moment the walk lands and reports its real size.
|
|
65
99
|
*/
|
|
66
100
|
function totalCoveredDirs(): number {
|
|
@@ -110,10 +144,8 @@ export function startWatching(projectName: string, projectPath: string): Promise
|
|
|
110
144
|
return existing.ready;
|
|
111
145
|
}
|
|
112
146
|
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
Math.min(MAX_DIRS_PER_PROJECT, MAX_DIRS_TOTAL - totalCoveredDirs()),
|
|
116
|
-
);
|
|
147
|
+
const { perProject, total } = hostBudgets();
|
|
148
|
+
const maxDirs = Math.max(MIN_DIRS_PER_PROJECT, Math.min(perProject, total - totalCoveredDirs()));
|
|
117
149
|
const entry: WatchEntry = {
|
|
118
150
|
tree: new WatchTree({
|
|
119
151
|
root: projectPath,
|
|
@@ -13,12 +13,16 @@ import {
|
|
|
13
13
|
removeEntrySync,
|
|
14
14
|
renameEntrySync,
|
|
15
15
|
} from "./fs-ops/fs-core-ops.ts";
|
|
16
|
-
import type { FileNode,
|
|
16
|
+
import type { FileNode, FileDirEntry, FileEntry } from "../types/project.ts";
|
|
17
|
+
import type { IndexBuild } from "./file-index/index-walk.ts";
|
|
18
|
+
import type { SearchKind } from "./file-index/index-search.ts";
|
|
17
19
|
import {
|
|
18
20
|
listDir as listDirImpl,
|
|
19
21
|
listDirBatch as listDirBatchImpl,
|
|
20
22
|
buildIndex as buildIndexImpl,
|
|
23
|
+
searchFileIndex,
|
|
21
24
|
invalidateIndexCache,
|
|
25
|
+
markIndexStale,
|
|
22
26
|
clearIndexCache,
|
|
23
27
|
} from "./file-list-index.service.ts";
|
|
24
28
|
|
|
@@ -280,13 +284,19 @@ class FileService {
|
|
|
280
284
|
}
|
|
281
285
|
|
|
282
286
|
/**
|
|
283
|
-
* Build flat file index for palette/search (delegates to file-list-index.service)
|
|
284
|
-
* Cached per project;
|
|
287
|
+
* Build flat file index for palette/search (delegates to file-list-index.service), as the
|
|
288
|
+
* ready-to-send `/files/index` response. Cached per project; a file change marks it stale
|
|
289
|
+
* via markIndexStale().
|
|
285
290
|
*/
|
|
286
|
-
buildIndex(projectPath: string):
|
|
291
|
+
buildIndex(projectPath: string): Promise<IndexBuild> {
|
|
287
292
|
return buildIndexImpl(projectPath);
|
|
288
293
|
}
|
|
289
294
|
|
|
295
|
+
/** Search the flat file index on the server (delegates to file-list-index.service). */
|
|
296
|
+
searchIndex(projectPath: string, query: string, kind: SearchKind, limit: number): Promise<FileEntry[]> {
|
|
297
|
+
return searchFileIndex(projectPath, query, kind, limit);
|
|
298
|
+
}
|
|
299
|
+
|
|
290
300
|
/** Block access to sensitive paths (.git/) */
|
|
291
301
|
private blockSensitive(filePath: string): void {
|
|
292
302
|
const normalized = normalize(filePath);
|
|
@@ -323,7 +333,8 @@ export class ValidationError extends Error {
|
|
|
323
333
|
|
|
324
334
|
export const fileService = new FileService();
|
|
325
335
|
|
|
326
|
-
// Wire file watcher → index
|
|
336
|
+
// Wire file watcher → index staleness. Stale, not dropped: dropping made the next request walk
|
|
337
|
+
// the whole project while it waited (see IndexEntry in file-list-index.service).
|
|
327
338
|
// Dynamic import avoids circular dependency (file-watcher → chat.ts → file.service)
|
|
328
339
|
import("./file-watcher.service.ts").then(({ onFileChange }) => {
|
|
329
340
|
onFileChange((projectName) => {
|
|
@@ -332,7 +343,7 @@ import("./file-watcher.service.ts").then(({ onFileChange }) => {
|
|
|
332
343
|
const { configService } = require("./config.service.ts");
|
|
333
344
|
const projects = configService.get("projects") as Array<{ name: string; path: string }>;
|
|
334
345
|
const project = projects.find((p: { name: string }) => p.name === projectName);
|
|
335
|
-
if (project)
|
|
346
|
+
if (project) markIndexStale(project.path);
|
|
336
347
|
} catch {
|
|
337
348
|
// Config not yet loaded or project not found — skip invalidation
|
|
338
349
|
}
|
|
@@ -327,7 +327,7 @@ class GroupChatService {
|
|
|
327
327
|
// consumer-side signal guard halts the turn, so only permissionMode is
|
|
328
328
|
// forwarded here.
|
|
329
329
|
sendMessage: (pid, sid, prompt, opts) =>
|
|
330
|
-
chatService.sendMessage(pid, sid, prompt, { permissionMode: opts?.permissionMode, model: opts?.model, oneMContext: opts?.oneMContext }),
|
|
330
|
+
chatService.sendMessage(pid, sid, prompt, { permissionMode: opts?.permissionMode, model: opts?.model, oneMContext: opts?.oneMContext, origin: "group-chat" }),
|
|
331
331
|
};
|
|
332
332
|
return this.backendCache;
|
|
333
333
|
}
|
|
@@ -184,7 +184,7 @@ class JiraDebugSessionService {
|
|
|
184
184
|
|
|
185
185
|
// bypassPermissions: automated debug sessions run without user approval (same as PPMBot)
|
|
186
186
|
const opts = { permissionMode: "bypassPermissions" as PermissionMode };
|
|
187
|
-
const events = chatService.sendMessage(session.providerId, session.id, prompt, opts);
|
|
187
|
+
const events = chatService.sendMessage(session.providerId, session.id, prompt, { ...opts, origin: "jira" });
|
|
188
188
|
|
|
189
189
|
let lastAssistantText = "";
|
|
190
190
|
for await (const event of events) {
|
|
@@ -43,7 +43,7 @@ export async function executeDelegation(
|
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
const opts = { permissionMode: "bypassPermissions" as PermissionMode };
|
|
46
|
-
const events = chatService.sendMessage(providerId, session.id, task.prompt, opts);
|
|
46
|
+
const events = chatService.sendMessage(providerId, session.id, task.prompt, { ...opts, origin: "ppmbot" });
|
|
47
47
|
|
|
48
48
|
let fullText = "";
|
|
49
49
|
let lastAssistantText = "";
|
|
@@ -31,6 +31,43 @@ export async function resolveProjectSearchGrep(options: ResolverOptions = {}): P
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/** The program a search runs, and which one it is: their flags differ. */
|
|
35
|
+
export interface ProjectSearchTool { kind: "rg" | "grep"; path: string }
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* ripgrep when it is installed, GNU grep otherwise. ripgrep searches on every core, grep on one:
|
|
39
|
+
* on nxsys-workspace (181k entries) one query took grep 1.7 s — 11 s from a cold disk cache, past
|
|
40
|
+
* the timeout — and ripgrep 0.1 s, for the same 38,071 lines.
|
|
41
|
+
*/
|
|
42
|
+
export async function resolveProjectSearchTool(options: ResolverOptions = {}): Promise<ProjectSearchTool | undefined> {
|
|
43
|
+
const rg = (options.which ?? ((name: string) => Bun.which(name)))("rg");
|
|
44
|
+
if (rg) return { kind: "rg", path: rg };
|
|
45
|
+
const grep = await resolveProjectSearchGrep(options);
|
|
46
|
+
return grep ? { kind: "grep", path: grep } : undefined;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const EXCLUDED_DIRS = ["node_modules", ".git", "dist", ".next", "build", ".turbo", "coverage", "__pycache__"];
|
|
50
|
+
const EXCLUDED_FILES = ["*.min.js", "*.map", "*.lock", "bun.lock"];
|
|
51
|
+
|
|
52
|
+
/** Both print `path\0line:content` per match and exit 0 / 1 / 2 for match / none / error. */
|
|
53
|
+
function searchArgs(kind: ProjectSearchTool["kind"], options: ProjectSearchOptions): string[] {
|
|
54
|
+
const matching = [...(options.caseSensitive ? [] : ["-i"]), ...(options.wholeWord ? ["-w"] : [])];
|
|
55
|
+
if (kind === "rg") {
|
|
56
|
+
// -uu searches ignored and hidden files, as grep -r does; a trailing slash makes a glob match
|
|
57
|
+
// directories only, as --exclude-dir does. --no-config: a user's RIPGREP_CONFIG_PATH could
|
|
58
|
+
// change the output format. ripgrep prints `\` on Windows, and results are keyed by `/` paths.
|
|
59
|
+
return ["--no-config", "-uu", "--no-heading", "--with-filename", "--line-number", "--null", "--max-count=5",
|
|
60
|
+
"--path-separator=/",
|
|
61
|
+
...(options.regex ? [] : ["-F"]), ...matching,
|
|
62
|
+
...EXCLUDED_DIRS.flatMap((dir) => ["-g", `!${dir}/`]), ...EXCLUDED_FILES.flatMap((file) => ["-g", `!${file}`]),
|
|
63
|
+
"--", options.query, "."];
|
|
64
|
+
}
|
|
65
|
+
// Long --null also works with BSD grep, where -Z means decompress.
|
|
66
|
+
return ["-rHn", "--null", "--max-count=5", "-I", options.regex ? "-E" : "-F", ...matching,
|
|
67
|
+
...EXCLUDED_DIRS.flatMap((dir) => ["--exclude-dir", dir]), ...EXCLUDED_FILES.map((file) => `--exclude=${file}`),
|
|
68
|
+
"--", options.query, "."];
|
|
69
|
+
}
|
|
70
|
+
|
|
34
71
|
/** Convert glob pattern (VSCode-style) to RegExp for path filtering.
|
|
35
72
|
* - `*.ts` → matches any .ts file in any directory
|
|
36
73
|
* - `src/**` → matches any file under src/
|
|
@@ -57,17 +94,12 @@ export interface ProjectSearchOptions {
|
|
|
57
94
|
}
|
|
58
95
|
|
|
59
96
|
export async function searchProjectContent(projectPath: string, options: ProjectSearchOptions,
|
|
60
|
-
dependencies: {
|
|
97
|
+
dependencies: { resolveTool?: () => Promise<ProjectSearchTool | undefined>; timeoutMs?: number; maxBytes?: number } = {}) {
|
|
61
98
|
const empty = { results: [] as Array<{ file: string; matches: Array<{ lineNum: number; content: string }> }>, total: 0 };
|
|
62
99
|
if (options.query.length < (options.regex ? 1 : 2)) return empty;
|
|
63
|
-
const
|
|
64
|
-
if (!
|
|
65
|
-
const
|
|
66
|
-
// Long --null also works with BSD grep, where -Z means decompress.
|
|
67
|
-
const flags = ["-rHn", "--null", "--max-count=5", "-I", options.regex ? "-E" : "-F", ...(options.caseSensitive ? [] : ["-i"]), ...(options.wholeWord ? ["-w"] : [])];
|
|
68
|
-
const proc = Bun.spawn({ cmd: [executable, ...flags, ...excluded.flatMap((dir) => ["--exclude-dir", dir]),
|
|
69
|
-
"--exclude=*.min.js", "--exclude=*.map", "--exclude=*.lock", "--exclude=bun.lock", "--", options.query, "."],
|
|
70
|
-
cwd: projectPath, stdout: "pipe", stderr: "pipe" });
|
|
100
|
+
const tool = await (dependencies.resolveTool ?? resolveProjectSearchTool)();
|
|
101
|
+
if (!tool) throw new ProjectSearchError("Content search needs ripgrep or GNU grep. Install ripgrep or Git for Windows, or make grep available on PATH, then retry.", 503);
|
|
102
|
+
const proc = Bun.spawn({ cmd: [tool.path, ...searchArgs(tool.kind, options)], cwd: projectPath, stdout: "pipe", stderr: "pipe" });
|
|
71
103
|
let failure: ProjectSearchError | undefined;
|
|
72
104
|
let bytes = 0;
|
|
73
105
|
const stop = (error: ProjectSearchError) => { failure ??= error; proc.kill(); };
|
|
@@ -93,7 +125,7 @@ export async function searchProjectContent(projectPath: string, options: Project
|
|
|
93
125
|
finally { clearTimeout(timer); if (proc.exitCode === null) proc.kill(); }
|
|
94
126
|
if (failure) throw failure;
|
|
95
127
|
if (code !== 0 && code !== 1) {
|
|
96
|
-
const invalidPattern = options.regex && /regular expression|unmatched|unterminated|invalid range|trailing backslash|repetition/i.test(stderr);
|
|
128
|
+
const invalidPattern = options.regex && /regex parse error|regular expression|unmatched|unterminated|invalid range|trailing backslash|repetition/i.test(stderr);
|
|
97
129
|
throw new ProjectSearchError(invalidPattern ? "Invalid regular expression. Check the pattern and retry." : "Content search failed. Check file permissions and the search tool, then retry.", invalidPattern ? 400 : 500);
|
|
98
130
|
}
|
|
99
131
|
if (code === 1) return empty;
|
|
@@ -114,6 +146,8 @@ export async function searchProjectContent(projectPath: string, options: Project
|
|
|
114
146
|
matches.push({ lineNum: Number(record[1]), content: record[2]!.trimEnd() });
|
|
115
147
|
files.set(file, matches);
|
|
116
148
|
}
|
|
117
|
-
|
|
149
|
+
// ripgrep prints files in whatever order its threads finish them, so sort for a stable list.
|
|
150
|
+
const results = Array.from(files, ([file, matches]) => ({ file, matches }))
|
|
151
|
+
.sort((a, b) => (a.file < b.file ? -1 : a.file > b.file ? 1 : 0));
|
|
118
152
|
return { results, total: results.reduce((sum, result) => sum + result.matches.length, 0) };
|
|
119
153
|
}
|
|
@@ -16,6 +16,7 @@ import { mkdirSync } from "node:fs";
|
|
|
16
16
|
import { resolve } from "node:path";
|
|
17
17
|
import { providerRegistry } from "../providers/registry.ts";
|
|
18
18
|
import { getPpmDir } from "./ppm-dir.ts";
|
|
19
|
+
import { traceStream } from "./session-trace/trace-recorder.ts";
|
|
19
20
|
import type { AIProvider, ChatEvent } from "../types/chat.ts";
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -190,14 +191,17 @@ export async function startAgentTurn(providerId: string, req: TurnRequest): Prom
|
|
|
190
191
|
title: `[API] ${providerId}`,
|
|
191
192
|
});
|
|
192
193
|
|
|
193
|
-
const
|
|
194
|
+
const opts = {
|
|
194
195
|
permissionMode: PROXY_PERMISSION_MODE,
|
|
195
196
|
...(req.model ? { model: req.model } : {}),
|
|
196
197
|
...(req.imagePaths?.length ? { imagePaths: req.imagePaths } : {}),
|
|
197
|
-
}
|
|
198
|
+
};
|
|
199
|
+
const events = provider.sendMessage(session.id, message, opts);
|
|
198
200
|
|
|
199
201
|
return {
|
|
200
|
-
|
|
202
|
+
// Not through ChatService (no shared context, no design options), so it is traced here —
|
|
203
|
+
// outside the timeout, so a stalled turn is recorded as the failure it surfaces as.
|
|
204
|
+
events: traceStream({ sessionId: session.id, providerId: provider.id, origin: "proxy", message, opts }, withTimeout(events)),
|
|
201
205
|
cleanup: async () => {
|
|
202
206
|
try {
|
|
203
207
|
// abortQuery is what kills the runtime; deleteSession alone may only drop
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What "install the WebRTC relay" downloads: one MediaMTX build per platform.
|
|
3
|
+
*
|
|
4
|
+
* MediaMTX is a single static Go binary (Pion underneath) that takes PPM's existing H.264
|
|
5
|
+
* over RTSP and serves it to a browser as WebRTC, **without re-encoding** — verified against
|
|
6
|
+
* v1.21.1: a 1920x1080 Main@4.0 stream pushed by ffmpeg arrived at the browser as
|
|
7
|
+
* `video/H264` at the same resolution. That is the whole reason this is a relay and not an
|
|
8
|
+
* encoder: every bit of PPM's per-platform capture, quality ladder, cursor flag and privacy
|
|
9
|
+
* mode keeps working unchanged, and only the transport moves off the WebSocket.
|
|
10
|
+
*
|
|
11
|
+
* Why a downloaded binary rather than a library: Bun has no WebRTC stack at all. The two
|
|
12
|
+
* in-process routes were both measured and rejected — GStreamer's `webrtcbin` segfaults
|
|
13
|
+
* PyGObject on GStreamer 1.28.7 + Python 3.14 (`gst_sdp_message_copy` walking a malformed
|
|
14
|
+
* emails array) *and* would put GStreamer + PyGObject on every Windows and macOS host, while
|
|
15
|
+
* `@roamhq/wrtc` only accepts raw i420 frames, i.e. it would throw away the hardware H.264
|
|
16
|
+
* encode PPM just did and encode again in software.
|
|
17
|
+
*
|
|
18
|
+
* Pure and parameterised so the whole matrix is unit-testable without touching `process.*` or
|
|
19
|
+
* the network. Every entry is pinned by tag AND by SHA-256, because this downloads an
|
|
20
|
+
* executable onto the user's machine.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** MediaMTX release the binaries come from. Bump this and every SHA-256 below together. */
|
|
24
|
+
export const MEDIAMTX_VERSION = "1.21.1";
|
|
25
|
+
|
|
26
|
+
const RELEASE_BASE = `https://github.com/bluenviron/mediamtx/releases/download/v${MEDIAMTX_VERSION}`;
|
|
27
|
+
|
|
28
|
+
export interface MediamtxAsset {
|
|
29
|
+
/** Archive file name as published in the release. */
|
|
30
|
+
file: string;
|
|
31
|
+
url: string;
|
|
32
|
+
/** Lowercase hex, from the release's own `checksums.sha256`. */
|
|
33
|
+
sha256: string;
|
|
34
|
+
ext: "tar.gz" | "zip";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Keyed `<platform>-<arch>` in Node's own vocabulary, so a caller passes `process.platform`
|
|
39
|
+
* and `process.arch` straight through.
|
|
40
|
+
*
|
|
41
|
+
* `win32-arm64` is deliberately absent: the release publishes no Windows ARM build, and a
|
|
42
|
+
* missing row has to read as "not available for this host" rather than fall back to an amd64
|
|
43
|
+
* binary that would fail at spawn with nothing explaining why.
|
|
44
|
+
*/
|
|
45
|
+
const ASSETS: Record<string, MediamtxAsset> = {
|
|
46
|
+
"linux-x64": {
|
|
47
|
+
file: `mediamtx_v${MEDIAMTX_VERSION}_linux_amd64.tar.gz`,
|
|
48
|
+
url: `${RELEASE_BASE}/mediamtx_v${MEDIAMTX_VERSION}_linux_amd64.tar.gz`,
|
|
49
|
+
sha256: "653abc672a3e693f8d3b2717752492fdcfb8072291ec108d03d3dd857411b0ee",
|
|
50
|
+
ext: "tar.gz",
|
|
51
|
+
},
|
|
52
|
+
"linux-arm64": {
|
|
53
|
+
file: `mediamtx_v${MEDIAMTX_VERSION}_linux_arm64.tar.gz`,
|
|
54
|
+
url: `${RELEASE_BASE}/mediamtx_v${MEDIAMTX_VERSION}_linux_arm64.tar.gz`,
|
|
55
|
+
sha256: "6a3aa635fb60ea9b8d566ec306f0a42ff1b6b52a3942bc2baffbe55880d4c3dd",
|
|
56
|
+
ext: "tar.gz",
|
|
57
|
+
},
|
|
58
|
+
"darwin-x64": {
|
|
59
|
+
file: `mediamtx_v${MEDIAMTX_VERSION}_darwin_amd64.tar.gz`,
|
|
60
|
+
url: `${RELEASE_BASE}/mediamtx_v${MEDIAMTX_VERSION}_darwin_amd64.tar.gz`,
|
|
61
|
+
sha256: "be403a36d2225668ea695cbd2c784109bc23ef9a32f886837e43c920b6818813",
|
|
62
|
+
ext: "tar.gz",
|
|
63
|
+
},
|
|
64
|
+
"darwin-arm64": {
|
|
65
|
+
file: `mediamtx_v${MEDIAMTX_VERSION}_darwin_arm64.tar.gz`,
|
|
66
|
+
url: `${RELEASE_BASE}/mediamtx_v${MEDIAMTX_VERSION}_darwin_arm64.tar.gz`,
|
|
67
|
+
sha256: "25e20ed41611f1f3103b8359585210b29b11b69fa0d9e11bd11b92f7bbcb42ef",
|
|
68
|
+
ext: "tar.gz",
|
|
69
|
+
},
|
|
70
|
+
"win32-x64": {
|
|
71
|
+
file: `mediamtx_v${MEDIAMTX_VERSION}_windows_amd64.zip`,
|
|
72
|
+
url: `${RELEASE_BASE}/mediamtx_v${MEDIAMTX_VERSION}_windows_amd64.zip`,
|
|
73
|
+
sha256: "faa97974861eb75a68b5aa326c78e7e7a6f670b5ef191bace78e715130381f23",
|
|
74
|
+
ext: "zip",
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/** The build for a host, or null when the release publishes none for it. */
|
|
79
|
+
export function mediamtxAsset(
|
|
80
|
+
platform: NodeJS.Platform = process.platform,
|
|
81
|
+
arch: string = process.arch,
|
|
82
|
+
): MediamtxAsset | null {
|
|
83
|
+
return ASSETS[`${platform}-${arch}`] ?? null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Every key the catalog knows, for tests and for the Settings pane's support copy. */
|
|
87
|
+
export function mediamtxSupportedHosts(): string[] {
|
|
88
|
+
return Object.keys(ASSETS);
|
|
89
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The MediaMTX config PPM generates for each run, and the one place the relay's exposure is
|
|
3
|
+
* decided.
|
|
4
|
+
*
|
|
5
|
+
* The archive ships its own `mediamtx.yml` that listens on every interface and turns on RTSP,
|
|
6
|
+
* RTMP, HLS, SRT, MoQ, an HTTP API, metrics and pprof. None of that is wanted, and MoQ in
|
|
7
|
+
* particular writes a self-signed `auto.crt`/`auto.key` beside itself on first start. PPM
|
|
8
|
+
* writes this file instead and passes it explicitly, so the shipped one is never read.
|
|
9
|
+
*
|
|
10
|
+
* Verified against v1.21.1: the generated config leaves exactly three sockets open —
|
|
11
|
+
* 127.0.0.1:<rtsp> TCP ffmpeg pushes the H.264 it already encoded
|
|
12
|
+
* 127.0.0.1:<whep> TCP WHEP signalling, reached only through PPM's authenticated proxy
|
|
13
|
+
* *:<ice> UDP the media itself
|
|
14
|
+
*
|
|
15
|
+
* The UDP port is the one thing that cannot be confined to loopback: WebRTC media goes
|
|
16
|
+
* peer-to-peer, so a browser on the LAN or the tailnet has to be able to reach it. What
|
|
17
|
+
* protects it is the ICE credentials — a random ufrag/password minted per session and carried
|
|
18
|
+
* in the SDP, which only travels through the authenticated proxy. That is the standard WebRTC
|
|
19
|
+
* model, but it does mean the port answers to anyone who can reach it *and* already holds a
|
|
20
|
+
* session's SDP, so the path name is random per session too rather than a guessable "desktop".
|
|
21
|
+
*/
|
|
22
|
+
import { randomBytes } from "node:crypto";
|
|
23
|
+
|
|
24
|
+
export interface MediamtxConfigOptions {
|
|
25
|
+
/** Loopback TCP port ffmpeg pushes RTSP to. */
|
|
26
|
+
rtspPort: number;
|
|
27
|
+
/** Loopback TCP port serving WHEP; PPM proxies to it. */
|
|
28
|
+
whepPort: number;
|
|
29
|
+
/** UDP port ICE media flows over. Bound on every interface by necessity. */
|
|
30
|
+
iceUdpPort: number;
|
|
31
|
+
/** Stream path, from `randomStreamPath()`. */
|
|
32
|
+
pathName: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* An unguessable path per session. MediaMTX path names allow only word characters, so this is
|
|
37
|
+
* hex rather than base64url.
|
|
38
|
+
*/
|
|
39
|
+
export function randomStreamPath(): string {
|
|
40
|
+
return `s${randomBytes(16).toString("hex")}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Where ffmpeg pushes, and where the relay reads from. */
|
|
44
|
+
export function rtspPublishUrl(rtspPort: number, pathName: string): string {
|
|
45
|
+
return `rtsp://127.0.0.1:${rtspPort}/${pathName}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** The WHEP endpoint on the relay, which PPM proxies rather than exposes. */
|
|
49
|
+
export function whepUrl(whepPort: number, pathName: string): string {
|
|
50
|
+
return `http://127.0.0.1:${whepPort}/${pathName}/whep`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* MediaMTX rejects unknown config keys outright (`json: unknown field "..."`), which is why
|
|
55
|
+
* every switch here is spelled out rather than trusted to default: a key that a future release
|
|
56
|
+
* renames fails loudly at start instead of silently leaving a listener open.
|
|
57
|
+
*/
|
|
58
|
+
export function buildMediamtxConfig(opts: MediamtxConfigOptions): string {
|
|
59
|
+
const { rtspPort, whepPort, iceUdpPort, pathName } = opts;
|
|
60
|
+
return [
|
|
61
|
+
"# Generated by PPM for one Remote Desktop session. Edits are overwritten on every start.",
|
|
62
|
+
"logLevel: warn",
|
|
63
|
+
"",
|
|
64
|
+
"# RTSP ingest: loopback only, TCP only. ffmpeg is the only thing that ever publishes.",
|
|
65
|
+
"rtsp: yes",
|
|
66
|
+
"rtspTransports: [tcp]",
|
|
67
|
+
`rtspAddress: 127.0.0.1:${rtspPort}`,
|
|
68
|
+
"",
|
|
69
|
+
"# WebRTC out. The signalling port stays on loopback and is reached through PPM's",
|
|
70
|
+
"# authenticated proxy; only the ICE/UDP port faces the network.",
|
|
71
|
+
"webrtc: yes",
|
|
72
|
+
`webrtcAddress: 127.0.0.1:${whepPort}`,
|
|
73
|
+
`webrtcLocalUDPAddress: :${iceUdpPort}`,
|
|
74
|
+
"webrtcIPsFromInterfaces: yes",
|
|
75
|
+
"",
|
|
76
|
+
"# Everything else off. MoQ also writes auto.crt/auto.key beside itself when left on.",
|
|
77
|
+
"rtmp: no",
|
|
78
|
+
"hls: no",
|
|
79
|
+
"srt: no",
|
|
80
|
+
"moq: no",
|
|
81
|
+
"api: no",
|
|
82
|
+
"metrics: no",
|
|
83
|
+
"pprof: no",
|
|
84
|
+
"playback: no",
|
|
85
|
+
"",
|
|
86
|
+
"paths:",
|
|
87
|
+
` ${pathName}:`,
|
|
88
|
+
" source: publisher",
|
|
89
|
+
"",
|
|
90
|
+
].join("\n");
|
|
91
|
+
}
|