@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
|
@@ -18,9 +18,11 @@ import {
|
|
|
18
18
|
CircleX,
|
|
19
19
|
WrapText,
|
|
20
20
|
Zap,
|
|
21
|
+
Cpu,
|
|
21
22
|
} from "@/lib/icons";
|
|
22
23
|
import { openExplorer } from "@/components/os-explorer/open-explorer";
|
|
23
24
|
import { openSettings } from "@/components/settings/open-settings";
|
|
25
|
+
import { useOpenSystemMonitor } from "@/components/system/use-open-system-monitor";
|
|
24
26
|
import { useTabStore, type TabType } from "@/stores/tab-store";
|
|
25
27
|
import { useProjectStore } from "@/stores/project-store";
|
|
26
28
|
import { useSettingsStore } from "@/stores/settings-store";
|
|
@@ -28,6 +30,7 @@ import { useIsMobile } from "@/hooks/use-is-mobile";
|
|
|
28
30
|
import { useIsTouchOnly } from "@/hooks/use-is-touch-only";
|
|
29
31
|
import { useKeybindingsStore } from "@/stores/keybindings-store";
|
|
30
32
|
import { useFileStore, type FileNode } from "@/stores/file-store";
|
|
33
|
+
import { useRemoteFileSearch } from "@/hooks/use-remote-file-search";
|
|
31
34
|
import { useExtensionStore } from "@/stores/extension-store";
|
|
32
35
|
import { extensionIcon } from "@/lib/extension-icons";
|
|
33
36
|
import { useCompareStore } from "@/stores/compare-store";
|
|
@@ -128,8 +131,10 @@ export function CommandPalette({ open, onClose, initialQuery = "" }: { open: boo
|
|
|
128
131
|
const activeProject = useProjectStore((s) => s.activeProject);
|
|
129
132
|
const fileIndex = useFileStore((s) => s.fileIndex);
|
|
130
133
|
const indexStatus = useFileStore((s) => s.indexStatus);
|
|
131
|
-
const
|
|
134
|
+
const indexProject = useFileStore((s) => s.indexProject);
|
|
135
|
+
const indexRemote = useFileStore((s) => s.indexRemote);
|
|
132
136
|
const loadIndex = useFileStore((s) => s.loadIndex);
|
|
137
|
+
const openIndexReader = useFileStore((s) => s.openIndexReader);
|
|
133
138
|
const fileTree = useFileStore((s) => s.tree);
|
|
134
139
|
const setSidebarActiveTab = useSettingsStore((s) => s.setSidebarActiveTab);
|
|
135
140
|
const sidebarCollapsed = useSettingsStore((s) => s.sidebarCollapsed);
|
|
@@ -139,6 +144,7 @@ export function CommandPalette({ open, onClose, initialQuery = "" }: { open: boo
|
|
|
139
144
|
const isMobile = useIsMobile();
|
|
140
145
|
const isTouchOnly = useIsTouchOnly();
|
|
141
146
|
const lspEnabled = useSettingsStore((s) => s.lspEnabled);
|
|
147
|
+
const openSystemMonitor = useOpenSystemMonitor();
|
|
142
148
|
|
|
143
149
|
/**
|
|
144
150
|
* A query may name one place in a file — `app.ts:120`, `app.ts:120-140`, `app.ts#L120` —
|
|
@@ -151,6 +157,11 @@ export function CommandPalette({ open, onClose, initialQuery = "" }: { open: boo
|
|
|
151
157
|
() => splitSourceLocation(deferredQuery)?.path ?? deferredQuery,
|
|
152
158
|
[deferredQuery],
|
|
153
159
|
);
|
|
160
|
+
// A project too long to send is searched on the server as the query changes. What comes back
|
|
161
|
+
// is ranked below with everything else, exactly as the list itself would have been.
|
|
162
|
+
const remoteFiles = useRemoteFileSearch(activeProject?.name, searchPath, {
|
|
163
|
+
enabled: open && indexRemote && !!searchPath.trim() && !isPathQuery(searchPath),
|
|
164
|
+
});
|
|
154
165
|
|
|
155
166
|
/**
|
|
156
167
|
* Read when an item is actually picked, rather than closed over per command: the file
|
|
@@ -306,6 +317,15 @@ export function CommandPalette({ open, onClose, initialQuery = "" }: { open: boo
|
|
|
306
317
|
onClose();
|
|
307
318
|
},
|
|
308
319
|
},
|
|
320
|
+
// A phone's only way in: the status bar's CPU/MEM chip, the other one, is hidden below md.
|
|
321
|
+
{
|
|
322
|
+
id: "system-monitor", label: "System Monitor", icon: Cpu, group: "action",
|
|
323
|
+
keywords: "task manager activity monitor cpu memory ram disk network gpu processes services apps performance resources",
|
|
324
|
+
action: () => {
|
|
325
|
+
openSystemMonitor();
|
|
326
|
+
onClose();
|
|
327
|
+
},
|
|
328
|
+
},
|
|
309
329
|
];
|
|
310
330
|
|
|
311
331
|
// Append extension-contributed commands (with keybinding shortcuts, respecting user overrides)
|
|
@@ -330,14 +350,16 @@ export function CommandPalette({ open, onClose, initialQuery = "" }: { open: boo
|
|
|
330
350
|
});
|
|
331
351
|
|
|
332
352
|
return [...builtIn, ...designCommands, ...extCmds];
|
|
333
|
-
}, [activeProject, openTab, onClose, setSidebarActiveTab, sidebarCollapsed, toggleSidebar, getBinding, extContributions, isMobile, isTouchOnly, lspEnabled, designCommands]);
|
|
353
|
+
}, [activeProject, openTab, onClose, setSidebarActiveTab, sidebarCollapsed, toggleSidebar, getBinding, extContributions, isMobile, isTouchOnly, lspEnabled, designCommands, openSystemMonitor]);
|
|
334
354
|
|
|
335
355
|
// File commands — from index when ready, fallback to flattened tree
|
|
336
356
|
const fileCommands = useMemo<CommandItem[]>(() => {
|
|
337
357
|
const projectId = activeProject?.name ?? null;
|
|
338
358
|
const meta = activeProject ? { projectName: activeProject.name } : undefined;
|
|
339
359
|
// Filter index to files only — directories are in the index for palette "open folder" affordances but not for file-open commands
|
|
340
|
-
const files =
|
|
360
|
+
const files = indexRemote
|
|
361
|
+
? remoteFiles
|
|
362
|
+
: indexStatus === "ready" && indexProject === activeProject?.name ? fileIndex.filter((e) => e.type === "file") : flattenFiles(fileTree);
|
|
341
363
|
|
|
342
364
|
return files.map((f) => ({
|
|
343
365
|
id: `file:${f.path}`,
|
|
@@ -350,7 +372,7 @@ export function CommandPalette({ open, onClose, initialQuery = "" }: { open: boo
|
|
|
350
372
|
isIgnored: ("isIgnored" in f ? f.isIgnored : undefined) as boolean | undefined,
|
|
351
373
|
action: () => openFileTab(f.path, f.name, projectId, meta),
|
|
352
374
|
}));
|
|
353
|
-
}, [indexStatus,
|
|
375
|
+
}, [indexStatus, indexProject, indexRemote, remoteFiles, fileIndex, fileTree, activeProject, openFileTab]);
|
|
354
376
|
|
|
355
377
|
// Filesystem commands — from cached API results
|
|
356
378
|
const fsCommands = useMemo<CommandItem[]>(() => {
|
|
@@ -473,12 +495,12 @@ export function CommandPalette({ open, onClose, initialQuery = "" }: { open: boo
|
|
|
473
495
|
setSelectedIdx(0);
|
|
474
496
|
}, []);
|
|
475
497
|
|
|
476
|
-
//
|
|
498
|
+
// Load the file index as the palette opens, or refresh it if files changed since, and keep it
|
|
499
|
+
// current while it stays open. Not on `indexStatus`: a failed load would retry itself in a
|
|
500
|
+
// loop — the hint below has a retry.
|
|
477
501
|
useEffect(() => {
|
|
478
|
-
if (open && activeProject
|
|
479
|
-
|
|
480
|
-
}
|
|
481
|
-
}, [open, indexStatus, indexProjectName, activeProject, loadIndex]);
|
|
502
|
+
if (open && activeProject) return openIndexReader(activeProject.name);
|
|
503
|
+
}, [open, activeProject, openIndexReader]);
|
|
482
504
|
|
|
483
505
|
// Reset state when opening
|
|
484
506
|
useEffect(() => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState, useCallback, useEffect, useMemo, lazy, Suspense } from "react";
|
|
2
|
-
import { X, Bug as BugIcon, Cloud, FolderTree, MonitorSmartphone, Settings } from "@/lib/icons";
|
|
2
|
+
import { X, Bug as BugIcon, Cloud, FolderTree, MonitorSmartphone, Settings, Smartphone } from "@/lib/icons";
|
|
3
3
|
import { useShallow } from "zustand/react/shallow";
|
|
4
4
|
import { useProjectStore } from "@/stores/project-store";
|
|
5
5
|
import { useSettingsStore, type SidebarActiveTab } from "@/stores/settings-store";
|
|
@@ -25,6 +25,8 @@ import { isMobileDevice } from "@/hooks/use-is-mobile";
|
|
|
25
25
|
import { openExplorer } from "@/components/os-explorer/open-explorer";
|
|
26
26
|
import { useOpenRemoteDesktop } from "@/components/remote-desktop/open-remote-desktop";
|
|
27
27
|
import { useRemoteDesktopAvailable } from "@/components/remote-desktop/use-remote-desktop-available";
|
|
28
|
+
import { useOpenAndroid } from "@/components/android/open-android";
|
|
29
|
+
import { useAndroidAvailable } from "@/components/android/use-android-available";
|
|
28
30
|
import { openSettings } from "@/components/settings/open-settings";
|
|
29
31
|
import { FeatureBadge } from "@/components/ui/feature-badge";
|
|
30
32
|
import type { FeatureBadgeId } from "@/lib/feature-badges";
|
|
@@ -84,6 +86,8 @@ export function MobileDrawer({ isOpen, onClose, initialTab }: MobileDrawerProps)
|
|
|
84
86
|
const contributions = useExtensionStore((s) => s.contributions);
|
|
85
87
|
const { available: remoteDesktopAvailable } = useRemoteDesktopAvailable();
|
|
86
88
|
const openRemoteDesktop = useOpenRemoteDesktop();
|
|
89
|
+
const openAndroid = useOpenAndroid();
|
|
90
|
+
const { available: androidAvailable } = useAndroidAvailable();
|
|
87
91
|
const [activeTab, setActiveTab] = useState<SidebarActiveTab>(initialTab ?? "explorer");
|
|
88
92
|
const [cloudOpen, setCloudOpen] = useState(false);
|
|
89
93
|
|
|
@@ -122,6 +126,9 @@ export function MobileDrawer({ isOpen, onClose, initialTab }: MobileDrawerProps)
|
|
|
122
126
|
...(remoteDesktopAvailable
|
|
123
127
|
? [{ icon: MonitorSmartphone, label: "Remote", badge: "remote-desktop", onClick: () => { onClose(); openRemoteDesktop(); } } satisfies FooterTileDef]
|
|
124
128
|
: []),
|
|
129
|
+
...(androidAvailable
|
|
130
|
+
? [{ icon: Smartphone, label: "Android", badge: "android", onClick: () => { onClose(); openAndroid(); } } satisfies FooterTileDef]
|
|
131
|
+
: []),
|
|
125
132
|
{ icon: Cloud, label: "Cloud", onClick: () => setCloudOpen(true) },
|
|
126
133
|
// Also not a sidebar tab — settings open as their own tab here, window on desktop.
|
|
127
134
|
{ icon: Settings, label: "Settings", onClick: () => { onClose(); openSettings(); } },
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { useState, useRef, useEffect, useMemo, memo } from "react";
|
|
2
2
|
import { createPortal } from "react-dom";
|
|
3
|
-
import { Settings, Bug, Cloud, FolderTree, MonitorSmartphone } from "@/lib/icons";
|
|
3
|
+
import { Settings, Bug, Cloud, FolderTree, MonitorSmartphone, Smartphone } from "@/lib/icons";
|
|
4
4
|
import { openExplorer } from "@/components/os-explorer/open-explorer";
|
|
5
5
|
import { useOpenRemoteDesktop } from "@/components/remote-desktop/open-remote-desktop";
|
|
6
6
|
import { useRemoteDesktopAvailable } from "@/components/remote-desktop/use-remote-desktop-available";
|
|
7
|
+
import { useOpenAndroid } from "@/components/android/open-android";
|
|
8
|
+
import { useAndroidAvailable } from "@/components/android/use-android-available";
|
|
7
9
|
import { openSettings } from "@/components/settings/open-settings";
|
|
8
10
|
import { FeatureBadge } from "@/components/ui/feature-badge";
|
|
9
11
|
import type { FeatureBadgeId } from "@/lib/feature-badges";
|
|
@@ -160,6 +162,8 @@ export const NavSectionRail = memo(function NavSectionRail({ className }: { clas
|
|
|
160
162
|
}, []);
|
|
161
163
|
|
|
162
164
|
const openRemoteDesktop = useOpenRemoteDesktop();
|
|
165
|
+
const openAndroid = useOpenAndroid();
|
|
166
|
+
const { available: androidAvailable } = useAndroidAvailable();
|
|
163
167
|
const { available: remoteDesktopAvailable } = useRemoteDesktopAvailable();
|
|
164
168
|
|
|
165
169
|
const handleReportBug = () => openBugReportPopup(version);
|
|
@@ -229,6 +233,9 @@ export const NavSectionRail = memo(function NavSectionRail({ className }: { clas
|
|
|
229
233
|
{remoteDesktopAvailable && (
|
|
230
234
|
<FooterUtil icon={MonitorSmartphone} label="Remote Desktop" featureBadge="remote-desktop" onClick={openRemoteDesktop} />
|
|
231
235
|
)}
|
|
236
|
+
{androidAvailable && (
|
|
237
|
+
<FooterUtil icon={Smartphone} label="Android" featureBadge="android" onClick={openAndroid} />
|
|
238
|
+
)}
|
|
232
239
|
<FooterUtil icon={Bug} label="Report Bug" onClick={handleReportBug} />
|
|
233
240
|
<FooterUtil icon={Settings} label="Settings" onClick={() => openSettings()} />
|
|
234
241
|
</div>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* remount the tab and destroy exactly the state (xterm buffer, Monaco undo stack, chat
|
|
13
13
|
* scroll) this component exists to preserve.
|
|
14
14
|
*/
|
|
15
|
-
import { useLayoutEffect, useRef, Suspense, type
|
|
15
|
+
import { useLayoutEffect, useRef, Suspense, type ComponentType } from "react";
|
|
16
16
|
import { createPortal } from "react-dom";
|
|
17
17
|
import { Loader2 } from "@/lib/icons";
|
|
18
18
|
import { usePanelStore } from "@/stores/panel-store";
|
|
@@ -24,7 +24,7 @@ import { slotRegistry } from "./tab-pool-registry";
|
|
|
24
24
|
export interface ReparentingTabProps {
|
|
25
25
|
tabId: string;
|
|
26
26
|
panelId: string;
|
|
27
|
-
component:
|
|
27
|
+
component: ComponentType<{ metadata?: Record<string, unknown>; tabId?: string }>;
|
|
28
28
|
metadata?: Record<string, unknown>;
|
|
29
29
|
isActive: boolean;
|
|
30
30
|
/** Off-screen parent the wrapper lives in whenever its panel has no slot mounted. */
|
|
@@ -64,6 +64,11 @@ const TAB_COMPONENTS: Record<TabType, React.LazyExoticComponent<React.ComponentT
|
|
|
64
64
|
default: m.ConflictEditor,
|
|
65
65
|
})),
|
|
66
66
|
),
|
|
67
|
+
android: lazy(() =>
|
|
68
|
+
import("@/components/android/android-tab").then((m) => ({
|
|
69
|
+
default: m.AndroidTab,
|
|
70
|
+
})),
|
|
71
|
+
),
|
|
67
72
|
"system-monitor": lazy(() =>
|
|
68
73
|
import("@/components/system/system-monitor-tab").then((m) => ({
|
|
69
74
|
default: m.SystemMonitorTab,
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* ever swaps a wrapper. In exchange React binds its listeners to the wrapper itself, so
|
|
13
13
|
* they travel with the node — including into another document.
|
|
14
14
|
*/
|
|
15
|
-
import { useState, useEffect, useSyncExternalStore
|
|
15
|
+
import { useState, useEffect, useSyncExternalStore } from "react";
|
|
16
16
|
import { usePanelStore } from "@/stores/panel-store";
|
|
17
17
|
import { useMountedTabsStore } from "@/stores/mounted-tabs-store";
|
|
18
18
|
import type { TabType } from "@/stores/tab-store";
|
|
@@ -20,33 +20,44 @@ import { collectTabEntries, filterMountableEntries } from "./tab-pool-collect";
|
|
|
20
20
|
import { slotRegistry } from "./tab-pool-registry";
|
|
21
21
|
import { ReparentingTab } from "./reparenting-tab";
|
|
22
22
|
import { useWindowPanelReconcile } from "./use-window-panel-reconcile";
|
|
23
|
+
import { lazyWithPreload, type PreloadableComponent } from "@/lib/lazy-with-preload";
|
|
23
24
|
|
|
24
25
|
export { registerPanelSlot } from "./tab-pool-registry";
|
|
25
26
|
|
|
26
27
|
// ---------------------------------------------------------------------------
|
|
27
28
|
// Lazy tab components (single source of truth for all tab types)
|
|
28
29
|
// ---------------------------------------------------------------------------
|
|
29
|
-
const TAB_COMPONENTS: Record<TabType,
|
|
30
|
-
terminal:
|
|
31
|
-
chat:
|
|
32
|
-
editor:
|
|
33
|
-
database:
|
|
34
|
-
sqlite:
|
|
35
|
-
postgres:
|
|
36
|
-
"git-diff":
|
|
37
|
-
"branch-review":
|
|
38
|
-
settings:
|
|
39
|
-
extension:
|
|
40
|
-
"extension-webview":
|
|
41
|
-
"conflict-editor":
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
30
|
+
export const TAB_COMPONENTS: Record<TabType, PreloadableComponent<{ metadata?: Record<string, unknown>; tabId?: string }>> = {
|
|
31
|
+
terminal: lazyWithPreload(() => import("@/components/terminal/terminal-tab").then((m) => ({ default: m.TerminalTab }))),
|
|
32
|
+
chat: lazyWithPreload(() => import("@/components/chat/chat-tab").then((m) => ({ default: m.ChatTab }))),
|
|
33
|
+
editor: lazyWithPreload(() => import("@/components/editor/code-editor").then((m) => ({ default: m.CodeEditor }))),
|
|
34
|
+
database: lazyWithPreload(() => import("@/components/database/database-viewer").then((m) => ({ default: m.DatabaseViewer }))),
|
|
35
|
+
sqlite: lazyWithPreload(() => import("@/components/sqlite/sqlite-viewer").then((m) => ({ default: m.SqliteViewer }))),
|
|
36
|
+
postgres: lazyWithPreload(() => import("@/components/postgres/postgres-viewer").then((m) => ({ default: m.PostgresViewer }))),
|
|
37
|
+
"git-diff": lazyWithPreload(() => import("@/components/editor/diff-viewer").then((m) => ({ default: m.DiffViewer }))),
|
|
38
|
+
"branch-review": lazyWithPreload(() => import("@/components/branch-review/branch-review-tab").then((m) => ({ default: m.BranchReviewTab }))),
|
|
39
|
+
settings: lazyWithPreload(() => import("@/components/settings/settings-tab").then((m) => ({ default: m.SettingsTab }))),
|
|
40
|
+
extension: lazyWithPreload(() => import("@/components/extensions/extension-webview").then((m) => ({ default: m.ExtensionWebview }))),
|
|
41
|
+
"extension-webview": lazyWithPreload(() => import("@/components/extensions/extension-webview").then((m) => ({ default: m.ExtensionWebview }))),
|
|
42
|
+
"conflict-editor": lazyWithPreload(() => import("@/components/editor/conflict-editor").then((m) => ({ default: m.ConflictEditor }))),
|
|
43
|
+
android: lazyWithPreload(() => import("@/components/android/android-tab").then((m) => ({ default: m.AndroidTab }))),
|
|
44
|
+
"system-monitor": lazyWithPreload(() => import("@/components/system/system-monitor-tab").then((m) => ({ default: m.SystemMonitorTab }))),
|
|
45
|
+
"git-log": lazyWithPreload(() => import("@/components/git/git-log-panel").then((m) => ({ default: m.GitLogPanel }))),
|
|
46
|
+
"ai-resource": lazyWithPreload(() => import("@/components/ai-resources/ai-resource-editor").then((m) => ({ default: m.AiResourceEditor }))),
|
|
47
|
+
group: lazyWithPreload(() => import("@/components/group-chat/group-chat-tab").then((m) => ({ default: m.GroupChatTab }))),
|
|
48
|
+
problems: lazyWithPreload(() => import("@/components/problems/problems-panel").then((m) => ({ default: m.ProblemsPanel }))),
|
|
49
|
+
design: lazyWithPreload(() => import("@/components/design/design-tab").then((m) => ({ default: m.DesignTab }))),
|
|
48
50
|
};
|
|
49
51
|
|
|
52
|
+
/** The tabs opened most, loaded first by `preloadWhenIdle`. */
|
|
53
|
+
const PRELOAD_FIRST: TabType[] = ["editor", "terminal", "chat", "git-diff", "settings"];
|
|
54
|
+
|
|
55
|
+
/** Every kind of tab's `preload`, the ones opened most first. */
|
|
56
|
+
export function tabPreloads(): Array<() => Promise<void>> {
|
|
57
|
+
const rest = (Object.keys(TAB_COMPONENTS) as TabType[]).filter((type) => !PRELOAD_FIRST.includes(type));
|
|
58
|
+
return [...PRELOAD_FIRST, ...rest].map((type) => TAB_COMPONENTS[type].preload);
|
|
59
|
+
}
|
|
60
|
+
|
|
50
61
|
const HIDDEN_CONTAINER_STYLE: React.CSSProperties = {
|
|
51
62
|
position: "fixed",
|
|
52
63
|
top: 0,
|
|
@@ -33,6 +33,28 @@ export function shouldDecodeAccessUnit(hasSeenKeyframeThisInstance: boolean, isK
|
|
|
33
33
|
return isKey || hasSeenKeyframeThisInstance;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Why `VideoDecoder` is missing — and it is usually not the browser.
|
|
38
|
+
*
|
|
39
|
+
* WebCodecs is **secure-context only**. Measured in one browser at one moment: `VideoDecoder`
|
|
40
|
+
* is `undefined` on `http://192.168.98.96:3210` and present on `http://127.0.0.1:3210`. Since
|
|
41
|
+
* PPM is most often reached over plain HTTP on a LAN — which is exactly how a phone or tablet
|
|
42
|
+
* gets to it — the common case for this message is a perfectly capable browser on an origin
|
|
43
|
+
* the specification excludes, and telling that user to "try Chrome" sends them to fix
|
|
44
|
+
* something that is not broken.
|
|
45
|
+
*
|
|
46
|
+
* Exported for the test; there is no `VideoDecoder` to stub in `bun:test` otherwise.
|
|
47
|
+
*/
|
|
48
|
+
export function missingDecoderReason(
|
|
49
|
+
secureContext: boolean = typeof window !== "undefined" ? window.isSecureContext : true,
|
|
50
|
+
): string {
|
|
51
|
+
return secureContext
|
|
52
|
+
? "This browser has no WebCodecs VideoDecoder — try Chrome, Edge, or Safari 16.4+."
|
|
53
|
+
: "Video needs a secure origin on this transport: browsers only expose WebCodecs over HTTPS "
|
|
54
|
+
+ "or on localhost. Reach PPM through its HTTPS tunnel, or install the WebRTC relay in "
|
|
55
|
+
+ "Settings, which streams over plain HTTP too.";
|
|
56
|
+
}
|
|
57
|
+
|
|
36
58
|
export interface UseH264CanvasDecoderResult {
|
|
37
59
|
status: DecoderStatus;
|
|
38
60
|
errorMessage: string | null;
|
|
@@ -78,7 +100,7 @@ export function useH264CanvasDecoder(
|
|
|
78
100
|
lastCodecRef.current = codec;
|
|
79
101
|
if (typeof VideoDecoder === "undefined") {
|
|
80
102
|
setStatus("unsupported");
|
|
81
|
-
setErrorMessage(
|
|
103
|
+
setErrorMessage(missingDecoderReason());
|
|
82
104
|
return;
|
|
83
105
|
}
|
|
84
106
|
const config: VideoDecoderConfig = { codec, optimizeForLatency: true };
|
|
@@ -19,6 +19,7 @@ import { api } from "@/lib/api-client";
|
|
|
19
19
|
import { useSettingsStore } from "@/stores/settings-store";
|
|
20
20
|
import { resolveRemoteDesktopWsUrl } from "./remote-desktop-ws-url";
|
|
21
21
|
import { useH264CanvasDecoder, type DecoderStatus } from "./use-h264-canvas-decoder";
|
|
22
|
+
import { useWebrtcCanvasVideo } from "./use-webrtc-canvas-video";
|
|
22
23
|
import {
|
|
23
24
|
DEFAULT_PRESET_ID, parsePresetId, type QualityChoice, type QualityPresetId,
|
|
24
25
|
} from "../../../shared/remote-desktop-quality";
|
|
@@ -33,9 +34,24 @@ const PING_INTERVAL_MS = 5_000;
|
|
|
33
34
|
* nonce and its own eviction rules. */
|
|
34
35
|
const FRAME_AUDIO = 2;
|
|
35
36
|
|
|
37
|
+
/** Set once WebRTC could not carry the picture in this tab. Session storage rather than a ref,
|
|
38
|
+
* so a viewer reopened from the same origin does not wait out `CONNECT_DEADLINE_MS` again. */
|
|
39
|
+
const WEBRTC_UNUSABLE_KEY = "ppm.remoteDesktop.webrtcUnusable";
|
|
40
|
+
|
|
41
|
+
function webrtcMarkedUnusable(): boolean {
|
|
42
|
+
try { return sessionStorage.getItem(WEBRTC_UNUSABLE_KEY) === "1"; } catch { return false; }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function markWebrtcUnusable(): void {
|
|
46
|
+
try { sessionStorage.setItem(WEBRTC_UNUSABLE_KEY, "1"); } catch { /* the hook's own ref still holds it */ }
|
|
47
|
+
}
|
|
48
|
+
|
|
36
49
|
export interface UseRemoteDesktopConnectionResult {
|
|
37
50
|
connState: RemoteDesktopConnState;
|
|
38
51
|
errorMessage: string | null;
|
|
52
|
+
/** Which transport is carrying the picture. `webrtc` means the host's relay is in use and
|
|
53
|
+
* this socket carries only control messages. */
|
|
54
|
+
transport: "websocket" | "webrtc";
|
|
39
55
|
decoderStatus: DecoderStatus;
|
|
40
56
|
decoderErrorMessage: string | null;
|
|
41
57
|
sendMessage: (msg: Record<string, unknown>) => void;
|
|
@@ -162,6 +178,23 @@ export function useRemoteDesktopConnection(
|
|
|
162
178
|
const [codec, setCodecState] = useState<string | null>(codecRef.current);
|
|
163
179
|
|
|
164
180
|
const decoder = useH264CanvasDecoder(canvasRef);
|
|
181
|
+
const webrtcUnusableRef = useRef(false);
|
|
182
|
+
/** WebRTC's media is UDP straight to the host's interface addresses, which a viewer on the
|
|
183
|
+
* Cloudflare tunnel has no route to: the handshake goes through and the picture never comes.
|
|
184
|
+
* So a WebRTC that cannot carry it reconnects asking for this socket's stream instead —
|
|
185
|
+
* wherever WebCodecs exists to decode that. On a plain-HTTP origin it does not, and the
|
|
186
|
+
* WebRTC error is the answer: reconnecting would only fail the same way again. */
|
|
187
|
+
const onWebrtcFailure = useCallback(() => {
|
|
188
|
+
if (typeof VideoDecoder === "undefined" || webrtcUnusableRef.current) return;
|
|
189
|
+
webrtcUnusableRef.current = true;
|
|
190
|
+
markWebrtcUnusable();
|
|
191
|
+
setGeneration((g) => g + 1);
|
|
192
|
+
}, []);
|
|
193
|
+
const webrtc = useWebrtcCanvasVideo(canvasRef, { onFailure: onWebrtcFailure });
|
|
194
|
+
/** Which transport is actually carrying the picture. The server decides: it answers with a
|
|
195
|
+
* `webrtc` message only when its relay is installed and came up, and otherwise frames access
|
|
196
|
+
* units onto this socket exactly as before. */
|
|
197
|
+
const [transport, setTransport] = useState<"websocket" | "webrtc">("websocket");
|
|
165
198
|
const audio = useOpusAudioPlayer();
|
|
166
199
|
const [audioOn, setAudioOn] = useState(false);
|
|
167
200
|
const [privacyOn, setPrivacyOn] = useState(false);
|
|
@@ -276,6 +309,8 @@ export function useRemoteDesktopConnection(
|
|
|
276
309
|
let pingTimer: ReturnType<typeof setInterval> | null = null;
|
|
277
310
|
setConnState("connecting");
|
|
278
311
|
setErrorMessage(null);
|
|
312
|
+
// Until the host says otherwise with a `webrtc` message, the picture comes on this socket.
|
|
313
|
+
setTransport("websocket");
|
|
279
314
|
// A fresh session engages nothing, and the old session's grab died with its socket.
|
|
280
315
|
setPrivacyOn(false);
|
|
281
316
|
setPrivacyError(null);
|
|
@@ -306,6 +341,11 @@ export function useRemoteDesktopConnection(
|
|
|
306
341
|
ws.send(JSON.stringify({
|
|
307
342
|
type: "auth", nonce, ...(displayId ? { displayId } : {}), cursor: showCursorRef.current,
|
|
308
343
|
...(codecRef.current ? { codec: codecRef.current } : {}),
|
|
344
|
+
// Asked for until it has failed in this tab (`onWebrtcFailure`); the host grants it
|
|
345
|
+
// only when its relay is installed. There is no setting for this: WebRTC measured
|
|
346
|
+
// better on every axis, and on a plain-HTTP LAN origin the WebCodecs path cannot
|
|
347
|
+
// start at all (`VideoDecoder` is secure-context only).
|
|
348
|
+
webrtc: !(webrtcUnusableRef.current || webrtcMarkedUnusable()),
|
|
309
349
|
}));
|
|
310
350
|
// Re-pin across a reconnect so a deliberate choice is not silently reset to balanced.
|
|
311
351
|
if (pinnedRef.current) ws.send(JSON.stringify(qualityMessage(pinnedRef.current)));
|
|
@@ -315,7 +355,18 @@ export function useRemoteDesktopConnection(
|
|
|
315
355
|
if (typeof event.data === "string") {
|
|
316
356
|
let msg: Record<string, unknown>;
|
|
317
357
|
try { msg = JSON.parse(event.data); } catch { return; }
|
|
318
|
-
if (msg.type === "
|
|
358
|
+
if (msg.type === "webrtc" && typeof msg.whepPath === "string") {
|
|
359
|
+
// Sent on connect and again after any respawn (a quality change restarts the
|
|
360
|
+
// publisher, which drops the browser's reader), so this re-runs the handshake.
|
|
361
|
+
setTransport("webrtc");
|
|
362
|
+
// This message stands in for `config` on the relay transport, so the same state it
|
|
363
|
+
// would have set is applied here — otherwise the quality and codec menus show
|
|
364
|
+
// their defaults instead of what the host is running.
|
|
365
|
+
applyQualityMessage(msg);
|
|
366
|
+
setCodecState(typeof msg.encoder === "string" ? msg.encoder : null);
|
|
367
|
+
webrtc.start(msg.whepPath);
|
|
368
|
+
setConnState("streaming");
|
|
369
|
+
} else if (msg.type === "config" && typeof msg.codec === "string") {
|
|
319
370
|
// A second `config` arrives on every quality change: the new ffmpeg has its own SPS
|
|
320
371
|
// and resolution, and `configure()` closes the old decoder and waits for a keyframe.
|
|
321
372
|
applyQualityMessage(msg);
|
|
@@ -394,24 +445,31 @@ export function useRemoteDesktopConnection(
|
|
|
394
445
|
try { wsRef.current?.close(); } catch { /* tearing down regardless */ }
|
|
395
446
|
wsRef.current = null;
|
|
396
447
|
try { decoder.reset(); } catch { /* tearing down regardless */ }
|
|
448
|
+
try { webrtc.stop(); } catch { /* tearing down regardless */ }
|
|
397
449
|
try { audio.reset(); } catch { /* tearing down regardless */ }
|
|
398
450
|
};
|
|
399
451
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- reconnect is driven by `generation` + the display pick
|
|
400
452
|
}, [generation, displayId]);
|
|
401
453
|
|
|
402
454
|
const reconnect = useCallback(() => setGeneration((g) => g + 1), []);
|
|
403
|
-
|
|
455
|
+
// On the relay transport no video crosses this socket, so the byte counter that feeds the
|
|
456
|
+
// KB/s stat has to come from WebRTC's own inbound-rtp report instead.
|
|
457
|
+
const getTotalBytes = useCallback(
|
|
458
|
+
() => (transport === "webrtc" ? webrtc.getTotalBytes() : totalBytesRef.current),
|
|
459
|
+
[transport, webrtc],
|
|
460
|
+
);
|
|
404
461
|
|
|
405
462
|
return {
|
|
406
463
|
connState,
|
|
407
464
|
errorMessage,
|
|
408
|
-
|
|
409
|
-
|
|
465
|
+
transport,
|
|
466
|
+
decoderStatus: transport === "webrtc" ? webrtc.status : decoder.status,
|
|
467
|
+
decoderErrorMessage: transport === "webrtc" ? webrtc.errorMessage : decoder.errorMessage,
|
|
410
468
|
sendMessage,
|
|
411
469
|
reconnect,
|
|
412
470
|
getTotalBytes,
|
|
413
|
-
getFrameCount: decoder.getFrameCount,
|
|
414
|
-
frameSize: decoder.frameSize,
|
|
471
|
+
getFrameCount: transport === "webrtc" ? webrtc.getFrameCount : decoder.getFrameCount,
|
|
472
|
+
frameSize: transport === "webrtc" ? webrtc.frameSize : decoder.frameSize,
|
|
415
473
|
quality,
|
|
416
474
|
setQuality,
|
|
417
475
|
setCustomQuality,
|