@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
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `/ws/android` wire format, version 1. Shared by `src/server/ws/android.ts` and the
|
|
3
|
+
* browser viewer so neither can drift from the other.
|
|
4
|
+
*
|
|
5
|
+
* Text frames are JSON control messages; binary frames are video. Video never travels as
|
|
6
|
+
* base64 inside JSON — that is a 33% tax on the one thing that has a bandwidth budget.
|
|
7
|
+
*
|
|
8
|
+
* Two generations ride on every message, and they answer different questions:
|
|
9
|
+
* - `sessionGeneration` changes when control moves to another client (a Take control). It is
|
|
10
|
+
* what lets the server drop input from a client that has been superseded but does not yet
|
|
11
|
+
* know it.
|
|
12
|
+
* - `geometryGeneration` changes when the frame size or rotation changes. Input carrying an
|
|
13
|
+
* old geometry describes a screen that no longer exists, so it is rejected rather than
|
|
14
|
+
* mapped onto the new one — the plan's "Reject input theo geometry cũ".
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export const ANDROID_PROTOCOL_VERSION = 1;
|
|
18
|
+
|
|
19
|
+
// ---------------------------------------------------------------------------------------------
|
|
20
|
+
// Binary video framing
|
|
21
|
+
// ---------------------------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Header laid out little-endian, then the Annex-B payload:
|
|
25
|
+
*
|
|
26
|
+
* 0 u8 protocol version
|
|
27
|
+
* 1 u8 flags (bit0 = keyframe, bit1 = codec config)
|
|
28
|
+
* 2 u16 session generation
|
|
29
|
+
* 4 u16 geometry generation
|
|
30
|
+
* 6 u32 sequence number
|
|
31
|
+
* 10 f64 presentation timestamp, milliseconds since the session began
|
|
32
|
+
* 18 u32 payload length
|
|
33
|
+
* 22 ... payload
|
|
34
|
+
*
|
|
35
|
+
* The length is carried even though a WS frame already delimits itself, because a proxy that
|
|
36
|
+
* coalesces or splits frames would otherwise be undetectable — a truncated access unit decodes
|
|
37
|
+
* to garbage rather than failing.
|
|
38
|
+
*/
|
|
39
|
+
export const VIDEO_HEADER_BYTES = 22;
|
|
40
|
+
|
|
41
|
+
export const VIDEO_FLAG_KEYFRAME = 1 << 0;
|
|
42
|
+
export const VIDEO_FLAG_CODEC_CONFIG = 1 << 1;
|
|
43
|
+
|
|
44
|
+
export interface VideoFrameHeader {
|
|
45
|
+
version: number;
|
|
46
|
+
keyframe: boolean;
|
|
47
|
+
codecConfig: boolean;
|
|
48
|
+
sessionGeneration: number;
|
|
49
|
+
geometryGeneration: number;
|
|
50
|
+
sequence: number;
|
|
51
|
+
ptsMs: number;
|
|
52
|
+
payloadLength: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function encodeVideoFrame(header: Omit<VideoFrameHeader, "version" | "payloadLength">, payload: Uint8Array): Uint8Array {
|
|
56
|
+
const out = new Uint8Array(VIDEO_HEADER_BYTES + payload.length);
|
|
57
|
+
const view = new DataView(out.buffer);
|
|
58
|
+
view.setUint8(0, ANDROID_PROTOCOL_VERSION);
|
|
59
|
+
view.setUint8(1, (header.keyframe ? VIDEO_FLAG_KEYFRAME : 0) | (header.codecConfig ? VIDEO_FLAG_CODEC_CONFIG : 0));
|
|
60
|
+
view.setUint16(2, header.sessionGeneration, true);
|
|
61
|
+
view.setUint16(4, header.geometryGeneration, true);
|
|
62
|
+
view.setUint32(6, header.sequence, true);
|
|
63
|
+
view.setFloat64(10, header.ptsMs, true);
|
|
64
|
+
view.setUint32(18, payload.length, true);
|
|
65
|
+
out.set(payload, VIDEO_HEADER_BYTES);
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Returns null when the buffer is too short or the declared length disagrees with what arrived. */
|
|
70
|
+
export function decodeVideoFrame(buf: ArrayBuffer | Uint8Array): { header: VideoFrameHeader; payload: Uint8Array } | null {
|
|
71
|
+
const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
|
|
72
|
+
if (bytes.length < VIDEO_HEADER_BYTES) return null;
|
|
73
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
74
|
+
const flags = view.getUint8(1);
|
|
75
|
+
const payloadLength = view.getUint32(18, true);
|
|
76
|
+
if (bytes.length - VIDEO_HEADER_BYTES !== payloadLength) return null;
|
|
77
|
+
return {
|
|
78
|
+
header: {
|
|
79
|
+
version: view.getUint8(0),
|
|
80
|
+
keyframe: (flags & VIDEO_FLAG_KEYFRAME) !== 0,
|
|
81
|
+
codecConfig: (flags & VIDEO_FLAG_CODEC_CONFIG) !== 0,
|
|
82
|
+
sessionGeneration: view.getUint16(2, true),
|
|
83
|
+
geometryGeneration: view.getUint16(4, true),
|
|
84
|
+
sequence: view.getUint32(6, true),
|
|
85
|
+
ptsMs: view.getFloat64(10, true),
|
|
86
|
+
payloadLength,
|
|
87
|
+
},
|
|
88
|
+
payload: bytes.subarray(VIDEO_HEADER_BYTES),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ---------------------------------------------------------------------------------------------
|
|
93
|
+
// Control messages
|
|
94
|
+
// ---------------------------------------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
export interface AndroidGeometry {
|
|
97
|
+
/** Frame size actually being encoded. */
|
|
98
|
+
width: number;
|
|
99
|
+
height: number;
|
|
100
|
+
/** The guest's own display size, which the frame may be a scaled copy of. */
|
|
101
|
+
deviceWidth: number;
|
|
102
|
+
deviceHeight: number;
|
|
103
|
+
rotation: 0 | 90 | 180 | 270;
|
|
104
|
+
generation: number;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export type AndroidQuality = "low" | "balanced" | "high";
|
|
108
|
+
|
|
109
|
+
/** Client -> server. */
|
|
110
|
+
export type AndroidClientMessage =
|
|
111
|
+
| { type: "auth"; nonce: string; quality?: AndroidQuality; viewport?: { width: number; height: number } }
|
|
112
|
+
| { type: "touch"; geometryGeneration: number; touches: AndroidTouchPoint[] }
|
|
113
|
+
| { type: "key"; geometryGeneration: number; key: string; action: "down" | "up" | "press" }
|
|
114
|
+
/** ASCII only. Anything outside [32,127) is dropped by the emulator *silently* — measured —
|
|
115
|
+
* so the viewer must route non-ASCII through `paste` instead. */
|
|
116
|
+
| { type: "text"; text: string }
|
|
117
|
+
/** The path for Vietnamese, emoji and CJK: set the guest clipboard, then send the paste combo. */
|
|
118
|
+
| { type: "paste"; text: string }
|
|
119
|
+
| { type: "hardware"; key: "home" | "back" | "recent" | "power" | "volume-up" | "volume-down" }
|
|
120
|
+
| { type: "rotate"; rotation: 0 | 90 | 180 | 270 }
|
|
121
|
+
| { type: "quality"; quality: AndroidQuality }
|
|
122
|
+
| { type: "visibility"; visible: boolean }
|
|
123
|
+
| { type: "input-reset" }
|
|
124
|
+
| { type: "take-control" }
|
|
125
|
+
/** Subscribing starts the device's logcat stream; unsubscribing stops it when nobody is left,
|
|
126
|
+
* which is the plan's "logs hidden ngừng subscription". */
|
|
127
|
+
| { type: "logcat"; subscribe: boolean }
|
|
128
|
+
| { type: "heartbeat" };
|
|
129
|
+
|
|
130
|
+
// ---------------------------------------------------------------------------------------------
|
|
131
|
+
// Logcat
|
|
132
|
+
// ---------------------------------------------------------------------------------------------
|
|
133
|
+
|
|
134
|
+
export type AndroidLogLevel = "verbose" | "debug" | "info" | "warn" | "error" | "fatal";
|
|
135
|
+
|
|
136
|
+
export interface AndroidLogEntry {
|
|
137
|
+
/** Monotonic within one device stream, so the viewer can key rows and drop duplicates. */
|
|
138
|
+
id: number;
|
|
139
|
+
/** Unix milliseconds, as the emulator reports them. */
|
|
140
|
+
timestamp: number;
|
|
141
|
+
pid: number;
|
|
142
|
+
tid: number;
|
|
143
|
+
level: AndroidLogLevel;
|
|
144
|
+
tag: string;
|
|
145
|
+
message: string;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface AndroidTouchPoint {
|
|
149
|
+
/** Frame coordinates, not CSS pixels. The viewer maps before sending. */
|
|
150
|
+
x: number;
|
|
151
|
+
y: number;
|
|
152
|
+
/** Stable for the life of one finger. */
|
|
153
|
+
id: number;
|
|
154
|
+
/** 0 releases the finger. The emulator will not free a slot until it sees one. */
|
|
155
|
+
pressure: number;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Server -> client. */
|
|
159
|
+
export type AndroidServerMessage =
|
|
160
|
+
/** `codec` is the WebCodecs `avc1.PPCCLL` string derived from the real SPS, and is null until
|
|
161
|
+
* the encoder has emitted its first keyframe — a `codec` message follows when it has.
|
|
162
|
+
* `encoder` is the ffmpeg encoder's name, for display only. */
|
|
163
|
+
| { type: "ready"; sessionId: string; sessionGeneration: number; geometry: AndroidGeometry; controller: boolean; codec: string | null; encoder: string }
|
|
164
|
+
/** Sent whenever the bitstream's profile/level changes — first keyframe, a rung switch, a
|
|
165
|
+
* rotation. Never guessed: `encoderArgs` sets no `-profile`/`-level`, so it is encoder-default
|
|
166
|
+
* and unknown until the bitstream exists, and a wrong string makes `configure()` throw. */
|
|
167
|
+
| { type: "codec"; codec: string }
|
|
168
|
+
| { type: "geometry"; geometry: AndroidGeometry }
|
|
169
|
+
| { type: "controller"; controller: boolean; reason?: string }
|
|
170
|
+
| { type: "quality"; quality: AndroidQuality }
|
|
171
|
+
| { type: "status"; booted: boolean; detail?: string }
|
|
172
|
+
/** A batch of log lines. The first batch after subscribing is the server's ring buffer, so a
|
|
173
|
+
* panel opened on a device that has been up for an hour is not empty. */
|
|
174
|
+
| { type: "log"; entries: AndroidLogEntry[] }
|
|
175
|
+
| { type: "error"; message: string; fatal?: boolean }
|
|
176
|
+
| { type: "heartbeat" };
|
|
177
|
+
|
|
178
|
+
/** Quality rungs. Height is a **ceiling**: a rung taller than the guest never upscales, which
|
|
179
|
+
* would spend the whole budget on interpolated pixels. */
|
|
180
|
+
export const ANDROID_QUALITY_PRESETS: Record<AndroidQuality, { maxHeight: number; fps: number; bitrate: string }> = {
|
|
181
|
+
low: { maxHeight: 720, fps: 24, bitrate: "1.5M" },
|
|
182
|
+
balanced: { maxHeight: 1280, fps: 30, bitrate: "4M" },
|
|
183
|
+
high: { maxHeight: 1920, fps: 30, bitrate: "8M" },
|
|
184
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a project's file list is searched: in the browser, or on the server where it is held.
|
|
3
|
+
*
|
|
4
|
+
* Shared because both ends act on the same number: the browser asks for the list only up to it,
|
|
5
|
+
* and the index worker keeps a list that long ready to search.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* From this many entries a list is searched on the server instead of being sent to the browser.
|
|
10
|
+
* nxsys-workspace's 175k entries are a 22 MB download that took 39 ms to parse and 19–85 ms per
|
|
11
|
+
* keystroke to search on a desktop, measured in Bun — several times that on a phone. Below it
|
|
12
|
+
* the list is sent once and searched locally, with no round trip per keystroke.
|
|
13
|
+
*/
|
|
14
|
+
export const REMOTE_FILE_SEARCH_FROM_ENTRIES = 50_000;
|
|
15
|
+
|
|
16
|
+
/** How many ranked entries a server-side search sends back; the palette shows 100. */
|
|
17
|
+
export const REMOTE_FILE_SEARCH_LIMIT = 100;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shapes shared by the session trace's writers: the server (agent runs) and the browser
|
|
3
|
+
* (`POST /api/trace`). See `docs/architecture/plugins-and-tracing.md`.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Who wrote a row: a provider's stream, PPM itself (inputs, outcomes), or a browser tab. */
|
|
7
|
+
export type TraceSource = "agent" | "server" | "browser";
|
|
8
|
+
|
|
9
|
+
/** Which door a run came through. The browser path is `ws`; `browser` is only for client rows. */
|
|
10
|
+
export type TraceOrigin =
|
|
11
|
+
| "ws"
|
|
12
|
+
| "scheduler"
|
|
13
|
+
| "ppmbot"
|
|
14
|
+
| "group-chat"
|
|
15
|
+
| "jira"
|
|
16
|
+
| "cli"
|
|
17
|
+
| "proxy"
|
|
18
|
+
| "browser"
|
|
19
|
+
| "unknown";
|
|
20
|
+
|
|
21
|
+
/** Most entries one `POST /api/trace` may carry; a larger batch is refused whole. */
|
|
22
|
+
export const TRACE_INGEST_MAX_BATCH = 50;
|
|
23
|
+
|
|
24
|
+
/** Largest serialised payload one browser entry may carry; a larger entry is dropped. */
|
|
25
|
+
export const TRACE_INGEST_MAX_PAYLOAD_BYTES = 16 * 1024;
|
|
26
|
+
|
|
27
|
+
/** A device id as `device-id.ts` mints it (a UUID) — anything else is refused. */
|
|
28
|
+
export const TRACE_DEVICE_ID_RE = /^[A-Za-z0-9-]{8,64}$/;
|
|
29
|
+
|
|
30
|
+
/** Row types a browser may write. Anything else in a batch is dropped. */
|
|
31
|
+
export const BROWSER_TRACE_TYPES = [
|
|
32
|
+
"console_log",
|
|
33
|
+
"console_info",
|
|
34
|
+
"console_debug",
|
|
35
|
+
"console_warn",
|
|
36
|
+
"console_error",
|
|
37
|
+
"browser_error",
|
|
38
|
+
"unhandled_rejection",
|
|
39
|
+
"render_error",
|
|
40
|
+
"chunk_error",
|
|
41
|
+
"entry_never_ran",
|
|
42
|
+
"console_dropped",
|
|
43
|
+
] as const;
|
|
44
|
+
|
|
45
|
+
export type BrowserTraceType = (typeof BROWSER_TRACE_TYPES)[number];
|
|
46
|
+
|
|
47
|
+
export interface BrowserTraceEntry {
|
|
48
|
+
/** The browser's clock when it happened; the server corrects it by `sentAt`. */
|
|
49
|
+
ts: number;
|
|
50
|
+
type: BrowserTraceType;
|
|
51
|
+
/** The chat session the tab was showing, so the row joins that session's trace. */
|
|
52
|
+
refId: string | null;
|
|
53
|
+
payload: Record<string, unknown>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface BrowserTraceBatch {
|
|
57
|
+
deviceId: string;
|
|
58
|
+
/** The browser's clock at send time, so a skewed clock can be corrected. */
|
|
59
|
+
sentAt: number;
|
|
60
|
+
entries: BrowserTraceEntry[];
|
|
61
|
+
}
|
package/src/types/chat.ts
CHANGED
|
@@ -64,6 +64,8 @@ export interface AIProvider {
|
|
|
64
64
|
): AsyncIterable<ChatEvent>;
|
|
65
65
|
|
|
66
66
|
// Optional capabilities — providers implement what they support
|
|
67
|
+
/** Start the process a chat about to be created will run on, ahead of its first message. */
|
|
68
|
+
prewarm?(input: PrewarmInput): Promise<void>;
|
|
67
69
|
resolveApproval?(requestId: string, approved: boolean, data?: unknown): void;
|
|
68
70
|
onToolApproval?: (callback: ToolApprovalHandler) => void;
|
|
69
71
|
abortQuery?(sessionId: string, source?: string): void;
|
|
@@ -117,6 +119,21 @@ export interface SessionConfig {
|
|
|
117
119
|
projectName?: string;
|
|
118
120
|
projectPath?: string;
|
|
119
121
|
title?: string;
|
|
122
|
+
/**
|
|
123
|
+
* Take the CLI `prewarm` started in this project, if one is waiting. Only the new-chat
|
|
124
|
+
* route asks: a scheduled run or a bot taking it would leave the tab it was started for
|
|
125
|
+
* to boot one of its own.
|
|
126
|
+
*/
|
|
127
|
+
adoptWarmSpare?: boolean;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** What `prewarm` needs to start the CLI a new chat's first message will run on. */
|
|
131
|
+
export interface PrewarmInput {
|
|
132
|
+
projectPath: string;
|
|
133
|
+
/** The account the new-chat tab claimed, which its session will be bound to. */
|
|
134
|
+
accountId?: string;
|
|
135
|
+
/** The per-session picks the first message will carry. */
|
|
136
|
+
opts?: Pick<SendMessageOpts, "permissionMode" | "model" | "effort" | "thinkingBudget">;
|
|
120
137
|
}
|
|
121
138
|
|
|
122
139
|
export interface ProjectTag {
|
package/src/types/config.ts
CHANGED
|
@@ -23,6 +23,20 @@ export interface ThemeConfig {
|
|
|
23
23
|
customThemeId?: string;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
export interface AndroidConfig {
|
|
27
|
+
/** SDK root the user picked. Empty/absent = discover it (env, then the per-OS default). */
|
|
28
|
+
sdk_root?: string;
|
|
29
|
+
/** How many emulators PPM may have running at once. Plan §1 keeps this at 1 by default:
|
|
30
|
+
* each one costs gigabytes of host RAM, and two is the design test rather than the target. */
|
|
31
|
+
max_concurrent?: number;
|
|
32
|
+
/** Window mode for emulators PPM starts. `no-window` needs no display; `qt-hide-window`
|
|
33
|
+
* creates a hidden Qt window and therefore needs one. */
|
|
34
|
+
window_mode?: "no-window" | "qt-hide-window" | "window";
|
|
35
|
+
/** `-gpu` argument. Left unset the emulator picks; `swiftshader_indirect` is the safe
|
|
36
|
+
* software fallback on a host with no usable GPU for the guest. */
|
|
37
|
+
gpu_mode?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
26
40
|
export interface PpmConfig {
|
|
27
41
|
device_name: string;
|
|
28
42
|
port: number;
|
|
@@ -35,7 +49,9 @@ export interface PpmConfig {
|
|
|
35
49
|
clawbot?: PPMBotConfig;
|
|
36
50
|
cloud_url?: string;
|
|
37
51
|
query_audit: QueryAuditConfig;
|
|
52
|
+
session_trace: SessionTraceConfig;
|
|
38
53
|
tunnel: TunnelConfig;
|
|
54
|
+
android?: AndroidConfig;
|
|
39
55
|
}
|
|
40
56
|
|
|
41
57
|
/**
|
|
@@ -69,6 +85,13 @@ export interface QueryAuditConfig {
|
|
|
69
85
|
max_size_mb: number;
|
|
70
86
|
}
|
|
71
87
|
|
|
88
|
+
export interface SessionTraceConfig {
|
|
89
|
+
/** Rows older than this are pruned. */
|
|
90
|
+
retention_days: number;
|
|
91
|
+
/** Hard ceiling for session-trace.db; oldest rows go first once it is hit. */
|
|
92
|
+
max_size_mb: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
72
95
|
export interface AuthConfig {
|
|
73
96
|
enabled: boolean;
|
|
74
97
|
token: string;
|
|
@@ -171,6 +194,10 @@ export const DEFAULT_CONFIG: PpmConfig = {
|
|
|
171
194
|
retention_days: 30,
|
|
172
195
|
max_size_mb: 500,
|
|
173
196
|
},
|
|
197
|
+
session_trace: {
|
|
198
|
+
retention_days: 30,
|
|
199
|
+
max_size_mb: 500,
|
|
200
|
+
},
|
|
174
201
|
telegram: {
|
|
175
202
|
bot_token: "",
|
|
176
203
|
},
|
package/src/types/project.ts
CHANGED
|
@@ -31,6 +31,15 @@ export interface FileEntry {
|
|
|
31
31
|
isIgnored?: boolean;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* `/files/index?max=` for a project holding more entries than `max`: too long to send, so it is
|
|
36
|
+
* searched with `/files/index/search` instead.
|
|
37
|
+
*/
|
|
38
|
+
export interface FileIndexTooLarge {
|
|
39
|
+
tooLarge: true;
|
|
40
|
+
count: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
34
43
|
/** Entry returned by /files/list (single directory level) */
|
|
35
44
|
export interface FileDirEntry {
|
|
36
45
|
name: string;
|
package/src/web/app.tsx
CHANGED
|
@@ -29,6 +29,7 @@ import { useWakeLock } from "@/hooks/use-wake-lock";
|
|
|
29
29
|
import { WakeLockMobileBadge } from "@/components/layout/wake-lock-indicator";
|
|
30
30
|
import { useTabPrefetch } from "@/hooks/use-tab-prefetch";
|
|
31
31
|
import { useFileIndexInvalidation } from "@/hooks/use-file-index-invalidation";
|
|
32
|
+
import { useUiPreload } from "@/hooks/use-ui-preload";
|
|
32
33
|
import { useGlobalEvents } from "@/hooks/use-global-events";
|
|
33
34
|
import { useServerReload } from "@/hooks/use-server-reload";
|
|
34
35
|
import { CommandPalette } from "@/components/layout/command-palette";
|
|
@@ -151,6 +152,10 @@ export function App() {
|
|
|
151
152
|
// lazily, so this trades a little background work for instant tab switching.
|
|
152
153
|
useTabPrefetch();
|
|
153
154
|
|
|
155
|
+
// Load every tab's and window's code during idle time (desktop or Wi-Fi), so the
|
|
156
|
+
// first one of each kind opens without waiting on its chunk or a spinner.
|
|
157
|
+
useUiPreload(authState === "authenticated");
|
|
158
|
+
|
|
154
159
|
// Warn before closing browser tab (prevents accidental Ctrl+W)
|
|
155
160
|
useEffect(() => {
|
|
156
161
|
if (authState !== "authenticated") return;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Uploading an APK with progress and a working cancel.
|
|
3
|
+
*
|
|
4
|
+
* `fetch` has no upload progress — `ReadableStream` request bodies do exist but need HTTP/2 and
|
|
5
|
+
* a `duplex` option that PPM's usual plain-HTTP LAN deployment cannot rely on, and even then
|
|
6
|
+
* nothing reports how far the send has got. `XMLHttpRequest.upload.onprogress` does, and
|
|
7
|
+
* `xhr.abort()` really stops the send rather than only dropping the response. So this is the one
|
|
8
|
+
* place in the Android client that is not on the api client.
|
|
9
|
+
*
|
|
10
|
+
* It is kept out of the component so the URL it builds and the way it reads an error can be
|
|
11
|
+
* unit-tested; a component here cannot be imported under `bun:test` (the stores read
|
|
12
|
+
* `localStorage` at module scope).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export interface ApkUploadOptions {
|
|
16
|
+
deviceId: string;
|
|
17
|
+
file: File;
|
|
18
|
+
allowDowngrade?: boolean;
|
|
19
|
+
token: string | null;
|
|
20
|
+
onProgress?: (fraction: number) => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ApkUploadHandle {
|
|
24
|
+
/** Resolves with the operation id the server started for the install itself. */
|
|
25
|
+
done: Promise<string>;
|
|
26
|
+
cancel(): void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function apkUploadUrl(deviceId: string, filename: string, allowDowngrade: boolean): string {
|
|
30
|
+
const params = new URLSearchParams({ filename });
|
|
31
|
+
if (allowDowngrade) params.set("downgrade", "1");
|
|
32
|
+
return `/api/android/devices/${encodeURIComponent(deviceId)}/apk?${params.toString()}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** PPM's envelope is `{ok, data}` / `{ok:false, error}`; a proxy's 502 page is neither. */
|
|
36
|
+
export function readUploadResponse(status: number, body: string): { operationId: string } {
|
|
37
|
+
let parsed: unknown = null;
|
|
38
|
+
try { parsed = JSON.parse(body); } catch { /* not JSON at all */ }
|
|
39
|
+
const envelope = parsed as { ok?: boolean; error?: string; data?: { operationId?: string } } | null;
|
|
40
|
+
if (status >= 200 && status < 300 && envelope?.ok && envelope.data?.operationId) {
|
|
41
|
+
return { operationId: envelope.data.operationId };
|
|
42
|
+
}
|
|
43
|
+
throw new Error(envelope?.error ?? (body.trim() || `the upload failed with HTTP ${status}`));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function uploadApk(opts: ApkUploadOptions): ApkUploadHandle {
|
|
47
|
+
const xhr = new XMLHttpRequest();
|
|
48
|
+
let cancelled = false;
|
|
49
|
+
|
|
50
|
+
const done = new Promise<string>((resolve, reject) => {
|
|
51
|
+
xhr.open("POST", apkUploadUrl(opts.deviceId, opts.file.name, opts.allowDowngrade === true));
|
|
52
|
+
if (opts.token) xhr.setRequestHeader("Authorization", `Bearer ${opts.token}`);
|
|
53
|
+
xhr.setRequestHeader("Content-Type", "application/vnd.android.package-archive");
|
|
54
|
+
xhr.setRequestHeader("x-ppm-client", "web");
|
|
55
|
+
|
|
56
|
+
xhr.upload.onprogress = (e) => {
|
|
57
|
+
if (e.lengthComputable && opts.onProgress) opts.onProgress(e.loaded / e.total);
|
|
58
|
+
};
|
|
59
|
+
xhr.onload = () => {
|
|
60
|
+
try { resolve(readUploadResponse(xhr.status, xhr.responseText).operationId); } catch (e) { reject(e); }
|
|
61
|
+
};
|
|
62
|
+
xhr.onerror = () => reject(new Error("the upload could not reach the server"));
|
|
63
|
+
xhr.onabort = () => reject(new Error("cancelled"));
|
|
64
|
+
xhr.send(opts.file);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
done,
|
|
69
|
+
cancel() {
|
|
70
|
+
if (cancelled) return;
|
|
71
|
+
cancelled = true;
|
|
72
|
+
xhr.abort();
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|