@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
|
@@ -3,19 +3,21 @@ import { useProjectStore } from "@/stores/project-store";
|
|
|
3
3
|
import { useFileStore, relativeProjectPath } from "@/stores/file-store";
|
|
4
4
|
import { onFsChanged } from "@/components/os-explorer/explorer-store";
|
|
5
5
|
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Keep on-demand indexes fresh even while the mobile file drawer is closed. A change only marks
|
|
8
|
+
* the index stale — it is refetched when something opens to read it, see `indexStale`.
|
|
9
|
+
*/
|
|
7
10
|
export function useFileIndexInvalidation(): void {
|
|
8
11
|
useEffect(() => {
|
|
9
12
|
const changed = (event: Event) => {
|
|
10
13
|
const projectName = (event as CustomEvent).detail?.projectName;
|
|
11
|
-
|
|
12
|
-
if (projectName && projectName === store.indexProjectName) store.invalidateIndex();
|
|
14
|
+
if (typeof projectName === "string") useFileStore.getState().markIndexStale(projectName);
|
|
13
15
|
};
|
|
14
16
|
window.addEventListener("file:changed", changed);
|
|
15
17
|
const unsubscribeFs = onFsChanged((directory) => {
|
|
16
18
|
const store = useFileStore.getState();
|
|
17
|
-
const project = useProjectStore.getState().projects.find((p) => p.name === store.
|
|
18
|
-
if (project && relativeProjectPath(project.path, directory) !== null) store.
|
|
19
|
+
const project = useProjectStore.getState().projects.find((p) => p.name === store.indexProject);
|
|
20
|
+
if (project && relativeProjectPath(project.path, directory) !== null) store.markIndexStale(project.name);
|
|
19
21
|
});
|
|
20
22
|
const unsubscribeProject = useProjectStore.subscribe((state, previous) => {
|
|
21
23
|
if (state.activeProject?.name !== previous.activeProject?.name) useFileStore.getState().reset();
|
|
@@ -3,6 +3,7 @@ import { WsClient } from "@/lib/ws-client";
|
|
|
3
3
|
import { getAuthToken } from "@/lib/api-client";
|
|
4
4
|
import { useNotificationStore } from "@/stores/notification-store";
|
|
5
5
|
import { useStreamingStore } from "@/stores/streaming-store";
|
|
6
|
+
import { useFileStore } from "@/stores/file-store";
|
|
6
7
|
import { syncRunningSessions } from "@/lib/sync-running-sessions";
|
|
7
8
|
import { syncAllKnownProjects } from "@/stores/session-list-sync-triggers";
|
|
8
9
|
import { notifyGlobalReady, sendIfOpen, setGlobalWsClient } from "@/lib/global-ws-channel";
|
|
@@ -23,7 +24,11 @@ const IDLE_TIMEOUT_MS = 45_000;
|
|
|
23
24
|
*
|
|
24
25
|
* Handles:
|
|
25
26
|
* - `file:changed` → re-dispatched as a window event for the editor, previews and
|
|
26
|
-
* file tree to consume.
|
|
27
|
+
* file tree to consume, and marks the file index stale.
|
|
28
|
+
* - `files:index-changed` → marks the file index stale: the server rebuilt it behind the list
|
|
29
|
+
* it had been serving, and the paths differ. Neither event fetches the index — on a large
|
|
30
|
+
* project that is a 22 MB download — unless something is showing it right now (the palette,
|
|
31
|
+
* a picker; see `openIndexReader`); otherwise it is refreshed when something opens to read it.
|
|
27
32
|
* - `session:unread_changed` → cross-device unread sync.
|
|
28
33
|
* - `session:phase_changed` → keeps the tab-strip spinner and title indicator
|
|
29
34
|
* correct for sessions whose tab is not mounted, and — critically — clears them
|
|
@@ -94,10 +99,16 @@ export function useGlobalEvents(enabled: boolean, projectName?: string): void {
|
|
|
94
99
|
}
|
|
95
100
|
|
|
96
101
|
if (type === "file:changed") {
|
|
102
|
+
if (typeof data.projectName === "string") useFileStore.getState().markIndexStale(data.projectName);
|
|
97
103
|
window.dispatchEvent(new CustomEvent("file:changed", { detail: data }));
|
|
98
104
|
return;
|
|
99
105
|
}
|
|
100
106
|
|
|
107
|
+
if (type === "files:index-changed") {
|
|
108
|
+
if (typeof data.projectName === "string") useFileStore.getState().indexRebuilt(data.projectName);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
101
112
|
if (type === "session:unread_changed") {
|
|
102
113
|
const d = data as unknown as {
|
|
103
114
|
sessionId: string; unreadCount: number; unreadType: string | null;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The best entries of a project whose file list is too long to send to the browser
|
|
3
|
+
* (`indexRemote`), searched on the server for `query` — for the palette and the pickers, which
|
|
4
|
+
* would otherwise filter `fileIndex` themselves. They still rank what comes back as they rank a
|
|
5
|
+
* list they hold; the server only saves them from holding 175k entries to find the best 100.
|
|
6
|
+
*
|
|
7
|
+
* What was last answered stays until the next answer lands, so typing does not blank the list,
|
|
8
|
+
* and it asks again whenever an index lands (`indexRevision`) — the server's list moved.
|
|
9
|
+
*/
|
|
10
|
+
import { useEffect, useState } from "react";
|
|
11
|
+
import { api, projectUrl } from "@/lib/api-client";
|
|
12
|
+
import { useFileStore } from "@/stores/file-store";
|
|
13
|
+
import { REMOTE_FILE_SEARCH_LIMIT } from "../../shared/file-index-limits";
|
|
14
|
+
import type { FileEntry } from "../../types/project";
|
|
15
|
+
|
|
16
|
+
const NONE: FileEntry[] = [];
|
|
17
|
+
|
|
18
|
+
export function useRemoteFileSearch(
|
|
19
|
+
projectName: string | null | undefined,
|
|
20
|
+
query: string,
|
|
21
|
+
{ enabled, kind = "file" }: { enabled: boolean; kind?: "file" | "all" },
|
|
22
|
+
): FileEntry[] {
|
|
23
|
+
const revision = useFileStore((s) => s.indexRevision);
|
|
24
|
+
const [files, setFiles] = useState<FileEntry[]>(NONE);
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (!enabled || !projectName) {
|
|
28
|
+
setFiles(NONE);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const controller = new AbortController();
|
|
32
|
+
const params = new URLSearchParams({ q: query, kind, limit: String(REMOTE_FILE_SEARCH_LIMIT) });
|
|
33
|
+
api.get<FileEntry[]>(`${projectUrl(projectName)}/files/index/search?${params}`, { signal: controller.signal })
|
|
34
|
+
.then(setFiles, () => { /* superseded by the next keystroke, or failed: keep what is shown */ });
|
|
35
|
+
return () => controller.abort();
|
|
36
|
+
}, [projectName, query, enabled, kind, revision]);
|
|
37
|
+
|
|
38
|
+
return files;
|
|
39
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import { tabPreloads } from "@/components/layout/tab-pool";
|
|
3
|
+
import { WINDOW_CONTENT } from "@/components/floating-window/window-content-registry";
|
|
4
|
+
import { isTouchOnlyDevice } from "@/hooks/use-is-touch-only";
|
|
5
|
+
import { preloadWhenIdle, shouldPreloadUi, type ConnectionHints } from "@/lib/preload-ui";
|
|
6
|
+
|
|
7
|
+
/** The head start the tabs a workspace restores get, as in `use-tab-prefetch.ts`. */
|
|
8
|
+
const START_DELAY_MS = 2500;
|
|
9
|
+
|
|
10
|
+
/** Imported, not reached statically: that would pull Settings' shell into the boot chunk. */
|
|
11
|
+
const preloadSettingsPanes = () =>
|
|
12
|
+
import("@/components/settings/settings-section-content").then((m) => m.preloadSettingsSections());
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Loads the code of every kind of tab and window, and of every Settings pane, once the app has
|
|
16
|
+
* settled, so the first one of each opens at once. Not under `vite dev`, where it would be
|
|
17
|
+
* hundreds of unbundled modules.
|
|
18
|
+
*/
|
|
19
|
+
export function useUiPreload(enabled: boolean): void {
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!enabled || import.meta.env.DEV) return;
|
|
22
|
+
const connection = (navigator as Navigator & { connection?: ConnectionHints }).connection;
|
|
23
|
+
if (!shouldPreloadUi(connection, isTouchOnlyDevice())) return;
|
|
24
|
+
|
|
25
|
+
let stop = () => {};
|
|
26
|
+
const timer = setTimeout(() => {
|
|
27
|
+
stop = preloadWhenIdle([
|
|
28
|
+
...tabPreloads(),
|
|
29
|
+
...Object.values(WINDOW_CONTENT).map((content) => content.preload),
|
|
30
|
+
preloadSettingsPanes,
|
|
31
|
+
]);
|
|
32
|
+
}, START_DELAY_MS);
|
|
33
|
+
return () => {
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
stop();
|
|
36
|
+
};
|
|
37
|
+
}, [enabled]);
|
|
38
|
+
}
|
package/src/web/index.html
CHANGED
|
@@ -91,6 +91,48 @@
|
|
|
91
91
|
purge().then(function () { location.reload(); });
|
|
92
92
|
};
|
|
93
93
|
}
|
|
94
|
+
// Tell the server, since nothing bundled can: an `entry_never_ran` row in the
|
|
95
|
+
// session trace, naming the files that failed to load where the browser says.
|
|
96
|
+
// Same device id and token keys as src/web/lib/device-id.ts and api-client.ts.
|
|
97
|
+
function beacon(retried) {
|
|
98
|
+
try {
|
|
99
|
+
var token = null, dev = null;
|
|
100
|
+
try {
|
|
101
|
+
token = localStorage.getItem("ppm-auth-token");
|
|
102
|
+
dev = localStorage.getItem("ppm-device-id");
|
|
103
|
+
} catch (e) {}
|
|
104
|
+
if (!dev || !/^[A-Za-z0-9-]{8,64}$/.test(dev)) {
|
|
105
|
+
var b = new Uint8Array(16);
|
|
106
|
+
crypto.getRandomValues(b);
|
|
107
|
+
b[6] = (b[6] & 15) | 64;
|
|
108
|
+
b[8] = (b[8] & 63) | 128;
|
|
109
|
+
var h = "";
|
|
110
|
+
for (var i = 0; i < 16; i++) h += (b[i] + 256).toString(16).slice(1);
|
|
111
|
+
dev = h.slice(0, 8) + "-" + h.slice(8, 12) + "-" + h.slice(12, 16) + "-" + h.slice(16, 20) + "-" + h.slice(20);
|
|
112
|
+
try { localStorage.setItem("ppm-device-id", dev); } catch (e) {}
|
|
113
|
+
}
|
|
114
|
+
var failed = [];
|
|
115
|
+
try {
|
|
116
|
+
var list = performance.getEntriesByType("resource");
|
|
117
|
+
for (var j = 0; j < list.length && failed.length < 20; j++) {
|
|
118
|
+
if (list[j].responseStatus >= 400) failed.push(list[j].name.replace(location.origin, "") + " " + list[j].responseStatus);
|
|
119
|
+
}
|
|
120
|
+
} catch (e) {}
|
|
121
|
+
var now = Date.now();
|
|
122
|
+
var headers = { "Content-Type": "application/json" };
|
|
123
|
+
if (token) headers.Authorization = "Bearer " + token;
|
|
124
|
+
fetch("/api/trace", {
|
|
125
|
+
method: "POST",
|
|
126
|
+
keepalive: true,
|
|
127
|
+
headers: headers,
|
|
128
|
+
body: JSON.stringify({
|
|
129
|
+
deviceId: dev,
|
|
130
|
+
sentAt: now,
|
|
131
|
+
entries: [{ ts: now, type: "entry_never_ran", refId: null, payload: { path: location.pathname, retried: retried, failed: failed, ua: navigator.userAgent } }],
|
|
132
|
+
}),
|
|
133
|
+
}).catch(function () {});
|
|
134
|
+
} catch (e) {}
|
|
135
|
+
}
|
|
94
136
|
function check() {
|
|
95
137
|
// Module scripts execute before `load`, so a flag still unset here is
|
|
96
138
|
// never going to be set — this cannot misfire on a slow boot.
|
|
@@ -113,6 +155,7 @@
|
|
|
113
155
|
// reload is a loop. Go straight to the message.
|
|
114
156
|
retried = true;
|
|
115
157
|
}
|
|
158
|
+
beacon(retried);
|
|
116
159
|
// One silent attempt first: index.html is served `no-cache`, so a
|
|
117
160
|
// reload with this origin's caches dropped is exactly how a tab
|
|
118
161
|
// holding an upgraded-away chunk list heals itself.
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
* one that says what happened.
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
+
import { reportTraceError } from "./trace-client";
|
|
28
|
+
|
|
27
29
|
const RELOAD_KEY = "ppm:chunk-reload";
|
|
28
30
|
|
|
29
31
|
/**
|
|
@@ -107,7 +109,9 @@ export function installChunkErrorRecovery(): void {
|
|
|
107
109
|
// rethrow, and `React.lazy` then fails reading `.default` of undefined — an
|
|
108
110
|
// error that says nothing about what actually happened. The reload normally
|
|
109
111
|
// wins the race; when it does not, the boundary catches the real throw.
|
|
110
|
-
window.addEventListener("vite:preloadError", () => {
|
|
112
|
+
window.addEventListener("vite:preloadError", (event) => {
|
|
113
|
+
// Recorded before the reload; the page-hide flush carries it out as the page goes.
|
|
114
|
+
reportTraceError("chunk_error", (event as (Event & { payload?: unknown }) | undefined)?.payload ?? "vite:preloadError");
|
|
111
115
|
reloadOnceForChunkError();
|
|
112
116
|
});
|
|
113
117
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A stable id for this browser, minted once. Browser rows in the session trace are keyed by it
|
|
3
|
+
* (`browser:<deviceId>`), which answers "which machine does this happen on" and gives each
|
|
4
|
+
* device its own rate limit on `POST /api/trace`.
|
|
5
|
+
*
|
|
6
|
+
* `index.html`'s boot watchdog reads and mints the same key without the bundle, so the two
|
|
7
|
+
* formats must stay identical.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const DEVICE_ID_KEY = "ppm-device-id";
|
|
11
|
+
const VALID = /^[A-Za-z0-9-]{8,64}$/;
|
|
12
|
+
|
|
13
|
+
let memo: string | null = null;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A v4 UUID from `getRandomValues`. Not `crypto.randomUUID`: that exists only in a secure
|
|
17
|
+
* context, and PPM is routinely reached over plain HTTP on a LAN.
|
|
18
|
+
*/
|
|
19
|
+
export function uuidV4(): string {
|
|
20
|
+
const b = new Uint8Array(16);
|
|
21
|
+
crypto.getRandomValues(b);
|
|
22
|
+
b[6] = (b[6]! & 0x0f) | 0x40;
|
|
23
|
+
b[8] = (b[8]! & 0x3f) | 0x80;
|
|
24
|
+
const h = Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
25
|
+
return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20)}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getDeviceId(): string {
|
|
29
|
+
if (memo) return memo;
|
|
30
|
+
try {
|
|
31
|
+
const stored = localStorage.getItem(DEVICE_ID_KEY);
|
|
32
|
+
if (stored && VALID.test(stored)) return (memo = stored);
|
|
33
|
+
} catch {
|
|
34
|
+
// Private mode can refuse storage outright; an id per page load still works.
|
|
35
|
+
}
|
|
36
|
+
const id = uuidV4();
|
|
37
|
+
try { localStorage.setItem(DEVICE_ID_KEY, id); } catch { /* see above */ }
|
|
38
|
+
return (memo = id);
|
|
39
|
+
}
|
|
@@ -16,6 +16,8 @@ export const FEATURE_BADGES = {
|
|
|
16
16
|
"remote-desktop": "beta",
|
|
17
17
|
/** Design mode (Designs sidebar tab): design chat beside a live canvas, shipped in 0.23.0. */
|
|
18
18
|
designs: "new",
|
|
19
|
+
/** Android emulator — start an AVD and control its screen from the browser. */
|
|
20
|
+
android: "beta",
|
|
19
21
|
} as const satisfies Record<string, FeatureBadgeKind>;
|
|
20
22
|
|
|
21
23
|
export type FeatureBadgeId = keyof typeof FEATURE_BADGES;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `React.lazy`, plus a way to load the module before anything renders it — and, once it is
|
|
3
|
+
* loaded, a first render that does not suspend at all.
|
|
4
|
+
*
|
|
5
|
+
* The second half is the point. A `React.lazy` component suspends on its first render even
|
|
6
|
+
* when its module is already in memory: its initializer only starts on that render, and a
|
|
7
|
+
* promise cannot report that it has settled until a microtask later. So the boundary commits
|
|
8
|
+
* its spinner, and from then on react-dom holds the content back until 300 ms after that
|
|
9
|
+
* spinner appeared (`FALLBACK_THROTTLE_MS`), however soon it is ready. Measured against
|
|
10
|
+
* localhost on a desktop: a terminal's code had arrived 11–27 ms after the click, and the
|
|
11
|
+
* terminal appeared at 350–355 ms. Loading the module sooner cannot change that; not
|
|
12
|
+
* suspending does.
|
|
13
|
+
*/
|
|
14
|
+
import { lazy, useState, type ComponentType } from "react";
|
|
15
|
+
|
|
16
|
+
export type PreloadableComponent<P> = ComponentType<P> & {
|
|
17
|
+
/** Load the module now. A load that fails is forgotten, so the next render asks again. */
|
|
18
|
+
preload: () => Promise<void>;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export function lazyWithPreload<P extends object>(
|
|
22
|
+
load: () => Promise<{ default: ComponentType<P> }>,
|
|
23
|
+
): PreloadableComponent<P> {
|
|
24
|
+
let loaded: ComponentType<P> | undefined;
|
|
25
|
+
let loading: Promise<void> | undefined;
|
|
26
|
+
const preload = () =>
|
|
27
|
+
(loading ??= load().then(
|
|
28
|
+
(module) => { loaded = module.default; },
|
|
29
|
+
(error: unknown) => { loading = undefined; throw error; },
|
|
30
|
+
));
|
|
31
|
+
// What an instance mounted before the module arrived renders: it suspends, as `lazy` always did.
|
|
32
|
+
const Lazy = lazy(() => preload().then(() => ({ default: loaded! })));
|
|
33
|
+
|
|
34
|
+
function Preloadable(props: P) {
|
|
35
|
+
// Chosen once per instance. A transition that suspends here and is pinged before it
|
|
36
|
+
// resumes commits this instance as `Lazy` without rendering it again, so switching to the
|
|
37
|
+
// loaded component on a later render would change the element type under it — and React
|
|
38
|
+
// would remount the whole tab.
|
|
39
|
+
const [Component] = useState<ComponentType<P>>(() => loaded ?? Lazy);
|
|
40
|
+
return <Component {...props} />;
|
|
41
|
+
}
|
|
42
|
+
return Object.assign(Preloadable, { preload });
|
|
43
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loads the code behind every tab and window while the app has nothing else to do, so the
|
|
3
|
+
* first terminal, editor or chat of a session opens at once instead of behind a spinner.
|
|
4
|
+
* `lazy-with-preload.tsx` is why a loaded module also has to skip that spinner.
|
|
5
|
+
*
|
|
6
|
+
* It is a download, so it is skipped wherever one costs the user something: a data-saver
|
|
7
|
+
* setting, a 2G link, and any touch-only device not known to be on Wi-Fi — which includes
|
|
8
|
+
* every iPhone, since Safari says nothing about its connection.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** The fields of `navigator.connection` (Network Information API) this reads. */
|
|
12
|
+
export interface ConnectionHints {
|
|
13
|
+
saveData?: boolean;
|
|
14
|
+
effectiveType?: string;
|
|
15
|
+
type?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function shouldPreloadUi(connection: ConnectionHints | undefined, touchOnly: boolean): boolean {
|
|
19
|
+
if (connection?.saveData) return false;
|
|
20
|
+
if (connection?.effectiveType === "slow-2g" || connection?.effectiveType === "2g") return false;
|
|
21
|
+
if (!touchOnly) return true;
|
|
22
|
+
return connection?.type === "wifi" || connection?.type === "ethernet";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Runs `run` once the main thread is idle; returns a function that calls it off. */
|
|
26
|
+
export type WhenIdle = (run: () => void) => () => void;
|
|
27
|
+
|
|
28
|
+
const whenIdle: WhenIdle = (run) => {
|
|
29
|
+
if (typeof requestIdleCallback === "function") {
|
|
30
|
+
const id = requestIdleCallback(run);
|
|
31
|
+
return () => cancelIdleCallback(id);
|
|
32
|
+
}
|
|
33
|
+
// Safari has no `requestIdleCallback`.
|
|
34
|
+
const id = setTimeout(run, 200);
|
|
35
|
+
return () => clearTimeout(id);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Runs `tasks` one after another, each starting in an idle period of its own, so no two
|
|
40
|
+
* modules are evaluated in one stretch of the main thread. A task that fails is skipped:
|
|
41
|
+
* whatever needed that module will ask for it again. Returns a function that stops the rest.
|
|
42
|
+
*/
|
|
43
|
+
export function preloadWhenIdle(tasks: ReadonlyArray<() => Promise<unknown>>, idle: WhenIdle = whenIdle): () => void {
|
|
44
|
+
let stopped = false;
|
|
45
|
+
let cancel = () => {};
|
|
46
|
+
const next = (i: number) => {
|
|
47
|
+
if (stopped || i >= tasks.length) return;
|
|
48
|
+
cancel = idle(() => {
|
|
49
|
+
void Promise.resolve()
|
|
50
|
+
.then(tasks[i])
|
|
51
|
+
.catch(() => {})
|
|
52
|
+
.then(() => next(i + 1));
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
next(0);
|
|
56
|
+
return () => {
|
|
57
|
+
stopped = true;
|
|
58
|
+
cancel();
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -60,20 +60,7 @@ export function scoreFileSearchFast(
|
|
|
60
60
|
): FileSearchScore | null {
|
|
61
61
|
// Multi-word query: score each word independently, require all to match
|
|
62
62
|
if (qLower.includes(" ")) {
|
|
63
|
-
|
|
64
|
-
if (words.length === 0) return null;
|
|
65
|
-
if (words.length === 1) {
|
|
66
|
-
return scoreFileSearchFast(words[0]!, filenameLower, pathLower, labelLen, depth);
|
|
67
|
-
}
|
|
68
|
-
let maxTier = 0;
|
|
69
|
-
let totalOffset = 0;
|
|
70
|
-
for (const word of words) {
|
|
71
|
-
const s = scoreFileSearchFast(word, filenameLower, pathLower, labelLen, depth);
|
|
72
|
-
if (!s) return null;
|
|
73
|
-
maxTier = Math.max(maxTier, s.tier);
|
|
74
|
-
totalOffset += s.offset;
|
|
75
|
-
}
|
|
76
|
-
return { tier: maxTier, offset: totalOffset, nameLen: labelLen, depth };
|
|
63
|
+
return scoreWordsFast(qLower.split(/\s+/).filter(Boolean), filenameLower, pathLower, labelLen, depth);
|
|
77
64
|
}
|
|
78
65
|
|
|
79
66
|
// Tier 0: exact filename match
|
|
@@ -101,6 +88,32 @@ export function scoreFileSearchFast(
|
|
|
101
88
|
return null;
|
|
102
89
|
}
|
|
103
90
|
|
|
91
|
+
/**
|
|
92
|
+
* `scoreFileSearchFast` for a multi-word query already split into its words, so a loop scoring
|
|
93
|
+
* one query against many paths splits it once rather than once per path.
|
|
94
|
+
*/
|
|
95
|
+
export function scoreWordsFast(
|
|
96
|
+
words: string[],
|
|
97
|
+
filenameLower: string,
|
|
98
|
+
pathLower: string,
|
|
99
|
+
labelLen: number,
|
|
100
|
+
depth: number,
|
|
101
|
+
): FileSearchScore | null {
|
|
102
|
+
if (words.length === 0) return null;
|
|
103
|
+
if (words.length === 1) {
|
|
104
|
+
return scoreFileSearchFast(words[0]!, filenameLower, pathLower, labelLen, depth);
|
|
105
|
+
}
|
|
106
|
+
let maxTier = 0;
|
|
107
|
+
let totalOffset = 0;
|
|
108
|
+
for (const word of words) {
|
|
109
|
+
const s = scoreFileSearchFast(word, filenameLower, pathLower, labelLen, depth);
|
|
110
|
+
if (!s) return null;
|
|
111
|
+
maxTier = Math.max(maxTier, s.tier);
|
|
112
|
+
totalOffset += s.offset;
|
|
113
|
+
}
|
|
114
|
+
return { tier: maxTier, offset: totalOffset, nameLen: labelLen, depth };
|
|
115
|
+
}
|
|
116
|
+
|
|
104
117
|
/** Convenience wrapper — lowers inputs on the fly. Use for ad-hoc calls. */
|
|
105
118
|
export function scoreFileSearch(
|
|
106
119
|
query: string,
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import {
|
|
9
9
|
Terminal, MessageSquare, FileCode, Database, FileDiff, Settings, Puzzle, Sparkles, Users, CircleX,
|
|
10
|
-
GitCommitHorizontal, Palette,
|
|
10
|
+
GitCommitHorizontal, Palette, Smartphone,
|
|
11
11
|
type LucideIcon,
|
|
12
12
|
} from "@/lib/icons";
|
|
13
13
|
import type { ElementType } from "react";
|
|
@@ -36,6 +36,7 @@ export const TAB_TYPE_ICONS: Record<TabType, LucideIcon> = {
|
|
|
36
36
|
group: Users,
|
|
37
37
|
problems: CircleX,
|
|
38
38
|
design: Palette,
|
|
39
|
+
android: Smartphone,
|
|
39
40
|
};
|
|
40
41
|
|
|
41
42
|
/** Resolve the icon for a tab type, falling back to a generic glyph. */
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Starts browser logging. A module of its own so it can be the *first* import of `main.tsx`:
|
|
3
|
+
* imports evaluate in order before any statement runs, so a call written in `main.tsx` itself
|
|
4
|
+
* would only happen after the whole app had already evaluated — and logged — without it.
|
|
5
|
+
*/
|
|
6
|
+
import { installTraceClient } from "./trace-client";
|
|
7
|
+
|
|
8
|
+
installTraceClient();
|