@xopcai/xopc 0.0.415 → 0.0.417
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/README.md +2 -2
- package/README.zh-CN.md +2 -2
- package/dist/browser-ext/_locales/en/messages.json +4 -1
- package/dist/browser-ext/_locales/zh_CN/messages.json +4 -1
- package/dist/browser-ext/dist/assets/{page-context-MuzjMBlJ.js → page-context-BKnEwsOO.js} +2914 -1381
- package/dist/browser-ext/dist/background.js +39 -10
- package/dist/browser-ext/dist/sidepanel.html +1 -1
- package/dist/browser-ext/dist/sidepanel.js +502 -348
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/activity-YogQEteU.js +1 -0
- package/dist/gateway/static/root/assets/activity-store-DnqOM8GN.js +1 -0
- package/dist/gateway/static/root/assets/agent-avatar-dicebear-1UABT2KS.js +1 -0
- package/dist/gateway/static/root/assets/agent-avatar-display-Cy50vjbq.js +2 -0
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-V4NX_cWz.js +1 -0
- package/dist/gateway/static/root/assets/agent-display-names-Bje7vfSn.js +1 -0
- package/dist/gateway/static/root/assets/agent-plugin-dialog-CQ5LLDMO.js +1 -0
- package/dist/gateway/static/root/assets/agents-O7mago-m.js +77 -0
- package/dist/gateway/static/root/assets/{agents-admin-api-B1p-ghg9.js → agents-admin-api-CyjykMEh.js} +2 -2
- package/dist/gateway/static/root/assets/agents-app-path-ciChvpCS.js +1 -0
- package/dist/gateway/static/root/assets/api-C1dxxDZx.js +1 -0
- package/dist/gateway/static/root/assets/api-Ddrs70xV.js +1 -0
- package/dist/gateway/static/root/assets/app-chrome-BeB4KgOf.js +1 -0
- package/dist/gateway/static/root/assets/app-link-CytZ5zkp.js +1 -0
- package/dist/gateway/static/root/assets/app-management-settings-panel-C1Zs-eha.js +1 -0
- package/dist/gateway/static/root/assets/appearance-settings-lIfGokbz.js +1 -0
- package/dist/gateway/static/root/assets/apps-page-CUvtsRYD.js +1 -0
- package/dist/gateway/static/root/assets/archive-Dz0hferG.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-Ch7wolHE.js → archive-plugin-n5lPr79c.js} +1 -1
- package/dist/gateway/static/root/assets/arrow-left-D880xG-P.js +1 -0
- package/dist/gateway/static/root/assets/arrow-right-DSSvoX71.js +1 -0
- package/dist/gateway/static/root/assets/arrow-up-D5ZtR1QT.js +1 -0
- package/dist/gateway/static/root/assets/arrow-up-right-T72JbQ1Q.js +1 -0
- package/dist/gateway/static/root/assets/{attachment-preview-renderer-wzIchDSv.js → attachment-preview-renderer-DdOEgexg.js} +3 -3
- package/dist/gateway/static/root/assets/{attachment-process-heavy-Db4nTY5N.js → attachment-process-heavy-DGZZ-M85.js} +2 -2
- package/dist/gateway/static/root/assets/automation-api-Bld8blNl.js +1 -0
- package/dist/gateway/static/root/assets/automation-display-BcfZOQTC.js +2 -0
- package/dist/gateway/static/root/assets/{automations-page-DK7AU79v.js → automations-page-oLsNzu_6.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-BgtYY2Mm.js +8 -0
- package/dist/gateway/static/root/assets/beta-badge-BnzdzIEl.js +1 -0
- package/dist/gateway/static/root/assets/{binary-plugins-B4HcHYsC.js → binary-plugins-D9VW7dWP.js} +2 -2
- package/dist/gateway/static/root/assets/{block-editor-BQAWEZF-.js → block-editor-C477bTtO.js} +23 -23
- package/dist/gateway/static/root/assets/book-open-CCGtrT3R.js +1 -0
- package/dist/gateway/static/root/assets/bot-DjLkhyZL.js +1 -0
- package/dist/gateway/static/root/assets/box-DvYoGszj.js +1 -0
- package/dist/gateway/static/root/assets/braces-Cfmtagno.js +1 -0
- package/dist/gateway/static/root/assets/brand-logo-CgT9zQfr.js +1 -0
- package/dist/gateway/static/root/assets/briefcase-business-BsoCaI_t.js +1 -0
- package/dist/gateway/static/root/assets/browser-BLJWD7WI.js +8 -0
- package/dist/gateway/static/root/assets/{browser-automation-inputs-D6AccXaA.js → browser-automation-inputs-CCiYXxmh.js} +1 -1
- package/dist/gateway/static/root/assets/browser-automations-page-DIUNY94X.js +3 -0
- package/dist/gateway/static/root/assets/browser-control-api-Y3fvmeBk.js +6 -0
- package/dist/gateway/static/root/assets/browser-notification-delivery-DmE2FgGc.js +1 -0
- package/dist/gateway/static/root/assets/browser-settings-page-DjkGahlz.js +3 -0
- package/dist/gateway/static/root/assets/{button-aIC072nz.js → button-CnRSIP6m.js} +1 -1
- package/dist/gateway/static/root/assets/calendar-clock-D-quYVPe.js +1 -0
- package/dist/gateway/static/root/assets/calendar-days-hw_Y-g-s.js +1 -0
- package/dist/gateway/static/root/assets/capabilities-DAyA681v.js +1 -0
- package/dist/gateway/static/root/assets/capabilities-DRVXLssH.js +1 -0
- package/dist/gateway/static/root/assets/capabilities-page-DFW4Y0x8.js +2 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-uOHSMQPZ.js +8 -0
- package/dist/gateway/static/root/assets/capability-header-actions-CTUCuBlW.js +1 -0
- package/dist/gateway/static/root/assets/capability-icon-DVoZxEgW.js +1 -0
- package/dist/gateway/static/root/assets/capability-links-DzQWK1Fh.js +1 -0
- package/dist/gateway/static/root/assets/channels-D2a69dSt.js +1 -0
- package/dist/gateway/static/root/assets/channels-routes-r2g-9DdC.js +1 -0
- package/dist/gateway/static/root/assets/chat-agents-api-D5nR_JVe.js +1 -0
- package/dist/gateway/static/root/assets/chat-chart-block-K2t333qv.js +2 -0
- package/dist/gateway/static/root/assets/chat-page-CG38tCHE.js +71 -0
- package/dist/gateway/static/root/assets/chat-page-zQeUaawJ.css +1 -0
- package/dist/gateway/static/root/assets/chat-terminal-dock-CkFG6mA3.js +35 -0
- package/dist/gateway/static/root/assets/chevron-left-DqFhpbvK.js +1 -0
- package/dist/gateway/static/root/assets/chevron-right-BweFrslA.js +1 -0
- package/dist/gateway/static/root/assets/chunk-D32TOXHM-DQIy-Baq.js +156 -0
- package/dist/gateway/static/root/assets/chunk-KS7C4IRE-CiwuuyV8.js +4 -0
- package/dist/gateway/static/root/assets/circle-BoO4YvTx.js +1 -0
- package/dist/gateway/static/root/assets/circle-alert-BEjgurr2.js +1 -0
- package/dist/gateway/static/root/assets/circle-pause-CN9jYH2s.js +1 -0
- package/dist/gateway/static/root/assets/circle-x-DFsCKeya.js +1 -0
- package/dist/gateway/static/root/assets/clock-3-DnrAnuyZ.js +1 -0
- package/dist/gateway/static/root/assets/cloud-C4-yfnnk.js +1 -0
- package/dist/gateway/static/root/assets/cloud-credits-B-nbtkqv.js +1 -0
- package/dist/gateway/static/root/assets/code-xml-DJtYhZUF.js +1 -0
- package/dist/gateway/static/root/assets/coins-DjP27vUx.js +1 -0
- package/dist/gateway/static/root/assets/command-palette-api-Do_66X1B.js +1 -0
- package/dist/gateway/static/root/assets/composer-payload-handoff-BU3B-C26.js +1 -0
- package/dist/gateway/static/root/assets/computer-settings-page-DBxOcMko.js +1 -0
- package/dist/gateway/static/root/assets/confirm-dialog-XGclfBqe.js +1 -0
- package/dist/gateway/static/root/assets/connected-providers-grid-Dmnu2zle.js +1 -0
- package/dist/gateway/static/root/assets/connector-filters-Cfcx9EA2.js +1 -0
- package/dist/gateway/static/root/assets/connector-service-page-rWpnchb3.js +1 -0
- package/dist/gateway/static/root/assets/connectors-api-DIBG72k4.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-DT_WrC1y.js +1 -0
- package/dist/gateway/static/root/assets/constants-DBtMsXdW.js +1 -0
- package/dist/gateway/static/root/assets/copy-text-row-CYIv7RfP.js +1 -0
- package/dist/gateway/static/root/assets/cpu-B247669f.js +1 -0
- package/dist/gateway/static/root/assets/database-CjjeZfRG.js +1 -0
- package/dist/gateway/static/root/assets/date-picker-CE-cZFCU.js +1 -0
- package/dist/gateway/static/root/assets/dependency-picker-7SpSfDSg.js +1 -0
- package/dist/gateway/static/root/assets/desktop-pet-lorocS9j.js +1 -0
- package/dist/gateway/static/root/assets/desktop-pet-narrative-CS8qJpNO.js +1 -0
- package/dist/gateway/static/root/assets/desktop-pet-settings-CEcohlZq.js +1 -0
- package/dist/gateway/static/root/assets/{desktop-pet-sprite-Bd-aOI7N.js → desktop-pet-sprite-D5YYq2zC.js} +1 -1
- package/dist/gateway/static/root/assets/dev-view-store-57HgVuZ6.js +1 -0
- package/dist/gateway/static/root/assets/device-pairing-wizard-CLCPuf4R.js +1 -0
- package/dist/gateway/static/root/assets/directory-picker-path-field-D4jMhpka.js +1 -0
- package/dist/gateway/static/root/assets/discussion-annotation-sync-BKjf9gWe.js +1 -0
- package/dist/gateway/static/root/assets/dist-CaUuvp8-.js +1 -0
- package/dist/gateway/static/root/assets/dist-DNCdG_qB.js +1 -0
- package/dist/gateway/static/root/assets/dist-DfWfZ9iu.js +1 -0
- package/dist/gateway/static/root/assets/dist-DusecO_p.js +1 -0
- package/dist/gateway/static/root/assets/docx-preview-CnIClbYi.js +20 -0
- package/dist/gateway/static/root/assets/earth-BMhZtzcj.js +1 -0
- package/dist/gateway/static/root/assets/echarts-runtime-QSmTlXOu.js +18 -0
- package/dist/gateway/static/root/assets/electron-env-DHOGevH3.js +1 -0
- package/dist/gateway/static/root/assets/extension-debug-page-BsK2LMXQ.js +1 -0
- package/dist/gateway/static/root/assets/extension-iframe-host-Dhkk5JV2.js +1 -0
- package/dist/gateway/static/root/assets/extension-marketplace-api-CVJPqJOB.js +1 -0
- package/dist/gateway/static/root/assets/extension-page-Brps2XDP.js +1 -0
- package/dist/gateway/static/root/assets/extension-paths-DvuaZJuy.js +1 -0
- package/dist/gateway/static/root/assets/extension-provider-Byrd8Sor.js +1 -0
- package/dist/gateway/static/root/assets/extension-settings-page-CHY68DpG.js +1 -0
- package/dist/gateway/static/root/assets/file-BqMS_3DT.js +1 -0
- package/dist/gateway/static/root/assets/file-archive-DanfQJNe.js +1 -0
- package/dist/gateway/static/root/assets/file-preview-surface-BlprUrIs.js +1 -0
- package/dist/gateway/static/root/assets/file-text-D12HbeVy.js +1 -0
- package/dist/gateway/static/root/assets/file-tree-CFlZnV3Y.js +1 -0
- package/dist/gateway/static/root/assets/file-tree-utils-DJs1faGv.js +1 -0
- package/dist/gateway/static/root/assets/files-BNL4kkSB.js +1 -0
- package/dist/gateway/static/root/assets/floating-ui.dom-seOukHzT.js +1 -0
- package/dist/gateway/static/root/assets/folder-CN-pC3XL.js +1 -0
- package/dist/gateway/static/root/assets/folder-kanban-CpLlFI1o.js +1 -0
- package/dist/gateway/static/root/assets/form-field-width-DJw_jULe.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-config-swr-fQKBHBi1.js → gateway-config-swr-BAmUhiP1.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-realtime-CsykKL4l.js +1 -0
- package/dist/gateway/static/root/assets/gateway-realtime-store-DQqMBruB.js +1 -0
- package/dist/gateway/static/root/assets/gateway-restart-Ch128Lrr.js +1 -0
- package/dist/gateway/static/root/assets/gateway-settings-BA5-Uuwx.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-Cfwxof4k.js → gateway-startup-retry-CtUB3g6N.js} +1 -1
- package/dist/gateway/static/root/assets/gauge-C78eD2BA.js +1 -0
- package/dist/gateway/static/root/assets/git-branch-Dh9uxTot.js +1 -0
- package/dist/gateway/static/root/assets/global-defaults-api-CINf-C6a.js +2 -0
- package/dist/gateway/static/root/assets/heart-Cp4rgrqn.js +1 -0
- package/dist/gateway/static/root/assets/highlight-code-BH65IIbJ.js +1 -0
- package/dist/gateway/static/root/assets/highlighted-body-KQOG7T2V-DKGma5wI.js +1 -0
- package/dist/gateway/static/root/assets/history-DXH_9jsE.js +1 -0
- package/dist/gateway/static/root/assets/home-page-DaMFBYo1.js +2 -0
- package/dist/gateway/static/root/assets/image-Cwyalflz.js +1 -0
- package/dist/gateway/static/root/assets/image-generation-api-I_JgLL_m.js +1 -0
- package/dist/gateway/static/root/assets/imports-page-BWShtGRQ.js +1 -0
- package/dist/gateway/static/root/assets/index-BpCi0TdG.js +11 -0
- package/dist/gateway/static/root/assets/index-DY2Y83b9.css +1 -0
- package/dist/gateway/static/root/assets/index.module-Cd9ENXfk.js +1 -0
- package/dist/gateway/static/root/assets/info-CDrmIZhb.js +1 -0
- package/dist/gateway/static/root/assets/install-connector-dialog-DU1Tz7B3.js +1 -0
- package/dist/gateway/static/root/assets/interaction-BdhHBbYa.js +1 -0
- package/dist/gateway/static/root/assets/is-masked-secret-DOkL5b_X.js +1 -0
- package/dist/gateway/static/root/assets/{jszip.min-DT31yWkU.js → jszip.min-Dj17eJqX.js} +1 -1
- package/dist/gateway/static/root/assets/key-round-DWbpyU2U.js +1 -0
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-CdM4BQwp.js +1 -0
- package/dist/gateway/static/root/assets/languages-zXtNocoy.js +2 -0
- package/dist/gateway/static/root/assets/laptop-CI3hBVrl.js +1 -0
- package/dist/gateway/static/root/assets/layers-mJW7JJKm.js +1 -0
- package/dist/gateway/static/root/assets/layout-grid-CEVZdVFU.js +1 -0
- package/dist/gateway/static/root/assets/list-checks-BbsExAoq.js +1 -0
- package/dist/gateway/static/root/assets/list-filter-COkzTdOz.js +1 -0
- package/dist/gateway/static/root/assets/list-todo-CTVRto8O.js +1 -0
- package/dist/gateway/static/root/assets/list-tree-B0OMswgM.js +1 -0
- package/dist/gateway/static/root/assets/local-app-workbench-page-qPflPuQD.js +1 -0
- package/dist/gateway/static/root/assets/local-apps-Ck6kACsY.js +1 -0
- package/dist/gateway/static/root/assets/local-apps-page-CxyRVfjD.js +1 -0
- package/dist/gateway/static/root/assets/local-session-drafts-B9ZPwotC.js +1 -0
- package/dist/gateway/static/root/assets/{locale-store-B7s2Hb35.js → locale-store-lIXD1FMw.js} +1 -1
- package/dist/gateway/static/root/assets/lock-keyhole-DEK5kH0u.js +1 -0
- package/dist/gateway/static/root/assets/logs-page-CbY1N-zi.js +2 -0
- package/dist/gateway/static/root/assets/loopi-C09I2mNj.css +1 -0
- package/dist/gateway/static/root/assets/loopi-CNtmi9FU.js +1 -0
- package/dist/gateway/static/root/assets/management-settings-Diy12JfQ.js +1 -0
- package/dist/gateway/static/root/assets/{markdown-editor-phTQ0mox.js → markdown-editor-BuuGlcfG.js} +1 -1
- package/dist/gateway/static/root/assets/markdown-view-C-DHb3Io.css +1 -0
- package/dist/gateway/static/root/assets/markdown-view-CJt-i2Dp.js +324 -0
- package/dist/gateway/static/root/assets/{media-plugins-DYQDjCVQ.js → media-plugins-D_bR23mA.js} +1 -1
- package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-Ur99GwOg.js +1 -0
- package/dist/gateway/static/root/assets/mermaid-render-oOellPHt.js +134 -0
- package/dist/gateway/static/root/assets/message-circle-Badhj-4D.js +1 -0
- package/dist/gateway/static/root/assets/message-square-fVE7Ghj1.js +1 -0
- package/dist/gateway/static/root/assets/message-square-plus-XP0tGdlV.js +1 -0
- package/dist/gateway/static/root/assets/{messages-BYq0cPbn.js → messages-DRR9N3HC.js} +1 -1
- package/dist/gateway/static/root/assets/messages-square-BckAJrEW.js +1 -0
- package/dist/gateway/static/root/assets/mic-CuUb7zc-.js +1 -0
- package/dist/gateway/static/root/assets/minimize-2-DtOGrlpo.js +1 -0
- package/dist/gateway/static/root/assets/mobile-pair-qr-CuIbmw5x.js +1 -0
- package/dist/gateway/static/root/assets/model-selector-DCYA_ntf.js +1 -0
- package/dist/gateway/static/root/assets/models-hub-cache-za2fWJLg.js +1 -0
- package/dist/gateway/static/root/assets/monitor-Af5eAvF7.js +1 -0
- package/dist/gateway/static/root/assets/mouse-pointer-2-DZ51Onvj.js +1 -0
- package/dist/gateway/static/root/assets/navigation-BkjnOw30.js +1 -0
- package/dist/gateway/static/root/assets/network-BUQLY1BV.js +1 -0
- package/dist/gateway/static/root/assets/new-session-preferences-gb411vZP.js +1 -0
- package/dist/gateway/static/root/assets/note-detail-panel-DBs1yHLy.js +5 -0
- package/dist/gateway/static/root/assets/note-image-lightbox-CivkB6LB.js +1 -0
- package/dist/gateway/static/root/assets/notes-api-C_458rv5.js +1 -0
- package/dist/gateway/static/root/assets/notes-page-DL3c-41a.js +8 -0
- package/dist/gateway/static/root/assets/number-input-El7Szeln.js +1 -0
- package/dist/gateway/static/root/assets/oauth-api-C3X9FLYw.js +1 -0
- package/dist/gateway/static/root/assets/oauth-authorization-window-o6URRos4.js +1 -0
- package/dist/gateway/static/root/assets/oauth-provider-connect-H81se_3n.js +1 -0
- package/dist/gateway/static/root/assets/package-wATCyihJ.js +1 -0
- package/dist/gateway/static/root/assets/page-context-capture-button-BkAlQ7cB.js +1 -0
- package/dist/gateway/static/root/assets/page-context-draft-ClLgaOaD.js +1 -0
- package/dist/gateway/static/root/assets/page-header-store-DH8K0xii.js +1 -0
- package/dist/gateway/static/root/assets/page-tabs-oeTY7z3_.js +1 -0
- package/dist/gateway/static/root/assets/panel-left-C8MqSXRZ.js +1 -0
- package/dist/gateway/static/root/assets/panel-right-CFGrHTsD.js +1 -0
- package/dist/gateway/static/root/assets/paperclip-f1HujQY1.js +1 -0
- package/dist/gateway/static/root/assets/pause-DuPxgSxk.js +1 -0
- package/dist/gateway/static/root/assets/{pdf-D4PI9qAw.js → pdf-EQHMWEbX.js} +3 -3
- package/dist/gateway/static/root/assets/pdf-runtime-JnUAvfIa.js +2 -0
- package/dist/gateway/static/root/assets/{pdf.worker.min-B4E34YdZ.js → pdf.worker.min-bpyjgR8v.js} +7 -7
- package/dist/gateway/static/root/assets/pencil-DmIY3Oa-.js +1 -0
- package/dist/gateway/static/root/assets/personal-avatar-BLtHt8fV.js +1 -0
- package/dist/gateway/static/root/assets/personal-avatar-BUCb7OiW.css +1 -0
- package/dist/gateway/static/root/assets/personal-page-B5DP3lO-.js +1 -0
- package/dist/gateway/static/root/assets/personal-proactivity-DaRnbB1f.js +1 -0
- package/dist/gateway/static/root/assets/personal-settings-panel-DjDc5Kaz.js +1 -0
- package/dist/gateway/static/root/assets/phone-dependencies-card-DISHarj8.js +1 -0
- package/dist/gateway/static/root/assets/phone-model-picker-u8YIQCgo.js +1 -0
- package/dist/gateway/static/root/assets/phone-settings-page-el3pT0PD.js +1 -0
- package/dist/gateway/static/root/assets/phone-workspace-store-fhnZrgy_.js +1 -0
- package/dist/gateway/static/root/assets/pin-off-BMRv-Kxr.js +1 -0
- package/dist/gateway/static/root/assets/play-kxZvpBg8.js +1 -0
- package/dist/gateway/static/root/assets/plug-DKYPEgkR.js +1 -0
- package/dist/gateway/static/root/assets/plug-zap-L8NMe3Sv.js +1 -0
- package/dist/gateway/static/root/assets/plugin-details-dialog-CTBs1Jde.js +1 -0
- package/dist/gateway/static/root/assets/plus-Q2yW6OE7.js +1 -0
- package/dist/gateway/static/root/assets/popover-select-DniHw2dy.js +1 -0
- package/dist/gateway/static/root/assets/power-ZI-pBczI.js +1 -0
- package/dist/gateway/static/root/assets/power-off-CwwQ7Gp7.js +1 -0
- package/dist/gateway/static/root/assets/preference-select-fields-D7oluyHN.js +1 -0
- package/dist/gateway/static/root/assets/preload-helper-Czpn1I53.js +1 -0
- package/dist/gateway/static/root/assets/preview-open-alternatives-CY_hjK4b.js +1 -0
- package/dist/gateway/static/root/assets/product-automation-feedback-DsUSqCOX.js +7 -0
- package/dist/gateway/static/root/assets/product-delivery-BU_H84jL.js +1 -0
- package/dist/gateway/static/root/assets/product-navigation-Co8pLbDP.js +1 -0
- package/dist/gateway/static/root/assets/product-open-page-xn9G4hSI.js +1 -0
- package/dist/gateway/static/root/assets/product-preview-content-DcoK-iZe.js +1 -0
- package/dist/gateway/static/root/assets/product-preview-modal-Ruw9WSKK.js +2 -0
- package/dist/gateway/static/root/assets/project-detail-page-BKvWLiMw.js +7 -0
- package/dist/gateway/static/root/assets/project-understanding-BCQr0AZ_.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-D4g7bB7X.js +1 -0
- package/dist/gateway/static/root/assets/providers-api-CzVkFKFg.js +1 -0
- package/dist/gateway/static/root/assets/puzzle-BptcPjKI.js +1 -0
- package/dist/gateway/static/root/assets/recording-upload-0jxahBMo.js +1 -0
- package/dist/gateway/static/root/assets/refresh-button-bU_0NarN.js +1 -0
- package/dist/gateway/static/root/assets/refresh-cw-BRlGaq2w.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-BcfoLEna.js → registry-api-n8TwtJ_j.js} +2 -2
- package/dist/gateway/static/root/assets/remote-access-hub-cZpBi4Rk.js +1 -0
- package/dist/gateway/static/root/assets/rotate-ccw-JM1TBLpp.js +1 -0
- package/dist/gateway/static/root/assets/rotate-cw-LIg3Am9S.js +1 -0
- package/dist/gateway/static/root/assets/route-preload-B5UiReO7.js +2 -0
- package/dist/gateway/static/root/assets/runtime-health-D2TDFLLq.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-api-DesqGCnE.js → runtime-tools-api-D-8KjYK6.js} +1 -1
- package/dist/gateway/static/root/assets/runtime-tools-settings-panel-MKlLFuow.js +1 -0
- package/dist/gateway/static/root/assets/save-DRDABU--.js +1 -0
- package/dist/gateway/static/root/assets/schema-form-v4N4lawq.js +1 -0
- package/dist/gateway/static/root/assets/schemas-CCWMleym.js +55 -0
- package/dist/gateway/static/root/assets/search-DA7gz22f.js +1 -0
- package/dist/gateway/static/root/assets/secret-input-BQvFXqzz.js +1 -0
- package/dist/gateway/static/root/assets/secret-input-labels-B5Jl5HqK.js +1 -0
- package/dist/gateway/static/root/assets/segmented-styles-Cqb91xsn.js +1 -0
- package/dist/gateway/static/root/assets/send-1f1Ntw6E.js +1 -0
- package/dist/gateway/static/root/assets/server-BlHCBjiE.js +1 -0
- package/dist/gateway/static/root/assets/service-recommendation-list-B1xuVT3N.js +1 -0
- package/dist/gateway/static/root/assets/{session-api-DdQnMwkl.js → session-api-CsCoI2im.js} +1 -1
- package/dist/gateway/static/root/assets/session-channel-icon-SsY70Z6t.js +1 -0
- package/dist/gateway/static/root/assets/session-identity-label-B7sgG1PE.js +1 -0
- package/dist/gateway/static/root/assets/session-manager-5l9q0cd5.js +16 -0
- package/dist/gateway/static/root/assets/sessions-page-DsLw2aMD.js +1 -0
- package/dist/gateway/static/root/assets/settings-2-D-csvaET.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-B5lQeVNi.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-section-BqoVSko2.js +1 -0
- package/dist/gateway/static/root/assets/settings-form-draft-Dy10ldo8.js +1 -0
- package/dist/gateway/static/root/assets/settings-form-section-num14vSv.js +1 -0
- package/dist/gateway/static/root/assets/settings-loading-skeleton-BTqvr_Fw.js +1 -0
- package/dist/gateway/static/root/assets/settings-mode-store-CBsJ-Qg2.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-DROUGyJl.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-header-Bv-kQFTm.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-layout-DHP6MrrL.js +1 -0
- package/dist/gateway/static/root/assets/settings-uiTATseT.js +1 -0
- package/dist/gateway/static/root/assets/setup-status-panel-MJE3B_LX.js +1 -0
- package/dist/gateway/static/root/assets/share-link-dialog-BJHRQVKC.js +1 -0
- package/dist/gateway/static/root/assets/share-preview-page-Bsrv_zOQ.js +2 -0
- package/dist/gateway/static/root/assets/shares-api-rtWVHA_d.js +1 -0
- package/dist/gateway/static/root/assets/shares-settings-CfIRv4uX.js +1 -0
- package/dist/gateway/static/root/assets/shield-B1sI_cxl.js +1 -0
- package/dist/gateway/static/root/assets/shield-check-BU58siTV.js +1 -0
- package/dist/gateway/static/root/assets/shield-off-2jsucUds.js +1 -0
- package/dist/gateway/static/root/assets/side-chat-shortcut-BIw-1TTD.js +1 -0
- package/dist/gateway/static/root/assets/skill-api-B_W1K3sv.js +1 -0
- package/dist/gateway/static/root/assets/skill-api-utils-C7V4JVXM.js +1 -0
- package/dist/gateway/static/root/assets/skill-list-api-BzlKXPsE.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-Cff2GgZb.js +1 -0
- package/dist/gateway/static/root/assets/skill-wire-pattern-BPpeIcCi.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-DtBloYeU.js +2 -0
- package/dist/gateway/static/root/assets/sliders-horizontal-DqsYor6I.js +1 -0
- package/dist/gateway/static/root/assets/sliding-tab-list-DuQyViqe.js +1 -0
- package/dist/gateway/static/root/assets/smartphone-DSSsQFqA.js +1 -0
- package/dist/gateway/static/root/assets/{source-workspace-editor-BIvi89Zx.js → source-workspace-editor-kxosllTu.js} +1 -1
- package/dist/gateway/static/root/assets/sparkles-DHlfQFAF.js +1 -0
- package/dist/gateway/static/root/assets/specialists-xbB3xL9e.js +1 -0
- package/dist/gateway/static/root/assets/square-DMK_fB-3.js +1 -0
- package/dist/gateway/static/root/assets/square-pen-B8FsvqNu.js +1 -0
- package/dist/gateway/static/root/assets/square-terminal-K87bylpZ.js +1 -0
- package/dist/gateway/static/root/assets/star-BUWJqJ5c.js +1 -0
- package/dist/gateway/static/root/assets/stethoscope-DRqTAtjD.js +1 -0
- package/dist/gateway/static/root/assets/sticky-note-fzP7NAJq.js +1 -0
- package/dist/gateway/static/root/assets/store-SzD1Jvgm.js +1 -0
- package/dist/gateway/static/root/assets/system-settings-panel-BeQeUUMH.js +1 -0
- package/dist/gateway/static/root/assets/task-detail-page-Drrv-Hp0.js +2 -0
- package/dist/gateway/static/root/assets/task-result-evidence-D1Kyskm_.js +1 -0
- package/dist/gateway/static/root/assets/tasks-DRmd6sWt.js +1 -0
- package/dist/gateway/static/root/assets/terminal-oKqqZdiG.js +1 -0
- package/dist/gateway/static/root/assets/terminal-panel-store-5Fzctajw.js +1 -0
- package/dist/gateway/static/root/assets/theme-store-DW45fWYQ.js +1 -0
- package/dist/gateway/static/root/assets/timer-rCwGHjuO.js +1 -0
- package/dist/gateway/static/root/assets/tool-friendly-title-DGmi7rCQ.js +1 -0
- package/dist/gateway/static/root/assets/tracing-settings-page-B12u5D9A.js +1 -0
- package/dist/gateway/static/root/assets/trash-2-DusmjVPV.js +1 -0
- package/dist/gateway/static/root/assets/triangle-alert-2JXFNNKU.js +1 -0
- package/dist/gateway/static/root/assets/tunnel-api-DGO56LQU.js +1 -0
- package/dist/gateway/static/root/assets/understanding-activity-store-CTe6TFB0.js +1 -0
- package/dist/gateway/static/root/assets/understanding-refresh-store-mE9OKG6q.js +1 -0
- package/dist/gateway/static/root/assets/unlink-BEuthaaq.js +1 -0
- package/dist/gateway/static/root/assets/upload-rrb46c3c.js +1 -0
- package/dist/gateway/static/root/assets/usage-page-Ud2U9UG1.js +1 -0
- package/dist/gateway/static/root/assets/use-async-resource-BHFGZCY2.js +1 -0
- package/dist/gateway/static/root/assets/use-autosave-Cs2Ga_Y_.js +1 -0
- package/dist/gateway/static/root/assets/use-composer-attachments-BCbMj-MN.js +2 -0
- package/dist/gateway/static/root/assets/use-directory-picker-C4p7AgWY.js +1 -0
- package/dist/gateway/static/root/assets/use-file-preview-expanded-DSpCRXUW.js +2 -0
- package/dist/gateway/static/root/assets/use-media-query-ady-FgjK.js +1 -0
- package/dist/gateway/static/root/assets/use-personal-profile-BHL2AxWU.js +1 -0
- package/dist/gateway/static/root/assets/use-workspace-tree-CnmPZrpx.js +1 -0
- package/dist/gateway/static/root/assets/user-model-page-p5iPfnwl.js +2 -0
- package/dist/gateway/static/root/assets/user-round-C9jxPhMR.js +1 -0
- package/dist/gateway/static/root/assets/{vendor-codemirror-Qdcjid65.js → vendor-codemirror-aCQ0FcJT.js} +8 -8
- package/dist/gateway/static/root/assets/{vendor-swr-BIWyz7Rc.js → vendor-swr-CdRzEUwF.js} +1 -1
- package/dist/gateway/static/root/assets/video-B6V0GFss.js +1 -0
- package/dist/gateway/static/root/assets/voice-api-key-field-3gyc2UV3.js +1 -0
- package/dist/gateway/static/root/assets/voice-call-context-BM2A4bLz.js +1 -0
- package/dist/gateway/static/root/assets/{voice-config-api-BkUlN7GH.js → voice-config-api-Cda2uBIC.js} +1 -1
- package/dist/gateway/static/root/assets/voice-input-shortcut-events-DtYHsPLF.js +1 -0
- package/dist/gateway/static/root/assets/voice-transcribe-api-TInEfIYo.js +1 -0
- package/dist/gateway/static/root/assets/volume-2-BSJhAY97.js +1 -0
- package/dist/gateway/static/root/assets/wand-sparkles-CkSL-3Fy.js +1 -0
- package/dist/gateway/static/root/assets/{with-selector-aYPsXwdl.js → with-selector-xonYxPoM.js} +1 -1
- package/dist/gateway/static/root/assets/work-discovery-overlay-Dqu5CQCS.js +1 -0
- package/dist/gateway/static/root/assets/work-discovery-page-p-8ciZ0i.js +1 -0
- package/dist/gateway/static/root/assets/working-directory-picker-modal-DHl2cZY1.js +1 -0
- package/dist/gateway/static/root/assets/workspace-api-CtDbI6T7.js +2 -0
- package/dist/gateway/static/root/assets/workspace-editor-agent-store-B94Q2nN8.js +1 -0
- package/dist/gateway/static/root/assets/workspace-file-preview-dialog-CTIbUfKb.js +1 -0
- package/dist/gateway/static/root/assets/workspace-open-location-menu-BwxouqdZ.js +1 -0
- package/dist/gateway/static/root/assets/wrench-DFb4r8bH.js +1 -0
- package/dist/gateway/static/root/assets/x-B_N4OPjy.js +1 -0
- package/dist/gateway/static/root/assets/{xlsx-CKkngM-o.js → xlsx-Cl_0CZaL.js} +11 -11
- package/dist/gateway/static/root/assets/xml-_d7dTN2Q.js +3 -0
- package/dist/gateway/static/root/assets/xopc-cloud-account-card-CFb-23rS.js +1 -0
- package/dist/gateway/static/root/assets/zap-dximCGjy.js +1 -0
- package/dist/gateway/static/root/browser-setup-test.html +5 -0
- package/dist/gateway/static/root/browser-setup-test.js +7 -0
- package/dist/gateway/static/root/index.html +267 -46
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/browser-setup.js +6 -0
- package/dist/packages/gateway-contract/src/index.js +4 -0
- package/dist/packages/gateway-contract/src/phone-setup.js +6 -0
- package/dist/packages/realtime-client/src/index.js +1 -0
- package/dist/packages/realtime-protocol/src/index.js +1 -0
- package/dist/src/activity/emitter.js +1 -2
- package/dist/src/activity/service.js +1 -2
- package/dist/src/agent/agent-manager.d.ts +5 -0
- package/dist/src/agent/agent-manager.js +16 -6
- package/dist/src/agent/background-review/run-background-review.js +2 -3
- package/dist/src/agent/context/execution-context.js +1 -2
- package/dist/src/agent/context/execution-scope.js +1 -2
- package/dist/src/agent/context/project-context.js +1 -2
- package/dist/src/agent/embedded/agent-profile-context.js +1 -2
- package/dist/src/agent/embedded/run-turn.js +2 -4
- package/dist/src/agent/embedded/sqlite-hydrating-session-manager.js +1 -2
- package/dist/src/agent/embedded/tool-search-extension.js +14 -1
- package/dist/src/agent/external-tools/cliProvider.js +3 -4
- package/dist/src/agent/external-tools/composio-provider.js +3 -4
- package/dist/src/agent/external-tools/endpoint-provider.js +2 -2
- package/dist/src/agent/memory/compaction-promotion.js +1 -2
- package/dist/src/agent/orchestration/research-checkpoint.js +26 -31
- package/dist/src/agent/prompt/response-language.js +1 -2
- package/dist/src/agent/prompt/service-prompt-builder.js +3 -6
- package/dist/src/agent/prompt/system-prompt.js +1 -2
- package/dist/src/agent/service/direct-turn-helpers.js +1 -2
- package/dist/src/agent/service/process-direct-streaming.js +1 -2
- package/dist/src/agent/service/webchat-tts.js +1 -2
- package/dist/src/agent/service.d.ts +1 -0
- package/dist/src/agent/service.js +8 -3
- package/dist/src/agent/service.types.d.ts +3 -0
- package/dist/src/agent/skills/index.js +1 -1
- package/dist/src/agent/skills/managed-store.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +1 -1
- package/dist/src/agent/tool-manuals/computer.d.ts +1 -1
- package/dist/src/agent/tool-manuals/computer.js +2 -0
- package/dist/src/agent/tool-manuals/phone.d.ts +1 -1
- package/dist/src/agent/tool-manuals/phone.js +14 -4
- package/dist/src/agent/tool-manuals/xopc-configuration.d.ts +2 -0
- package/dist/src/agent/tool-manuals/xopc-configuration.js +29 -0
- package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +2 -0
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js +6 -2
- package/dist/src/agent/tools/delegate-tool.js +2 -4
- package/dist/src/agent/tools/factory.d.ts +4 -0
- package/dist/src/agent/tools/factory.js +23 -9
- package/dist/src/agent/tools/personal-read-tool.js +1 -1
- package/dist/src/agent/tools/personal-task-tool.js +1 -2
- package/dist/src/agent/tools/phone-use-tool.d.ts +2 -0
- package/dist/src/agent/tools/phone-use-tool.js +79 -4
- package/dist/src/agent/tools/research-checkpoint-tool.js +1 -2
- package/dist/src/agent/tools/tool-manual-tool.d.ts +1 -1
- package/dist/src/agent/tools/tool-manual-tool.js +3 -1
- package/dist/src/agent/tools/toolExposure.js +3 -0
- package/dist/src/agent/tools/xopc-use-tool.d.ts +5 -2
- package/dist/src/agent/tools/xopc-use-tool.js +47 -6
- package/dist/src/agent-catalog/capabilities.js +2 -2
- package/dist/src/agent-catalog/repository.js +3 -4
- package/dist/src/agent-catalog/test-support.js +1 -2
- package/dist/src/agent-matching/selection-repository.js +1 -2
- package/dist/src/automations/capabilities/drafts.js +3 -5
- package/dist/src/bootstrap/application-state.js +1 -2
- package/dist/src/browser/automations/repository.js +1 -2
- package/dist/src/browser/drivers/browser-driver.d.ts +2 -2
- package/dist/src/browser/drivers/extension-driver.d.ts +2 -2
- package/dist/src/browser/drivers/extension-driver.js +6 -3
- package/dist/src/browser/native-messaging-host.js +2 -4
- package/dist/src/browser/providers/browser-ext-install.js +3 -2
- package/dist/src/browser/providers/realtime-extension.js +1 -2
- package/dist/src/browser/recordings/service.js +1 -2
- package/dist/src/browser/runtime/browser-runtime.d.ts +4 -1
- package/dist/src/browser/runtime/browser-runtime.js +29 -17
- package/dist/src/browser/setup/repository.d.ts +5 -0
- package/dist/src/browser/setup/repository.js +42 -0
- package/dist/src/browser/setup/service.d.ts +157 -0
- package/dist/src/browser/setup/service.js +433 -0
- package/dist/src/browser/setup/types.d.ts +38 -0
- package/dist/src/browser/setup/types.js +1 -0
- package/dist/src/capabilities/runtime/dispatcher.js +1 -1
- package/dist/src/capabilities/runtime/product.js +1 -1
- package/dist/src/chat-previews/store.js +1 -2
- package/dist/src/cli/commands/agents.js +1 -1
- package/dist/src/cli/commands/doctor/checks/automation-integrity.js +1 -2
- package/dist/src/cli/commands/doctor/checks/database-relations.js +1 -2
- package/dist/src/cli/commands/doctor/checks/database-schema.js +2 -3
- package/dist/src/cli/commands/doctor/checks/node-version.js +6 -6
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -2
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/cli/commands/gateway/shared.js +1 -2
- package/dist/src/cli/commands/history.js +1 -2
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/onboard/model.js +1 -1
- package/dist/src/cli/commands/project.js +1 -2
- package/dist/src/cli/utils/init-workspace-core.js +1 -1
- package/dist/src/computer/diagnostics.d.ts +7 -7
- package/dist/src/computer/diagnostics.js +8 -2
- package/dist/src/computer/errors.js +9 -1
- package/dist/src/computer/evaluation.d.ts +4 -4
- package/dist/src/computer/keyboard.d.ts +1 -1
- package/dist/src/computer/keyboard.js +10 -2
- package/dist/src/computer/model-adapter.js +27 -7
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/gateway-bind.js +1 -2
- package/dist/src/config/schema.d.ts +7 -0
- package/dist/src/connectors/cli/lifecycle.js +1 -2
- package/dist/src/connectors/composio-managed-events.js +1 -2
- package/dist/src/connectors/connected-source-ingestion.js +1 -2
- package/dist/src/connectors/connected-source-understanding.js +3 -5
- package/dist/src/connectors/content-enrichment.js +1 -2
- package/dist/src/connectors/learning-coordinator.js +2 -3
- package/dist/src/connectors/runtime-adapter-registry.js +1 -2
- package/dist/src/daemon/constants.js +9 -14
- package/dist/src/daemon/index.js +1 -4
- package/dist/src/daemon/install-plan.js +1 -2
- package/dist/src/daemon/launchd.js +1 -2
- package/dist/src/daemon/schtasks.js +1 -2
- package/dist/src/daemon/service-audit.js +1 -2
- package/dist/src/daemon/service.js +1 -2
- package/dist/src/daemon/systemd.js +1 -2
- package/dist/src/discussions/analyzer.d.ts +3 -3
- package/dist/src/endpoint-tools/runtime.js +1 -2
- package/dist/src/execution-environments/local-worktree-manager.js +1 -1
- package/dist/src/execution-environments/subject.js +1 -2
- package/dist/src/extensions/agent-plugins/branding.js +2 -1
- package/dist/src/extensions/agent-plugins/cli-authorization.js +2 -1
- package/dist/src/extensions/agent-plugins/contained-path.d.ts +1 -0
- package/dist/src/extensions/agent-plugins/contained-path.js +29 -0
- package/dist/src/extensions/agent-plugins/mcp-adapter.js +2 -1
- package/dist/src/extensions/agent-plugins/resources.js +1 -1
- package/dist/src/extensions/agent-plugins/skill-catalog.js +3 -2
- package/dist/src/extensions/agent-plugins/source-catalog.js +1 -1
- package/dist/src/extensions/agent-plugins/store.js +2 -1
- package/dist/src/extensions/agent-plugins/validation.d.ts +1 -2
- package/dist/src/extensions/agent-plugins/validation.js +3 -26
- package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/agents-admin.js +2 -2
- package/dist/src/gateway/client-ip.js +1 -2
- package/dist/src/gateway/file-space-service.js +1 -2
- package/dist/src/gateway/global-defaults-admin.js +1 -1
- package/dist/src/gateway/hono/app.js +2 -4
- package/dist/src/gateway/hono/middleware/auth.js +3 -6
- package/dist/src/gateway/hono/middleware/logger.js +1 -2
- package/dist/src/gateway/hono/middleware/public-device-rate-limit.js +1 -2
- package/dist/src/gateway/hono/middleware/scopes.js +1 -2
- package/dist/src/gateway/hono/middleware/strict-rate-limit.js +1 -2
- package/dist/src/gateway/hono/oauth-async.js +1 -2
- package/dist/src/gateway/hono/routes/agents.js +1 -1
- package/dist/src/gateway/hono/routes/browser-session.js +1 -2
- package/dist/src/gateway/hono/routes/browser-setup.d.ts +3 -0
- package/dist/src/gateway/hono/routes/browser-setup.js +114 -0
- package/dist/src/gateway/hono/routes/browser.d.ts +2 -1
- package/dist/src/gateway/hono/routes/browser.js +4 -7
- package/dist/src/gateway/hono/routes/cli-connectors.js +1 -2
- package/dist/src/gateway/hono/routes/composer-history.js +1 -2
- package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
- package/dist/src/gateway/hono/routes/config.js +1 -2
- package/dist/src/gateway/hono/routes/connectors.js +9 -11
- package/dist/src/gateway/hono/routes/context-sources.js +1 -2
- package/dist/src/gateway/hono/routes/device-pairing-approval.js +2 -4
- package/dist/src/gateway/hono/routes/device-push.js +1 -2
- package/dist/src/gateway/hono/routes/devices.js +4 -8
- package/dist/src/gateway/hono/routes/discussions.js +1 -2
- package/dist/src/gateway/hono/routes/endpoint-tools.js +1 -2
- package/dist/src/gateway/hono/routes/home.js +2 -3
- package/dist/src/gateway/hono/routes/interaction-state.js +1 -2
- package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
- package/dist/src/gateway/hono/routes/memory-learning.js +1 -2
- package/dist/src/gateway/hono/routes/notes.js +2 -2
- package/dist/src/gateway/hono/routes/personal-agent.js +1 -2
- package/dist/src/gateway/hono/routes/phone-dependencies.js +2 -7
- package/dist/src/gateway/hono/routes/phone-setup.d.ts +7 -0
- package/dist/src/gateway/hono/routes/phone-setup.js +231 -0
- package/dist/src/gateway/hono/routes/phone-wireless.d.ts +4 -0
- package/dist/src/gateway/hono/routes/phone-wireless.js +63 -0
- package/dist/src/gateway/hono/routes/phone.js +119 -28
- package/dist/src/gateway/hono/routes/projects.js +3 -4
- package/dist/src/gateway/hono/routes/public-gateway.js +4 -3
- package/dist/src/gateway/hono/routes/session-input-handler.js +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +2 -4
- package/dist/src/gateway/hono/routes/shares.js +2 -4
- package/dist/src/gateway/hono/routes/tasks.js +2 -3
- package/dist/src/gateway/hono/routes/user-model-refresh.js +1 -2
- package/dist/src/gateway/hono/routes/user-model.js +1 -2
- package/dist/src/gateway/host.js +4 -9
- package/dist/src/gateway/image-generation-setup.js +1 -1
- package/dist/src/gateway/index.js +2 -6
- package/dist/src/gateway/listen.js +1 -2
- package/dist/src/gateway/next-turn-suggestions/service.js +1 -2
- package/dist/src/gateway/next-turn-suggestions/snapshot.js +1 -2
- package/dist/src/gateway/provider-model-setup.js +1 -1
- package/dist/src/gateway/rate-limit/auth-policy.js +11 -7
- package/dist/src/gateway/rate-limit/buckets.js +220 -211
- package/dist/src/gateway/rate-limit/env-flags.js +1 -4
- package/dist/src/gateway/rate-limit/index.js +4 -13
- package/dist/src/gateway/runtime-config.js +2 -4
- package/dist/src/gateway/security/audit.js +1 -2
- package/dist/src/gateway/security/browser-session.js +1 -2
- package/dist/src/gateway/security/device-request-proof.d.ts +1 -2
- package/dist/src/gateway/security/device-request-proof.js +2 -4
- package/dist/src/gateway/security/gateway-scopes.js +2 -6
- package/dist/src/gateway/security/index.js +1 -4
- package/dist/src/gateway/security/loopback.js +6 -7
- package/dist/src/gateway/service/agent-runner.js +2 -4
- package/dist/src/gateway/service/app-context-access.js +1 -2
- package/dist/src/gateway/service/config-coordinator.d.ts +4 -0
- package/dist/src/gateway/service/run-gateway-agent.js +2 -4
- package/dist/src/gateway/service/session-input-coordinator.js +3 -6
- package/dist/src/gateway/service.d.ts +5 -0
- package/dist/src/gateway/service.js +64 -22
- package/dist/src/gateway/session-context-summary.js +2 -4
- package/dist/src/gateway/tailscale-auth.js +1 -2
- package/dist/src/gateway/ws-security.js +1 -2
- package/dist/src/gateway/xopc-cloud-capability-setup.js +8 -2
- package/dist/src/home-intelligence/host.js +2 -2
- package/dist/src/imports/importService.js +1 -1
- package/dist/src/infra/rate-limit/failure-limiter.js +90 -78
- package/dist/src/infra/rate-limit/index.js +3 -11
- package/dist/src/infra/rate-limit/keyed-store.js +47 -52
- package/dist/src/infra/rate-limit/rate-limiter.js +58 -55
- package/dist/src/infra/update-restart.js +1 -1
- package/dist/src/infra/update-service-refresh.js +1 -2
- package/dist/src/knowledge/chunks.js +1 -4
- package/dist/src/knowledge/connected-knowledge-pipeline.js +3 -6
- package/dist/src/knowledge/ingestion-service.js +1 -2
- package/dist/src/knowledge-memory/repository.js +1 -2
- package/dist/src/local-apps/service.js +1 -1
- package/dist/src/local-apps/store.js +1 -2
- package/dist/src/media/session-references.js +1 -2
- package/dist/src/memory-learning/forget-capture.js +1 -2
- package/dist/src/memory-learning/forgotten-history.js +3 -6
- package/dist/src/memory-learning/service.js +1 -2
- package/dist/src/memory-learning/source-learning.js +3 -3
- package/dist/src/memory-learning/task-receipts.js +1 -2
- package/dist/src/memory-learning/work-candidate.d.ts +29 -0
- package/dist/src/memory-learning/work-candidate.js +31 -0
- package/dist/src/memory-learning/work-capture.d.ts +2 -29
- package/dist/src/memory-learning/work-capture.js +2 -30
- package/dist/src/memory-maintenance/service.js +1 -2
- package/dist/src/notes/agent-context.js +1 -2
- package/dist/src/notes/attachment-ref.js +4 -8
- package/dist/src/notes/note-attachment-sync.js +1 -2
- package/dist/src/notes/note-index-meta.js +7 -14
- package/dist/src/notes/note-markdown.js +7 -13
- package/dist/src/notes/service.js +3 -6
- package/dist/src/notes/store.js +2 -4
- package/dist/src/notifications/clarification.js +1 -2
- package/dist/src/notifications/service.js +1 -2
- package/dist/src/personal-agent/proactivity/repository.js +1 -2
- package/dist/src/personal-agent/proactivity/service.js +1 -2
- package/dist/src/personal-agent/prompt-context.js +1 -2
- package/dist/src/personal-agent/reply-composer.js +4 -5
- package/dist/src/personal-agent/repository.js +1 -2
- package/dist/src/personal-agent/request-delivery.js +1 -2
- package/dist/src/personal-agent/result-extraction.js +71 -71
- package/dist/src/personal-agent/service.js +2 -3
- package/dist/src/phone/adb-command.d.ts +1 -0
- package/dist/src/phone/adb-command.js +12 -0
- package/dist/src/phone/adb-driver.d.ts +6 -2
- package/dist/src/phone/adb-driver.js +45 -21
- package/dist/src/phone/cloud-adb-connection.d.ts +34 -0
- package/dist/src/phone/cloud-adb-connection.js +324 -0
- package/dist/src/phone/cloud-adb-writable.d.ts +3 -0
- package/dist/src/phone/cloud-adb-writable.js +21 -0
- package/dist/src/phone/cloud-adb.d.ts +3 -32
- package/dist/src/phone/cloud-adb.js +3 -259
- package/dist/src/phone/cloud-key-permissions.d.ts +2 -0
- package/dist/src/phone/cloud-key-permissions.js +66 -0
- package/dist/src/phone/cloud-phones.js +2 -1
- package/dist/src/phone/cloud-scrcpy.d.ts +1 -1
- package/dist/src/phone/cloud-scrcpy.js +3 -2
- package/dist/src/phone/contracts.d.ts +197 -1
- package/dist/src/phone/contracts.js +55 -6
- package/dist/src/phone/foreground.d.ts +1 -0
- package/dist/src/phone/foreground.js +18 -0
- package/dist/src/phone/live-state.d.ts +2 -0
- package/dist/src/phone/live-state.js +5 -0
- package/dist/src/phone/model-adapter.d.ts +65 -4
- package/dist/src/phone/model-adapter.js +157 -48
- package/dist/src/phone/numeric-entry.d.ts +31 -0
- package/dist/src/phone/numeric-entry.js +126 -0
- package/dist/src/phone/planning.d.ts +27 -0
- package/dist/src/phone/planning.js +79 -0
- package/dist/src/phone/recovery.d.ts +37 -0
- package/dist/src/phone/recovery.js +81 -0
- package/dist/src/phone/reliability.d.ts +2 -2
- package/dist/src/phone/reliability.js +19 -6
- package/dist/src/phone/repository.d.ts +4 -1
- package/dist/src/phone/repository.js +12 -1
- package/dist/src/phone/runtime.d.ts +79 -3
- package/dist/src/phone/runtime.js +861 -93
- package/dist/src/phone/scrcpy.js +3 -2
- package/dist/src/phone/semantic-controls.d.ts +13 -0
- package/dist/src/phone/semantic-controls.js +76 -0
- package/dist/src/phone/setup/service.d.ts +101 -0
- package/dist/src/phone/setup/service.js +296 -0
- package/dist/src/phone/task-feedback.d.ts +4 -0
- package/dist/src/phone/task-feedback.js +47 -0
- package/dist/src/phone/ui-dump-binary.d.ts +1 -0
- package/dist/src/phone/ui-dump-binary.js +4 -0
- package/dist/src/phone/wireless.d.ts +80 -0
- package/dist/src/phone/wireless.js +244 -0
- package/dist/src/projects/capabilities/write.js +1 -2
- package/dist/src/projects/project-service.js +1 -2
- package/dist/src/projects/workspace.js +1 -2
- package/dist/src/providers/presentation.js +2 -2
- package/dist/src/providers/xopc-cloud-model-source.js +6 -2
- package/dist/src/realtime/runtime.d.ts +3 -0
- package/dist/src/realtime/runtime.js +16 -3
- package/dist/src/remote-access/exposure-guards.js +1 -2
- package/dist/src/runtime-tools/archive.js +1 -1
- package/dist/src/runtime-tools/catalog.d.ts +1 -1
- package/dist/src/runtime-tools/catalog.js +2 -2
- package/dist/src/session/config-store.js +1 -2
- package/dist/src/session/init-session-turn.js +1 -2
- package/dist/src/session/resolve-session.js +1 -2
- package/dist/src/session/store.js +2 -4
- package/dist/src/share/share-rate-limit.js +1 -2
- package/dist/src/share/share-url.js +1 -2
- package/dist/src/share/site-share-router.js +1 -2
- package/dist/src/storage/sqlite/activity-repository.js +2 -6
- package/dist/src/storage/sqlite/browser-tab-binding-repository.js +2 -6
- package/dist/src/storage/sqlite/clarification-wait-repository.js +9 -14
- package/dist/src/storage/sqlite/collaboration-rule-repository.js +3 -8
- package/dist/src/storage/sqlite/composer-input-history-repository.js +3 -8
- package/dist/src/storage/sqlite/config-repository.js +5 -9
- package/dist/src/storage/sqlite/connector-learning-repository.js +2 -6
- package/dist/src/storage/sqlite/connector-sync-policy-repository.js +2 -6
- package/dist/src/storage/sqlite/context-evidence-repository.js +3 -8
- package/dist/src/storage/sqlite/context-extraction-repository.js +3 -8
- package/dist/src/storage/sqlite/device-access-repository.js +16 -23
- package/dist/src/storage/sqlite/device-pairing-approval.js +2 -6
- package/dist/src/storage/sqlite/device-pairing-repository.js +5 -10
- package/dist/src/storage/sqlite/endpoint-principal-repository.js +2 -6
- package/dist/src/storage/sqlite/endpoint-session-binding-repository.js +2 -6
- package/dist/src/storage/sqlite/endpoint-tool-invocation-repository.js +2 -6
- package/dist/src/storage/sqlite/gateway-identity-repository.js +2 -6
- package/dist/src/storage/sqlite/home-attention-repository.js +2 -6
- package/dist/src/storage/sqlite/index.js +40 -72
- package/dist/src/storage/sqlite/interaction-state-repository.js +4 -10
- package/dist/src/storage/sqlite/knowledge-repository.js +3 -8
- package/dist/src/storage/sqlite/note-agent-context-repository.js +2 -6
- package/dist/src/storage/sqlite/notes-repository.js +4 -9
- package/dist/src/storage/sqlite/research-checkpoint-repository.js +3 -8
- package/dist/src/storage/sqlite/schema.d.ts +2 -2
- package/dist/src/storage/sqlite/schema.js +7 -7
- package/dist/src/storage/sqlite/schema.sql +10 -0
- package/dist/src/storage/sqlite/session-creation-repository.js +2 -4
- package/dist/src/storage/sqlite/session-task-plan-repository.js +9 -14
- package/dist/src/storage/sqlite/session-turn-replace-repository.js +5 -9
- package/dist/src/storage/sqlite/sidebar-layout-repository.js +9 -14
- package/dist/src/storage/sqlite/transcript-repository.js +6 -10
- package/dist/src/storage/sqlite/upgrades/260_browser_setup.sql +9 -0
- package/dist/src/storage/sqlite/user-people-repository.js +3 -8
- package/dist/src/storage/sqlite/user-trust-repository.js +4 -9
- package/dist/src/tasks/capabilities/read.js +2 -2
- package/dist/src/tasks/capabilities/write.js +1 -1
- package/dist/src/tasks/execution-context.js +1 -2
- package/dist/src/tasks/home-query-service.js +1 -2
- package/dist/src/tasks/task-allocation-repository.js +1 -2
- package/dist/src/tasks/task-context-assembler.js +1 -2
- package/dist/src/tasks/task-handoff.js +2 -4
- package/dist/src/tasks/task-instruction-sequence.d.ts +1 -0
- package/dist/src/tasks/task-instruction-sequence.js +7 -0
- package/dist/src/tasks/task-language.js +1 -2
- package/dist/src/tasks/task-research-result.d.ts +1 -2
- package/dist/src/tasks/task-research-result.js +1 -3
- package/dist/src/tasks/task-result-delivery-repository.js +1 -1
- package/dist/src/tasks/task-result-delivery-service.js +3 -3
- package/dist/src/tasks/task-run-coordinator.js +3 -3
- package/dist/src/tasks/task-run-dispatcher.js +1 -2
- package/dist/src/tasks/task-value-metrics-service.js +1 -2
- package/dist/src/tui/backends/embedded-backend.js +2 -3
- package/dist/src/tui/tui-commands.js +1 -2
- package/dist/src/tunnel/registration-proof.js +1 -2
- package/dist/src/tunnel/tunnel-rate-limit.js +1 -2
- package/dist/src/user-context/access-policy.js +1 -2
- package/dist/src/user-context/domain.js +13 -18
- package/dist/src/user-context/extraction/registry.js +1 -2
- package/dist/src/user-context/interaction-state.js +1 -4
- package/dist/src/user-context/relationship-continuity.js +1 -2
- package/dist/src/user-context/sources/consent-repository.js +1 -2
- package/dist/src/user-context/sources/index.js +1 -1
- package/dist/src/user-context/trust-policy.js +8 -13
- package/dist/src/user-model/action-rule-suggestions.js +1 -2
- package/dist/src/user-model/bootstrap.js +1 -2
- package/dist/src/user-model/capture/executor.js +2 -4
- package/dist/src/user-model/capture/semantic.d.ts +1 -1
- package/dist/src/user-model/capture/semantic.js +1 -1
- package/dist/src/user-model/domain.js +30 -35
- package/dist/src/user-model/goals.js +1 -2
- package/dist/src/user-model/index.js +1 -4
- package/dist/src/user-model/observation-repository.js +1 -2
- package/dist/src/user-model/repository.js +1 -2
- package/dist/src/user-model/usage-policy.js +1 -2
- package/dist/src/voice/realtime/memory-context.js +1 -2
- package/dist/src/voice/realtime/persona-context.js +1 -1
- package/dist/src/work-discovery/service.js +4 -6
- package/package.json +8 -8
- package/skills/tools/configure-xopc/SKILL.md +54 -0
- package/skills/tools/configure-xopc/references/browser/acceptance.md +32 -0
- package/skills/tools/configure-xopc/references/browser/chrome-extension.md +23 -0
- package/skills/tools/configure-xopc/references/browser/overview.md +19 -0
- package/skills/tools/configure-xopc/references/browser/permissions.md +23 -0
- package/skills/tools/configure-xopc/references/browser/troubleshooting.md +24 -0
- package/skills/tools/configure-xopc/references/phone/acceptance.md +27 -0
- package/skills/tools/configure-xopc/references/phone/aliyun.md +29 -0
- package/skills/tools/configure-xopc/references/phone/dependencies.md +18 -0
- package/skills/tools/configure-xopc/references/phone/local.md +19 -0
- package/skills/tools/configure-xopc/references/phone/models.md +21 -0
- package/skills/tools/configure-xopc/references/phone/overview.md +25 -0
- package/skills/tools/configure-xopc/references/phone/troubleshooting.md +27 -0
- package/skills/tools/configure-xopc/references/scene-index.md +12 -0
- package/dist/gateway/static/root/assets/agent-avatar-dicebear-CJFwitU2.js +0 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-DclyJr1N.js +0 -1
- package/dist/gateway/static/root/assets/agents-jhErNtzi.js +0 -77
- package/dist/gateway/static/root/assets/app-management-settings-panel-DgwqNi5i.js +0 -1
- package/dist/gateway/static/root/assets/appearance-settings-C0wJfFyz.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-C0LcnI4h.js +0 -1
- package/dist/gateway/static/root/assets/automation-display-BFN7zWBg.js +0 -2
- package/dist/gateway/static/root/assets/automations-workspace-CBxiV34x.js +0 -8
- package/dist/gateway/static/root/assets/browser-automations-page-vJIrTxdi.js +0 -3
- package/dist/gateway/static/root/assets/browser-settings-page-in5Roh_E.js +0 -3
- package/dist/gateway/static/root/assets/capabilities-BlxF36t-.js +0 -1
- package/dist/gateway/static/root/assets/capabilities-page-CiGx8wpQ.js +0 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-a8kqjzQu.js +0 -8
- package/dist/gateway/static/root/assets/capability-header-actions-D4Yq35fD.js +0 -1
- package/dist/gateway/static/root/assets/channels-C_CxcjKT.js +0 -1
- package/dist/gateway/static/root/assets/chat-terminal-dock-zdMySdMm.js +0 -36
- package/dist/gateway/static/root/assets/chunk-KS7C4IRE-BvcCCgTW.js +0 -4
- package/dist/gateway/static/root/assets/cloud-credits-BMYMiiNn.js +0 -1
- package/dist/gateway/static/root/assets/computer-settings-page-C5Z6Jr0p.js +0 -1
- package/dist/gateway/static/root/assets/connector-service-page-Cxus0qrZ.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-DCBO2CxK.js +0 -1
- package/dist/gateway/static/root/assets/constants-DeXt1mV-.js +0 -1
- package/dist/gateway/static/root/assets/date-picker-DuyyD6jz.js +0 -1
- package/dist/gateway/static/root/assets/dependency-picker-BZN72rrk.js +0 -1
- package/dist/gateway/static/root/assets/desktop-pet-BtvTIDCi.js +0 -1
- package/dist/gateway/static/root/assets/desktop-pet-settings-BcyP7Z6v.js +0 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-Ctbgr50F.js +0 -1
- package/dist/gateway/static/root/assets/directory-picker-path-field-DOusKz-O.js +0 -1
- package/dist/gateway/static/root/assets/dist-C3DSFZCi.js +0 -1
- package/dist/gateway/static/root/assets/dist-CI_fqRk-.js +0 -1
- package/dist/gateway/static/root/assets/docx-preview-CajIk2FR.js +0 -20
- package/dist/gateway/static/root/assets/echarts-runtime-tcHc9TOS.js +0 -18
- package/dist/gateway/static/root/assets/electron-env-Dit0bHgy.js +0 -1
- package/dist/gateway/static/root/assets/extension-debug-page-Bt4FwsFu.js +0 -1
- package/dist/gateway/static/root/assets/extension-page-0vsxX3FB.js +0 -1
- package/dist/gateway/static/root/assets/extension-settings-page-5Pt5_ELc.js +0 -1
- package/dist/gateway/static/root/assets/files-Bw4SBGdM.js +0 -1
- package/dist/gateway/static/root/assets/floating-ui.dom-B7uQOZZW.js +0 -1
- package/dist/gateway/static/root/assets/gateway-realtime-DkWCHVzI.js +0 -1
- package/dist/gateway/static/root/assets/gateway-realtime-store-Bx9KCID-.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-BsVOcmV5.js +0 -1
- package/dist/gateway/static/root/assets/highlight-code-C8eS9949.js +0 -1
- package/dist/gateway/static/root/assets/highlighted-body-KQOG7T2V-Cbk7eMlg.js +0 -1
- package/dist/gateway/static/root/assets/home-page-BZDZnmyc.js +0 -2
- package/dist/gateway/static/root/assets/image-generation-api-CAS8QVla.js +0 -1
- package/dist/gateway/static/root/assets/imports-page-BCLBYzV1.js +0 -1
- package/dist/gateway/static/root/assets/index-Bys6njTY.js +0 -710
- package/dist/gateway/static/root/assets/index-Vsf0bj5e.css +0 -1
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-CM_kt5XN.js +0 -1
- package/dist/gateway/static/root/assets/languages-byq_L2Ae.js +0 -2
- package/dist/gateway/static/root/assets/local-app-workbench-page-Dk87jtcc.js +0 -1
- package/dist/gateway/static/root/assets/local-apps-page-BTSOChhk.js +0 -1
- package/dist/gateway/static/root/assets/local-apps-yys1VChX.js +0 -1
- package/dist/gateway/static/root/assets/local-session-drafts-iGX_6O0O.js +0 -1
- package/dist/gateway/static/root/assets/logs-page-D3gVdm8S.js +0 -2
- package/dist/gateway/static/root/assets/management-settings-BQNYFE4J.js +0 -1
- package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-ChweJKTv.js +0 -1
- package/dist/gateway/static/root/assets/note-detail-panel-CYKwUCte.js +0 -5
- package/dist/gateway/static/root/assets/note-image-lightbox-BTSZb9ZT.js +0 -1
- package/dist/gateway/static/root/assets/notes-page-CJ5nhWfL.js +0 -8
- package/dist/gateway/static/root/assets/number-input-DDeqHK-G.js +0 -1
- package/dist/gateway/static/root/assets/page-context-capture-button-DVn_dU83.js +0 -1
- package/dist/gateway/static/root/assets/pdf-runtime-DU_sMPjG.js +0 -2
- package/dist/gateway/static/root/assets/personal-page-DcW14lqn.js +0 -1
- package/dist/gateway/static/root/assets/personal-proactivity-BJcZ3Yhi.js +0 -1
- package/dist/gateway/static/root/assets/personal-settings-panel-C16Iqe7X.js +0 -1
- package/dist/gateway/static/root/assets/phone-dependencies-card-D3l9uPFM.js +0 -1
- package/dist/gateway/static/root/assets/phone-model-picker-DOv38vBn.js +0 -1
- package/dist/gateway/static/root/assets/phone-settings-page-DUHp1q_9.js +0 -1
- package/dist/gateway/static/root/assets/plugin-details-dialog-BpfgDlVa.js +0 -1
- package/dist/gateway/static/root/assets/popover-select-DGKUpVsz.js +0 -1
- package/dist/gateway/static/root/assets/preload-helper-zJ_50EbN.js +0 -1
- package/dist/gateway/static/root/assets/preview-open-alternatives-RlHk76TI.js +0 -1
- package/dist/gateway/static/root/assets/product-delivery-BqNm-8S5.js +0 -1
- package/dist/gateway/static/root/assets/product-open-page-Dh-HqLrE.js +0 -1
- package/dist/gateway/static/root/assets/product-preview-content-c3K-4DWc.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-GD8TxKad.js +0 -7
- package/dist/gateway/static/root/assets/projects-page-B8HAt9sD.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-D3el7lHK.js +0 -1
- package/dist/gateway/static/root/assets/runtime-tools-settings-panel-Dbskk6RG.js +0 -1
- package/dist/gateway/static/root/assets/schema-form-CXO1B1k4.js +0 -1
- package/dist/gateway/static/root/assets/schemas-CObaziC7.js +0 -64
- package/dist/gateway/static/root/assets/session-manager-CA1NkTR_.js +0 -16
- package/dist/gateway/static/root/assets/sessions-page-07liaSHH.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BGjU8rfN.js +0 -1
- package/dist/gateway/static/root/assets/settings-form-section-BQxKmbbJ.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-DvVMpKiA.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-header-CYpuTXUW.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-layout-B20AfmFG.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-DKo_VTx-.js +0 -1
- package/dist/gateway/static/root/assets/share-preview-page-XgZk8Oa1.js +0 -2
- package/dist/gateway/static/root/assets/shares-settings-BODFqK8k.js +0 -1
- package/dist/gateway/static/root/assets/skill-api-CV-WT2hj.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-Ce6OUk2C.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-B7ehOIML.js +0 -2
- package/dist/gateway/static/root/assets/specialists-4bkS5rZ4.js +0 -1
- package/dist/gateway/static/root/assets/system-settings-panel-CxJkZRT4.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-CxRR0QuW.js +0 -2
- package/dist/gateway/static/root/assets/task-result-evidence-D-gGKNX9.js +0 -1
- package/dist/gateway/static/root/assets/tasks-TVRjEggr.js +0 -1
- package/dist/gateway/static/root/assets/tracing-settings-page-CQw3G-FB.js +0 -1
- package/dist/gateway/static/root/assets/tunnel-api-B2HnCi0U.js +0 -1
- package/dist/gateway/static/root/assets/usage-page-uUEkO38r.js +0 -1
- package/dist/gateway/static/root/assets/use-autosave-Dc0nwUpX.js +0 -1
- package/dist/gateway/static/root/assets/user-model-page-ICUutbKL.js +0 -2
- package/dist/gateway/static/root/assets/voice-api-key-field-BSWXZkGa.js +0 -1
- package/dist/gateway/static/root/assets/work-discovery-overlay-H3cdwq3l.js +0 -1
- package/dist/gateway/static/root/assets/xopc-cloud-account-card-CvT_W6YS.js +0 -1
|
@@ -3,44 +3,84 @@ import { init_logger } from "../utils/logger.js";
|
|
|
3
3
|
import { MOCK_PHONE_MODEL, PhoneError, PhoneInputSchema, init_contracts } from "./contracts.js";
|
|
4
4
|
import { resolveEffectiveAgentConfigForAgent } from "../config/agent-profile.js";
|
|
5
5
|
import { phoneAllowsApp, phoneAppAccess } from "./app-access.js";
|
|
6
|
+
import { nativePhoneOutput, updatePhoneFeedback } from "./task-feedback.js";
|
|
6
7
|
import { PhoneFrameCache, PhoneOperationBudget } from "./live-state.js";
|
|
7
8
|
import { PhoneInteractiveSession } from "./interactive-session.js";
|
|
8
|
-
import { AdbPhoneDriver, resolveAdbPath } from "./adb-driver.js";
|
|
9
9
|
import { LocalScrcpyProvider } from "./scrcpy.js";
|
|
10
|
+
import { AdbPhoneDriver, resolveAdbPath } from "./adb-driver.js";
|
|
10
11
|
import { CloudPhones } from "./cloud-phones.js";
|
|
12
|
+
import { WirelessPhones } from "./wireless.js";
|
|
13
|
+
import { advancePhonePlan, buildPhonePlan, createPhonePlanState } from "./planning.js";
|
|
14
|
+
import { canDispatchPhoneAction, observationSignature, phoneCompletionSatisfied } from "./reliability.js";
|
|
15
|
+
import { groundPhoneCoordinateAction, resolvePhoneSemanticAction } from "./semantic-controls.js";
|
|
11
16
|
import { createPhoneModel, isAboutScreen } from "./model-adapter.js";
|
|
12
17
|
import { PhoneRepository } from "./repository.js";
|
|
13
|
-
import {
|
|
18
|
+
import { confirmPhoneFocusRecovery, phoneBackRecovery, phoneUnfocusedTypingHint, preparePhoneFocusRecovery } from "./recovery.js";
|
|
19
|
+
import { createPhoneNumericEntry, nextPhoneNumericEntry } from "./numeric-entry.js";
|
|
14
20
|
import { createHash, randomUUID } from "node:crypto";
|
|
21
|
+
import { setTimeout } from "node:timers/promises";
|
|
15
22
|
//#region src/phone/runtime.ts
|
|
16
23
|
init_logger();
|
|
17
24
|
init_contracts();
|
|
25
|
+
const VIEW_MODEL = "phone-view-only";
|
|
18
26
|
const log = createLogger("PhoneRuntime");
|
|
19
|
-
const terminal = new Set([
|
|
20
|
-
"cancelled",
|
|
21
|
-
"closed",
|
|
22
|
-
"failed",
|
|
23
|
-
"outcome_unknown"
|
|
24
|
-
]);
|
|
27
|
+
const terminal = new Set(["closed"]);
|
|
25
28
|
var PhoneRuntime = class {
|
|
29
|
+
reconnecting = /* @__PURE__ */ new Map();
|
|
30
|
+
reconnectAfter = /* @__PURE__ */ new Map();
|
|
26
31
|
cloudPhones;
|
|
27
32
|
get cloud() {
|
|
28
33
|
return this.cloudPhones ??= new CloudPhones(this.repository);
|
|
29
34
|
}
|
|
30
35
|
sessions = /* @__PURE__ */ new Map();
|
|
36
|
+
lastDevices = /* @__PURE__ */ new Map();
|
|
31
37
|
openings = /* @__PURE__ */ new Map();
|
|
38
|
+
deviceOpenings = /* @__PURE__ */ new Map();
|
|
32
39
|
maintenance;
|
|
33
|
-
constructor(repository = new PhoneRepository(), driverFactory = (path) => new AdbPhoneDriver(path), modelFactory = createPhoneModel, interactiveFactory = (adb, serial, failed) => new LocalScrcpyProvider(adb, serial, failed)) {
|
|
40
|
+
constructor(repository = new PhoneRepository(), driverFactory = (path) => new AdbPhoneDriver(path), modelFactory = createPhoneModel, interactiveFactory = (adb, serial, failed) => new LocalScrcpyProvider(adb, serial, failed), wireless = new WirelessPhones()) {
|
|
34
41
|
this.repository = repository;
|
|
35
42
|
this.driverFactory = driverFactory;
|
|
36
43
|
this.modelFactory = modelFactory;
|
|
37
44
|
this.interactiveFactory = interactiveFactory;
|
|
45
|
+
this.wireless = wireless;
|
|
38
46
|
}
|
|
39
47
|
async driverFor(device, config) {
|
|
40
48
|
return device.connection ? this.cloud.driver(device) : this.driverFactory(resolveAdbPath(config.phone.adbPath));
|
|
41
49
|
}
|
|
42
50
|
async discover(config, signal) {
|
|
43
|
-
|
|
51
|
+
const driver = this.driverFactory(resolveAdbPath(config.phone.adbPath));
|
|
52
|
+
let devices = await driver.discover(signal);
|
|
53
|
+
const missing = this.repository.list().filter((device) => device.enabled && device.wireless && !devices.some((item) => item.serial === device.serial && item.state === "device") && (this.reconnectAfter.get(device.id) ?? 0) < Date.now()).slice(0, 2);
|
|
54
|
+
const reconnectSignal = AbortSignal.any([AbortSignal.timeout(5e3), ...signal ? [signal] : []]);
|
|
55
|
+
await Promise.all(missing.map(async (device) => {
|
|
56
|
+
this.reconnectAfter.set(device.id, Date.now() + 3e4);
|
|
57
|
+
await this.reconnectWireless(device.id, config, reconnectSignal).catch(() => {
|
|
58
|
+
signal?.throwIfAborted();
|
|
59
|
+
});
|
|
60
|
+
}));
|
|
61
|
+
if (missing.length) devices = await driver.discover(signal);
|
|
62
|
+
return devices;
|
|
63
|
+
}
|
|
64
|
+
reconnectWireless(id, config, signal, endpoint) {
|
|
65
|
+
const active = this.reconnecting.get(id);
|
|
66
|
+
if (active) return active;
|
|
67
|
+
const task = (async () => {
|
|
68
|
+
const device = this.repository.get(id);
|
|
69
|
+
if (!device.wireless || device.connection) throw new PhoneError("PHONE_NOT_WIRELESS", "Choose a registered wireless phone");
|
|
70
|
+
if (!device.enabled) throw new PhoneError("PHONE_DEVICE_DENIED", "Phone access is disabled", 403);
|
|
71
|
+
await Promise.all(this.reports().filter((report) => report.deviceId === id).map((report) => this.stop(report.owner, "close")));
|
|
72
|
+
this.cloudPhones?.disconnect(id);
|
|
73
|
+
const result = await this.wireless.reconnect(resolveAdbPath(config.phone.adbPath), device.wireless, signal, endpoint);
|
|
74
|
+
const current = this.repository.get(id);
|
|
75
|
+
if (current.revision !== device.revision) throw new PhoneError("PHONE_DEVICE_CHANGED", "Phone settings changed; retry connection", 409);
|
|
76
|
+
return this.repository.save({
|
|
77
|
+
...current,
|
|
78
|
+
serial: result.device.serial,
|
|
79
|
+
wireless: result.wireless
|
|
80
|
+
}, id);
|
|
81
|
+
})().finally(() => this.reconnecting.delete(id));
|
|
82
|
+
this.reconnecting.set(id, task);
|
|
83
|
+
return task;
|
|
44
84
|
}
|
|
45
85
|
async applications(input, config, signal) {
|
|
46
86
|
let driver;
|
|
@@ -72,6 +112,21 @@ var PhoneRuntime = class {
|
|
|
72
112
|
async preview(id, config, signal) {
|
|
73
113
|
const device = this.repository.get(id);
|
|
74
114
|
if (!device.enabled) throw new PhoneError("PHONE_DEVICE_DENIED", "Phone access is disabled", 403);
|
|
115
|
+
const connected = [...this.sessions.values()].find((session) => session.device.id === id && session.report.status !== "closed");
|
|
116
|
+
if (connected) {
|
|
117
|
+
this.guard(connected, {
|
|
118
|
+
...connected.context,
|
|
119
|
+
config
|
|
120
|
+
});
|
|
121
|
+
const observation = await this.observe(connected, signal);
|
|
122
|
+
try {
|
|
123
|
+
this.allowedScreen(connected, observation);
|
|
124
|
+
return observation;
|
|
125
|
+
} catch (error) {
|
|
126
|
+
observation.frame.fill(0);
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
75
130
|
const lease = this.repository.acquire(device.serial);
|
|
76
131
|
try {
|
|
77
132
|
const observation = await (await this.driverFor(device, config)).observe(device.serial, signal);
|
|
@@ -87,7 +142,6 @@ var PhoneRuntime = class {
|
|
|
87
142
|
async previewSession(owner, context, signal) {
|
|
88
143
|
const session = this.sessions.get(owner);
|
|
89
144
|
if (!session || terminal.has(session.report.status)) throw new PhoneError("PHONE_OPEN_REQUIRED", "Open a phone session first");
|
|
90
|
-
if (session.active) throw new PhoneError("PHONE_SESSION_BUSY", "Pause the task before previewing", 409);
|
|
91
145
|
this.guard(session, context);
|
|
92
146
|
const observation = await this.observe(session, signal);
|
|
93
147
|
try {
|
|
@@ -105,7 +159,56 @@ var PhoneRuntime = class {
|
|
|
105
159
|
const report = this.sessions.get(owner)?.report;
|
|
106
160
|
return report && structuredClone(report);
|
|
107
161
|
}
|
|
162
|
+
deviceContext(id, config) {
|
|
163
|
+
const session = [...this.sessions.values()].find((session) => session.device.id === id && session.report.status !== "closed");
|
|
164
|
+
if (!session) throw new PhoneError("PHONE_SESSION_NOT_FOUND", "Phone is not connected", 404);
|
|
165
|
+
return {
|
|
166
|
+
...session.context,
|
|
167
|
+
config
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
async viewDevice(id, config, agentId, signal) {
|
|
171
|
+
if ([...this.sessions.values()].some((session) => session.device.id === id && session.report.status !== "closed")) return;
|
|
172
|
+
const owner = `phone-view:${id}`;
|
|
173
|
+
await this.execute(owner, {
|
|
174
|
+
op: "open",
|
|
175
|
+
deviceId: id,
|
|
176
|
+
mode: "observe"
|
|
177
|
+
}, {
|
|
178
|
+
config,
|
|
179
|
+
agentId,
|
|
180
|
+
modelRef: VIEW_MODEL
|
|
181
|
+
}, signal);
|
|
182
|
+
await this.finishTask(owner);
|
|
183
|
+
}
|
|
184
|
+
updateConnectionPolicy(config) {
|
|
185
|
+
for (const session of this.sessions.values()) session.context = {
|
|
186
|
+
...session.context,
|
|
187
|
+
config
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
async releaseConversation(owner) {
|
|
191
|
+
const session = this.sessions.get(owner);
|
|
192
|
+
if (!session || session.report.status === "closed") return;
|
|
193
|
+
if (this.deviceOpenings.has(session.device.id)) return;
|
|
194
|
+
if (session.active) {
|
|
195
|
+
await this.stop(owner, "cancel");
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (!session.human && ![
|
|
199
|
+
"paused",
|
|
200
|
+
"needs_user",
|
|
201
|
+
"failed",
|
|
202
|
+
"outcome_unknown"
|
|
203
|
+
].includes(session.report.status)) await this.finishTask(owner);
|
|
204
|
+
}
|
|
108
205
|
publish(session) {
|
|
206
|
+
session.report.nextExecutionMode = this.repository.executionMode(session.report.owner) ?? session.context.config.phone.executionMode;
|
|
207
|
+
if (session.report.feedback && session.segmentUsage) session.report.feedback = updatePhoneFeedback(session.report, {
|
|
208
|
+
actions: session.report.actions - session.segmentUsage.actions,
|
|
209
|
+
modelRequests: session.report.modelRequests - session.segmentUsage.modelRequests,
|
|
210
|
+
activeDurationMs: session.segmentUsage.activeDurationMs + (session.budget?.elapsedMs ?? 0)
|
|
211
|
+
}, session.report.feedback);
|
|
109
212
|
session.report.updatedAt = Date.now();
|
|
110
213
|
this.repository.report(session.report);
|
|
111
214
|
return structuredClone(session.report);
|
|
@@ -114,7 +217,6 @@ var PhoneRuntime = class {
|
|
|
114
217
|
if (!context.config.phone.enabled || context.toolDenied) throw new PhoneError("PHONE_DISABLED", "Phone Use is disabled for this agent");
|
|
115
218
|
if (context.modelRef !== session.modelRef || resolveAdbPath(context.config.phone.adbPath) !== session.adbPath) throw new PhoneError("PHONE_BINDING_CHANGED", "Phone model or execution configuration changed; reopen the phone");
|
|
116
219
|
if (context.validateBinding && !context.validateBinding()) throw new PhoneError("PHONE_BINDING_CHANGED", "Agent model or tool policy changed; reopen the phone");
|
|
117
|
-
if (Date.now() - session.createdAt >= context.config.phone.maxSessionDurationMs) throw new PhoneError("PHONE_SESSION_LIMIT", "Phone session duration limit reached");
|
|
118
220
|
const current = this.repository.get(session.device.id);
|
|
119
221
|
if (!current.enabled || current.revision !== session.device.revision) throw new PhoneError("PHONE_ACCESS_CHANGED", "Device access changed; reopen the phone");
|
|
120
222
|
this.repository.renew(session.device.serial, session.lease);
|
|
@@ -124,6 +226,7 @@ var PhoneRuntime = class {
|
|
|
124
226
|
}
|
|
125
227
|
async execute(owner, raw, context, signal = new AbortController().signal) {
|
|
126
228
|
const input = PhoneInputSchema.parse(raw);
|
|
229
|
+
if (input.op === "close") return this.finishTask(owner);
|
|
127
230
|
if ([
|
|
128
231
|
"cancel",
|
|
129
232
|
"close",
|
|
@@ -131,35 +234,151 @@ var PhoneRuntime = class {
|
|
|
131
234
|
].includes(input.op)) return this.stop(owner, input.op);
|
|
132
235
|
if (input.op === "status") return this.status(owner) ?? { status: "closed" };
|
|
133
236
|
if (!context.config.phone.enabled || context.toolDenied) throw new PhoneError("PHONE_DISABLED", "Enable Phone Use in settings and allow the tool for this agent");
|
|
237
|
+
if (input.op === "set_mode") return {
|
|
238
|
+
executionMode: input.executionMode,
|
|
239
|
+
report: await this.setExecutionMode(owner, input.executionMode, context, input.applyCurrent)
|
|
240
|
+
};
|
|
134
241
|
if (input.op === "discover") return {
|
|
242
|
+
executionMode: this.repository.executionMode(owner) ?? context.config.phone.executionMode,
|
|
135
243
|
devices: this.repository.list().filter((device) => device.enabled),
|
|
136
|
-
defaultDeviceId: this.repository.defaultDevice()
|
|
244
|
+
defaultDeviceId: context.preferredDeviceId ?? this.repository.defaultDevice(),
|
|
245
|
+
systemDefaultDeviceId: this.repository.defaultDevice()
|
|
137
246
|
};
|
|
138
247
|
signal.throwIfAborted();
|
|
139
248
|
if (input.op === "open") {
|
|
249
|
+
const requestedDevice = input.deviceId ?? context.preferredDeviceId ?? this.repository.defaultDevice();
|
|
250
|
+
if (requestedDevice && this.deviceOpenings.has(requestedDevice)) throw this.busy(requestedDevice);
|
|
140
251
|
if (this.openings.has(owner)) throw new PhoneError("PHONE_SESSION_BUSY", "A phone is already being opened", 409);
|
|
141
252
|
const opening = new AbortController();
|
|
142
253
|
this.openings.set(owner, opening);
|
|
254
|
+
if (requestedDevice) this.deviceOpenings.set(requestedDevice, opening);
|
|
143
255
|
signal = AbortSignal.any([signal, opening.signal]);
|
|
144
256
|
try {
|
|
145
257
|
for (const [key, value] of this.sessions) if (terminal.has(value.report.status)) this.sessions.delete(key);
|
|
146
|
-
if (this.sessions.size >= 50) throw new PhoneError("PHONE_CAPACITY", "
|
|
258
|
+
if (this.sessions.size >= 50 && ![...this.sessions.values()].some((session) => session.device.id === requestedDevice)) throw new PhoneError("PHONE_CAPACITY", "Disconnect an idle phone in the global phone panel before opening another", 409);
|
|
147
259
|
const previous = this.sessions.get(owner);
|
|
148
|
-
|
|
149
|
-
const deviceId = input.deviceId ?? this.repository.defaultDevice();
|
|
260
|
+
const deviceId = requestedDevice;
|
|
150
261
|
if (!deviceId) throw new PhoneError("PHONE_DEVICE_REQUIRED", "Choose a registered phone in Phone Use settings");
|
|
151
|
-
|
|
262
|
+
if (previous && !terminal.has(previous.report.status) && previous.device.id !== deviceId) {
|
|
263
|
+
if (previous.active || previous.human || previous.report.controlOwner !== "none" || !["ready", "completed"].includes(previous.report.status)) throw this.busy(previous.device.id, previous);
|
|
264
|
+
}
|
|
265
|
+
let device = this.repository.get(deviceId);
|
|
152
266
|
if (!device.enabled) throw new PhoneError("PHONE_DEVICE_DENIED", "This phone is disabled", 403);
|
|
153
267
|
const modelRef = context.modelRef;
|
|
154
268
|
if (!modelRef) throw new PhoneError("PHONE_MODEL_REQUIRED", "Choose a Phone Use model in settings");
|
|
269
|
+
if (input.appPackage && (input.mode !== "control" || !phoneAllowsApp(device, input.appPackage))) throw new PhoneError("PHONE_APP_DENIED", "Launching requires control mode and an allowed application");
|
|
270
|
+
const connected = [...this.sessions.values()].find((value) => value.device.id === deviceId && !terminal.has(value.report.status));
|
|
271
|
+
if (connected) {
|
|
272
|
+
if (connected.active || connected.human || connected.report.handoff !== "idle" || [
|
|
273
|
+
"paused",
|
|
274
|
+
"needs_user",
|
|
275
|
+
"failed",
|
|
276
|
+
"outcome_unknown"
|
|
277
|
+
].includes(connected.report.status) || connected.report.owner !== owner && !["completed", "ready"].includes(connected.report.status) || connected.report.owner !== owner && connected.report.controlOwner !== "none") throw this.busy(deviceId, connected);
|
|
278
|
+
if (connected.report.owner === owner && connected.report.controlOwner !== "none") {
|
|
279
|
+
this.guard(connected, context);
|
|
280
|
+
if (connected.report.mode !== input.mode) throw new PhoneError("PHONE_ALREADY_OPEN", "Finish the current task before changing phone mode", 409);
|
|
281
|
+
if (input.appPackage) {
|
|
282
|
+
const observation = await this.observe(connected, signal);
|
|
283
|
+
try {
|
|
284
|
+
await this.dispatch(connected, {
|
|
285
|
+
type: "launch",
|
|
286
|
+
package: input.appPackage
|
|
287
|
+
}, observation, context, signal, connected.report.controlEpoch, false, input.settingsPage);
|
|
288
|
+
} finally {
|
|
289
|
+
observation.frame.fill(0);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return this.publish(connected);
|
|
293
|
+
}
|
|
294
|
+
const adapter = await this.modelFactory(modelRef, context.config, context.agentId);
|
|
295
|
+
signal.throwIfAborted();
|
|
296
|
+
this.guard(connected, connected.context);
|
|
297
|
+
if (input.mode === "control" && modelRef !== "phone-mock/settings-about" && !connected.applications.length && connected.driver.applications) try {
|
|
298
|
+
connected.applications = await connected.driver.applications(device.serial, signal);
|
|
299
|
+
} catch {
|
|
300
|
+
signal.throwIfAborted();
|
|
301
|
+
}
|
|
302
|
+
await connected.streamOpening?.catch(() => {});
|
|
303
|
+
await connected.stream?.revoke();
|
|
304
|
+
await connected.io;
|
|
305
|
+
signal.throwIfAborted();
|
|
306
|
+
this.guard(connected, connected.context);
|
|
307
|
+
this.sessions.delete(connected.report.owner);
|
|
308
|
+
if (previous && previous !== connected) {
|
|
309
|
+
this.sessions.delete(owner);
|
|
310
|
+
previous.report.owner = `phone-view:${previous.device.id}`;
|
|
311
|
+
this.sessions.set(previous.report.owner, previous);
|
|
312
|
+
}
|
|
313
|
+
connected.report.owner = owner;
|
|
314
|
+
connected.report.agentId = context.agentId;
|
|
315
|
+
connected.report.modelRef = modelRef;
|
|
316
|
+
connected.report.sourceConversationId = /^[\da-f]{8}-[\da-f-]{27}$/i.test(owner) ? owner : void 0;
|
|
317
|
+
connected.report.mode = input.mode;
|
|
318
|
+
connected.report.mock = modelRef === MOCK_PHONE_MODEL;
|
|
319
|
+
connected.report.status = "ready";
|
|
320
|
+
connected.report.controlOwner = "agent";
|
|
321
|
+
connected.report.controlEpoch++;
|
|
322
|
+
connected.report.actions = 0;
|
|
323
|
+
connected.report.modelRequests = 0;
|
|
324
|
+
connected.report.steps = [];
|
|
325
|
+
connected.report.humanActions = 0;
|
|
326
|
+
connected.report.verified = false;
|
|
327
|
+
connected.report.verificationLevel = "none";
|
|
328
|
+
connected.report.stopReason = void 0;
|
|
329
|
+
connected.report.errorCode = void 0;
|
|
330
|
+
connected.report.message = void 0;
|
|
331
|
+
connected.report.facts = void 0;
|
|
332
|
+
connected.report.readings = void 0;
|
|
333
|
+
connected.report.task = void 0;
|
|
334
|
+
connected.report.feedback = void 0;
|
|
335
|
+
connected.report.executionMode = void 0;
|
|
336
|
+
connected.segmentUsage = void 0;
|
|
337
|
+
connected.taskActiveMs = 0;
|
|
338
|
+
connected.taskStart = void 0;
|
|
339
|
+
connected.modeHandbackRequired = false;
|
|
340
|
+
connected.report.goalPreview = void 0;
|
|
341
|
+
connected.adapter = adapter;
|
|
342
|
+
connected.context = context;
|
|
343
|
+
connected.modelRef = modelRef;
|
|
344
|
+
connected.controller = new AbortController();
|
|
345
|
+
connected.createdAt = Date.now();
|
|
346
|
+
connected.taskPending = false;
|
|
347
|
+
connected.trajectory = [];
|
|
348
|
+
connected.trajectoryCount = 0;
|
|
349
|
+
connected.trajectorySummary = [];
|
|
350
|
+
connected.frames.clear();
|
|
351
|
+
connected.receipts.clear();
|
|
352
|
+
this.sessions.set(owner, connected);
|
|
353
|
+
this.lastDevices.set(owner, deviceId);
|
|
354
|
+
if (input.appPackage) {
|
|
355
|
+
if (input.mode !== "control" || !phoneAllowsApp(device, input.appPackage)) throw new PhoneError("PHONE_APP_DENIED", "Launching requires control mode and an allowed application");
|
|
356
|
+
const observation = await this.observe(connected, signal);
|
|
357
|
+
try {
|
|
358
|
+
await this.dispatch(connected, {
|
|
359
|
+
type: "launch",
|
|
360
|
+
package: input.appPackage
|
|
361
|
+
}, observation, context, signal, connected.report.controlEpoch, false, input.settingsPage);
|
|
362
|
+
} finally {
|
|
363
|
+
observation.frame.fill(0);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return this.publish(connected);
|
|
367
|
+
}
|
|
155
368
|
const adbPath = resolveAdbPath(context.config.phone.adbPath);
|
|
156
369
|
const driver = await this.driverFor(device, context.config);
|
|
157
|
-
|
|
370
|
+
let found = (await driver.discover(signal)).find((item) => item.serial === device.serial);
|
|
371
|
+
if (found?.state !== "device" && device.wireless) {
|
|
372
|
+
device = await this.reconnectWireless(device.id, context.config, signal);
|
|
373
|
+
found = (await driver.discover(signal)).find((item) => item.serial === device.serial);
|
|
374
|
+
}
|
|
158
375
|
if (found?.state !== "device") throw new PhoneError("PHONE_DEVICE_OFFLINE", "Phone is offline or has not authorized ADB");
|
|
159
376
|
if (modelRef === "phone-mock/settings-about" && !found.emulator) throw new PhoneError("PHONE_MOCK_EMULATOR_ONLY", "The deterministic mock model is only enabled for local Android emulators");
|
|
160
377
|
const lease = this.repository.acquire(device.serial);
|
|
161
378
|
try {
|
|
162
|
-
const adapter =
|
|
379
|
+
const adapter = modelRef === VIEW_MODEL ? { predict: async () => {
|
|
380
|
+
throw new PhoneError("PHONE_OBSERVE_ONLY", "This connection is view only", 403);
|
|
381
|
+
} } : await this.modelFactory(modelRef, context.config, context.agentId);
|
|
163
382
|
signal.throwIfAborted();
|
|
164
383
|
let applications = [];
|
|
165
384
|
if (input.mode === "control" && modelRef !== "phone-mock/settings-about" && driver.applications) try {
|
|
@@ -196,6 +415,7 @@ var PhoneRuntime = class {
|
|
|
196
415
|
owner,
|
|
197
416
|
agentId: context.agentId,
|
|
198
417
|
modelRef,
|
|
418
|
+
sourceConversationId: /^[\da-f]{8}-[\da-f-]{27}$/i.test(owner) ? owner : void 0,
|
|
199
419
|
mock: modelRef === MOCK_PHONE_MODEL,
|
|
200
420
|
mode: input.mode,
|
|
201
421
|
status: "ready",
|
|
@@ -217,7 +437,15 @@ var PhoneRuntime = class {
|
|
|
217
437
|
}
|
|
218
438
|
}
|
|
219
439
|
};
|
|
440
|
+
if (previous && previous.device.id !== deviceId) {
|
|
441
|
+
this.sessions.delete(owner);
|
|
442
|
+
previous.report.owner = `phone-view:${previous.device.id}`;
|
|
443
|
+
this.sessions.set(previous.report.owner, previous);
|
|
444
|
+
}
|
|
220
445
|
this.sessions.set(owner, session);
|
|
446
|
+
this.lastDevices.set(owner, deviceId);
|
|
447
|
+
if (this.lastDevices.size > 500) this.lastDevices.delete(this.lastDevices.keys().next().value);
|
|
448
|
+
this.startMaintenance();
|
|
221
449
|
if (input.appPackage) {
|
|
222
450
|
if (input.mode !== "control" || !phoneAllowsApp(device, input.appPackage)) throw new PhoneError("PHONE_APP_DENIED", "Launching requires control mode and an allowed application");
|
|
223
451
|
const epoch = session.report.controlEpoch;
|
|
@@ -226,7 +454,7 @@ var PhoneRuntime = class {
|
|
|
226
454
|
await this.dispatch(session, {
|
|
227
455
|
type: "launch",
|
|
228
456
|
package: input.appPackage
|
|
229
|
-
}, observation, context, signal, epoch);
|
|
457
|
+
}, observation, context, signal, epoch, false, input.settingsPage);
|
|
230
458
|
} finally {
|
|
231
459
|
observation.frame.fill(0);
|
|
232
460
|
}
|
|
@@ -234,19 +462,29 @@ var PhoneRuntime = class {
|
|
|
234
462
|
return this.publish(session);
|
|
235
463
|
} catch (error) {
|
|
236
464
|
this.repository.release(device.serial, lease);
|
|
237
|
-
this.sessions.delete(owner);
|
|
465
|
+
if (this.sessions.get(owner)?.device.id === deviceId) this.sessions.delete(owner);
|
|
238
466
|
throw error;
|
|
239
467
|
}
|
|
240
468
|
} finally {
|
|
241
469
|
this.openings.delete(owner);
|
|
470
|
+
if (requestedDevice) this.deviceOpenings.delete(requestedDevice);
|
|
242
471
|
}
|
|
243
472
|
}
|
|
244
473
|
const session = this.sessions.get(owner);
|
|
245
|
-
if (!session || terminal.has(session.report.status))
|
|
246
|
-
|
|
474
|
+
if (!session || terminal.has(session.report.status)) {
|
|
475
|
+
const deviceId = this.lastDevices.get(owner);
|
|
476
|
+
const occupying = deviceId && [...this.sessions.values()].find((value) => value.device.id === deviceId && !terminal.has(value.report.status));
|
|
477
|
+
if (occupying) throw this.busy(deviceId, occupying);
|
|
478
|
+
throw new PhoneError("PHONE_OPEN_REQUIRED", "Open a phone session first");
|
|
479
|
+
}
|
|
480
|
+
if (session.switching) throw new PhoneError("PHONE_SESSION_BUSY", "Phone execution mode is changing", 409);
|
|
481
|
+
if (this.deviceOpenings.has(session.device.id)) throw this.busy(session.device.id, session);
|
|
482
|
+
if (session.human) throw new PhoneError("PHONE_PAUSED", "The user controls this phone. Wait for explicit handback in the phone panel", 409);
|
|
247
483
|
if (session.active) throw new PhoneError("PHONE_SESSION_BUSY", "A phone operation is already running", 409);
|
|
248
484
|
this.guard(session, context);
|
|
249
485
|
if (input.op === "resume") {
|
|
486
|
+
if (session.modeHandbackRequired) throw new PhoneError("PHONE_PAUSED", "Inspect the phone and explicitly hand back in the phone panel after changing execution mode", 409);
|
|
487
|
+
if (session.report.steps.at(-1)?.dispatch === "unknown") throw new PhoneError("PHONE_DISPATCH_UNKNOWN", "Inspect the previous input before continuing; do not retry automatically", 409);
|
|
250
488
|
session.controller = new AbortController();
|
|
251
489
|
session.report.controlOwner = "agent";
|
|
252
490
|
session.report.controlEpoch++;
|
|
@@ -255,23 +493,276 @@ var PhoneRuntime = class {
|
|
|
255
493
|
session.report.message = void 0;
|
|
256
494
|
return this.publish(session);
|
|
257
495
|
}
|
|
258
|
-
if (
|
|
259
|
-
|
|
496
|
+
if ([
|
|
497
|
+
"paused",
|
|
498
|
+
"needs_user",
|
|
499
|
+
"failed",
|
|
500
|
+
"outcome_unknown"
|
|
501
|
+
].includes(session.report.status)) throw new PhoneError("PHONE_PAUSED", "Inspect the phone and explicitly hand back control before continuing", 409);
|
|
502
|
+
if (input.op === "run" || input.op === "step") {
|
|
503
|
+
const previous = session.report.task;
|
|
504
|
+
const continuing = Boolean(input.taskId && previous?.taskId === input.taskId);
|
|
505
|
+
const executionMode = input.executionMode ?? (continuing ? previous.executionMode : this.repository.executionMode(owner) ?? context.config.phone.executionMode);
|
|
506
|
+
if (continuing && executionMode !== previous.executionMode) throw new PhoneError("PHONE_MODE_SWITCH_REQUIRED", "Pause and explicitly switch the current task before changing execution mode", 409);
|
|
507
|
+
const constraints = [...new Set([...continuing ? previous.constraints : [], ...input.constraints ?? []])];
|
|
508
|
+
if (constraints.length > 12) throw new PhoneError("PHONE_CONSTRAINT_LIMIT", "A phone task supports at most 12 constraints; existing constraints cannot be removed");
|
|
509
|
+
if (!continuing) {
|
|
510
|
+
session.trajectory = [];
|
|
511
|
+
session.trajectorySummary = [];
|
|
512
|
+
session.taskActiveMs = 0;
|
|
513
|
+
session.taskStart = {
|
|
514
|
+
actions: session.report.actions - (session.report.humanActions ?? 0),
|
|
515
|
+
modelRequests: session.report.modelRequests
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
session.report.task = {
|
|
519
|
+
taskId: continuing ? previous.taskId : input.taskId ?? randomUUID(),
|
|
520
|
+
executionMode,
|
|
521
|
+
goal: input.goal,
|
|
522
|
+
constraints,
|
|
523
|
+
requestedOutputs: input.requestedOutputs ?? (continuing ? previous.requestedOutputs : []),
|
|
524
|
+
budget: {
|
|
525
|
+
maxActions: Math.min(input.budget?.maxActions ?? 80, continuing ? previous.budget?.maxActions ?? 80 : 80),
|
|
526
|
+
maxModelRequests: Math.min(input.budget?.maxModelRequests ?? 120, continuing ? previous.budget?.maxModelRequests ?? 120 : 120),
|
|
527
|
+
maxActiveDurationMs: Math.min(input.budget?.maxActiveDurationMs ?? 9e5, continuing ? previous.budget?.maxActiveDurationMs ?? 9e5 : 9e5)
|
|
528
|
+
},
|
|
529
|
+
completion: input.completion,
|
|
530
|
+
expectText: input.expectText
|
|
531
|
+
};
|
|
532
|
+
session.report.executionMode = executionMode;
|
|
533
|
+
session.segmentUsage = {
|
|
534
|
+
actions: session.report.actions,
|
|
535
|
+
modelRequests: session.report.modelRequests,
|
|
536
|
+
activeDurationMs: 0
|
|
537
|
+
};
|
|
538
|
+
session.report.feedback = {
|
|
539
|
+
taskId: session.report.task.taskId,
|
|
540
|
+
segmentId: randomUUID(),
|
|
541
|
+
executionMode,
|
|
542
|
+
outcome: "running",
|
|
543
|
+
verified: false,
|
|
544
|
+
verificationLevel: "none",
|
|
545
|
+
progress: {
|
|
546
|
+
completed: [],
|
|
547
|
+
remaining: ["Current goal has not been verified"],
|
|
548
|
+
source: "runtime"
|
|
549
|
+
},
|
|
550
|
+
outputs: session.report.task.requestedOutputs.map((output) => ({
|
|
551
|
+
key: output.key,
|
|
552
|
+
verification: "unavailable",
|
|
553
|
+
reason: "not_observed"
|
|
554
|
+
})),
|
|
555
|
+
evidence: [],
|
|
556
|
+
usage: {
|
|
557
|
+
actions: 0,
|
|
558
|
+
modelRequests: 0,
|
|
559
|
+
activeDurationMs: 0
|
|
560
|
+
},
|
|
561
|
+
nextAction: "wait"
|
|
562
|
+
};
|
|
563
|
+
session.taskPending = true;
|
|
564
|
+
session.report.goalPreview = input.goal.slice(0, 160);
|
|
565
|
+
}
|
|
566
|
+
if (session.report.controlOwner === "none") {
|
|
567
|
+
session.report.controlOwner = "agent";
|
|
568
|
+
session.report.controlEpoch++;
|
|
569
|
+
}
|
|
570
|
+
const duration = Math.min(context.config.phone.maxOperationDurationMs, context.config.phone.maxSessionDurationMs, session.report.task?.budget?.maxActiveDurationMs ?? 9e5);
|
|
571
|
+
session.budget = new PhoneOperationBudget(Math.max(1, duration - (session.taskActiveMs ?? 0)));
|
|
260
572
|
if (session.report.controlOwner === "agent") session.budget.resume();
|
|
261
573
|
const combined = AbortSignal.any([
|
|
262
574
|
signal,
|
|
263
575
|
session.controller.signal,
|
|
264
576
|
session.budget.controller.signal
|
|
265
577
|
]);
|
|
266
|
-
const operation =
|
|
578
|
+
const operation = (async () => {
|
|
579
|
+
await this.perform(session, input, context, combined);
|
|
580
|
+
if ((input.op === "run" || input.op === "step") && ["ready", "completed"].includes(session.report.status) && session.report.task?.requestedOutputs.length) {
|
|
581
|
+
const observation = await this.observe(session, combined);
|
|
582
|
+
try {
|
|
583
|
+
this.guard(session, context);
|
|
584
|
+
this.allowedScreen(session, observation);
|
|
585
|
+
this.recordObservation(session, observation);
|
|
586
|
+
const conditions = input.completion || input.expectText ? {
|
|
587
|
+
...input.completion,
|
|
588
|
+
requireChange: false,
|
|
589
|
+
textAll: [...input.completion?.textAll ?? [], ...input.expectText ? [input.expectText] : []]
|
|
590
|
+
} : void 0;
|
|
591
|
+
if (session.report.verified && conditions && !phoneCompletionSatisfied({
|
|
592
|
+
...conditions,
|
|
593
|
+
textAll: conditions.textAll.length ? conditions.textAll : void 0
|
|
594
|
+
}, observation, true)) {
|
|
595
|
+
session.report.verified = false;
|
|
596
|
+
session.report.verificationLevel = "none";
|
|
597
|
+
session.report.status = "ready";
|
|
598
|
+
session.report.stopReason = "completion_changed";
|
|
599
|
+
}
|
|
600
|
+
const epoch = session.report.controlEpoch;
|
|
601
|
+
for (const request of session.report.task.requestedOutputs) {
|
|
602
|
+
if (request.selector) continue;
|
|
603
|
+
await this.readScreen(session, observation, request.description, context, combined);
|
|
604
|
+
if (epoch !== session.report.controlEpoch || session.report.controlOwner !== "agent") break;
|
|
605
|
+
const reading = session.report.readings?.at(-1);
|
|
606
|
+
if (reading?.source === "screenshot") {
|
|
607
|
+
const output = session.report.feedback.outputs.find((output) => output.key === request.key);
|
|
608
|
+
Object.assign(output, {
|
|
609
|
+
value: reading.text.join("\n") || void 0,
|
|
610
|
+
source: reading.source,
|
|
611
|
+
verification: reading.verification,
|
|
612
|
+
frameId: reading.frameId,
|
|
613
|
+
capturedAt: reading.capturedAt,
|
|
614
|
+
reason: reading.reason
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
this.publish(session);
|
|
619
|
+
} finally {
|
|
620
|
+
observation.frame.fill(0);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
})();
|
|
267
624
|
session.active = operation;
|
|
268
625
|
try {
|
|
269
|
-
|
|
626
|
+
await operation;
|
|
627
|
+
} catch (error) {
|
|
628
|
+
if (combined.aborted && combined.reason instanceof PhoneError && combined.reason.code === "PHONE_OPERATION_TIMEOUT" && ![
|
|
629
|
+
"outcome_unknown",
|
|
630
|
+
"closed",
|
|
631
|
+
"cancelled"
|
|
632
|
+
].includes(session.report.status) && session.report.steps.at(-1)?.dispatch !== "unknown") {
|
|
633
|
+
session.report.status = "paused";
|
|
634
|
+
session.report.controlOwner = "none";
|
|
635
|
+
session.report.controlEpoch++;
|
|
636
|
+
session.report.stopReason = "operation_timeout";
|
|
637
|
+
session.report.errorCode = "PHONE_OPERATION_TIMEOUT";
|
|
638
|
+
}
|
|
639
|
+
if (["ready", "completed"].includes(session.report.status)) {
|
|
640
|
+
session.report.status = combined.aborted ? "cancelled" : "failed";
|
|
641
|
+
session.report.verified = false;
|
|
642
|
+
session.report.verificationLevel = "none";
|
|
643
|
+
session.report.errorCode = error instanceof PhoneError ? error.code : "PHONE_OPERATION_FAILED";
|
|
644
|
+
session.report.stopReason = "operation_failed";
|
|
645
|
+
}
|
|
646
|
+
if (error instanceof PhoneError && [
|
|
647
|
+
"PHONE_ACCESS_CHANGED",
|
|
648
|
+
"PHONE_APP_DENIED",
|
|
649
|
+
"PHONE_BINDING_CHANGED"
|
|
650
|
+
].includes(error.code)) {
|
|
651
|
+
session.report.facts = void 0;
|
|
652
|
+
session.report.readings = [];
|
|
653
|
+
if (session.report.feedback) session.report.feedback.outputs = session.report.feedback.outputs.map((output) => ({
|
|
654
|
+
key: output.key,
|
|
655
|
+
verification: "unavailable",
|
|
656
|
+
reason: error.code
|
|
657
|
+
}));
|
|
658
|
+
}
|
|
659
|
+
this.publish(session);
|
|
660
|
+
throw error;
|
|
270
661
|
} finally {
|
|
271
662
|
session.active = void 0;
|
|
663
|
+
const elapsed = session.budget?.elapsedMs ?? 0;
|
|
664
|
+
session.taskActiveMs = (session.taskActiveMs ?? 0) + elapsed;
|
|
665
|
+
if (session.segmentUsage) session.segmentUsage.activeDurationMs += elapsed;
|
|
272
666
|
session.budget?.dispose();
|
|
273
667
|
session.budget = void 0;
|
|
668
|
+
if (session.report.status === "cancelled" && !session.controller.signal.aborted) {
|
|
669
|
+
session.report.status = "ready";
|
|
670
|
+
session.taskPending = false;
|
|
671
|
+
}
|
|
672
|
+
if (session.report.status === "completed") session.taskPending = false;
|
|
673
|
+
if (!terminal.has(session.report.status) && !session.human && !["paused", "needs_user"].includes(session.report.status)) {
|
|
674
|
+
session.report.controlOwner = "none";
|
|
675
|
+
session.report.controlEpoch++;
|
|
676
|
+
this.publish(session);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
return structuredClone(session.report);
|
|
680
|
+
}
|
|
681
|
+
async setExecutionMode(owner, executionMode, context, applyCurrent = false, expectedEpoch) {
|
|
682
|
+
const session = this.sessions.get(owner);
|
|
683
|
+
if (session && expectedEpoch !== void 0 && session.report.controlEpoch !== expectedEpoch) throw new PhoneError("PHONE_CONTROL_STALE", "Phone control changed; refresh before switching", 409);
|
|
684
|
+
if (applyCurrent && session?.report.task) {
|
|
685
|
+
this.guard(session, context);
|
|
686
|
+
if (session.switching) throw new PhoneError("PHONE_SESSION_BUSY", "Phone execution mode is changing", 409);
|
|
687
|
+
if (session.human || session.report.handoff !== "idle" || session.report.status === "needs_user") throw new PhoneError("PHONE_PAUSED", "Wait for explicit user handback before switching the current task", 409);
|
|
688
|
+
if (session.report.steps.at(-1)?.dispatch === "unknown" || session.report.status === "outcome_unknown") throw new PhoneError("PHONE_DISPATCH_UNKNOWN", "Inspect the previous input before switching", 409);
|
|
689
|
+
session.switching = true;
|
|
690
|
+
try {
|
|
691
|
+
await this.stop(owner, "pause");
|
|
692
|
+
if (session.report.steps.at(-1)?.dispatch === "unknown") throw new PhoneError("PHONE_DISPATCH_UNKNOWN", "Inspect the previous input before switching", 409);
|
|
693
|
+
const observation = await this.observe(session, AbortSignal.timeout(1e4));
|
|
694
|
+
try {
|
|
695
|
+
this.guard(session, context);
|
|
696
|
+
this.allowedScreen(session, observation);
|
|
697
|
+
this.recordObservation(session, observation);
|
|
698
|
+
} finally {
|
|
699
|
+
observation.frame.fill(0);
|
|
700
|
+
}
|
|
701
|
+
session.trajectory = [];
|
|
702
|
+
session.trajectorySummary = [];
|
|
703
|
+
session.frames.clear();
|
|
704
|
+
session.report.task = {
|
|
705
|
+
...session.report.task,
|
|
706
|
+
executionMode
|
|
707
|
+
};
|
|
708
|
+
session.report.executionMode = executionMode;
|
|
709
|
+
if (session.report.feedback) session.report.feedback = {
|
|
710
|
+
...session.report.feedback,
|
|
711
|
+
executionMode,
|
|
712
|
+
segmentId: randomUUID()
|
|
713
|
+
};
|
|
714
|
+
session.modeHandbackRequired = true;
|
|
715
|
+
session.report.stopReason = "mode_changed";
|
|
716
|
+
session.report.message = "Execution mode changed. Inspect and hand back control, then continue the remaining goal with the same taskId.";
|
|
717
|
+
} finally {
|
|
718
|
+
session.switching = false;
|
|
719
|
+
}
|
|
274
720
|
}
|
|
721
|
+
this.repository.setExecutionMode(owner, executionMode);
|
|
722
|
+
return session ? this.publish(session) : void 0;
|
|
723
|
+
}
|
|
724
|
+
busy(deviceId, session) {
|
|
725
|
+
const kind = session?.human ? "human" : session && [
|
|
726
|
+
"paused",
|
|
727
|
+
"needs_user",
|
|
728
|
+
"failed",
|
|
729
|
+
"outcome_unknown"
|
|
730
|
+
].includes(session.report.status) ? "inspection" : session ? "agent" : "opening";
|
|
731
|
+
return new PhoneError("PHONE_DEVICE_BUSY", kind === "human" ? "Phone is under manual control. This task did not start. Hand back control before starting another task." : kind === "inspection" ? "Phone requires inspection in the current conversation. This task did not start." : "Phone is occupied by another task or is connecting. This task did not start. View the phone or wait; do not retry automatically.", 409, {
|
|
732
|
+
executionStarted: false,
|
|
733
|
+
deviceId,
|
|
734
|
+
occupancy: {
|
|
735
|
+
kind,
|
|
736
|
+
conversationId: session?.report.owner ?? [...this.openings].find(([, controller]) => controller === this.deviceOpenings.get(deviceId))?.[0],
|
|
737
|
+
sessionId: session?.report.sessionId
|
|
738
|
+
},
|
|
739
|
+
retryPolicy: "user_initiated"
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
async finishTask(owner) {
|
|
743
|
+
const session = this.sessions.get(owner);
|
|
744
|
+
if (!session || terminal.has(session.report.status)) return this.status(owner) ?? { status: "closed" };
|
|
745
|
+
if (this.deviceOpenings.has(session.device.id)) throw this.busy(session.device.id, session);
|
|
746
|
+
if (session.human || session.report.status === "needs_user" || session.report.steps.at(-1)?.dispatch === "unknown") throw this.busy(session.device.id, session);
|
|
747
|
+
if (session.active) await this.stop(owner, "pause");
|
|
748
|
+
session.controller = new AbortController();
|
|
749
|
+
session.report.controlOwner = "none";
|
|
750
|
+
session.report.controlEpoch++;
|
|
751
|
+
if (session.report.status !== "completed") session.report.status = "ready";
|
|
752
|
+
session.report.stopReason = "task_finished";
|
|
753
|
+
session.taskPending = false;
|
|
754
|
+
session.report.goalPreview = void 0;
|
|
755
|
+
session.report.facts = void 0;
|
|
756
|
+
session.report.readings = void 0;
|
|
757
|
+
session.report.task = void 0;
|
|
758
|
+
session.report.feedback = void 0;
|
|
759
|
+
session.segmentUsage = void 0;
|
|
760
|
+
session.taskActiveMs = 0;
|
|
761
|
+
session.taskStart = void 0;
|
|
762
|
+
session.modeHandbackRequired = false;
|
|
763
|
+
session.frames.clear();
|
|
764
|
+
await session.stream?.revoke();
|
|
765
|
+
return this.publish(session);
|
|
275
766
|
}
|
|
276
767
|
async perform(session, input, context, signal) {
|
|
277
768
|
let observation;
|
|
@@ -282,6 +773,8 @@ var PhoneRuntime = class {
|
|
|
282
773
|
session.report.verificationLevel = "none";
|
|
283
774
|
session.report.stopReason = void 0;
|
|
284
775
|
session.report.message = void 0;
|
|
776
|
+
session.report.facts = void 0;
|
|
777
|
+
session.report.readings = void 0;
|
|
285
778
|
try {
|
|
286
779
|
await this.waitForAgent(session, signal);
|
|
287
780
|
session.report.status = "running";
|
|
@@ -298,7 +791,8 @@ var PhoneRuntime = class {
|
|
|
298
791
|
this.allowedScreen(session, observation);
|
|
299
792
|
if (input.op === "observe") {
|
|
300
793
|
this.recordObservation(session, observation);
|
|
301
|
-
session.report.
|
|
794
|
+
if (!session.report.facts?.length || input.goal) await this.readScreen(session, observation, input.goal ?? "Read the visible page text and values", context, signal);
|
|
795
|
+
if (session.report.controlOwner === "agent" && !signal.aborted) session.report.status = "ready";
|
|
302
796
|
return this.publish(session);
|
|
303
797
|
}
|
|
304
798
|
if (input.op !== "run" && input.op !== "step") throw new PhoneError("PHONE_INVALID_OPERATION", "Unsupported operation");
|
|
@@ -315,7 +809,29 @@ var PhoneRuntime = class {
|
|
|
315
809
|
let repairs = 0;
|
|
316
810
|
let completionCorrections = 0;
|
|
317
811
|
let recoveryHint;
|
|
812
|
+
const enhancements = {
|
|
813
|
+
semanticControls: context.config.phone.semanticControls,
|
|
814
|
+
hierarchicalPlanning: context.config.phone.hierarchicalPlanning
|
|
815
|
+
};
|
|
816
|
+
const derivedPlan = enhancements.hierarchicalPlanning ? buildPhonePlan(input.goal, completion) : void 0;
|
|
817
|
+
let planning = derivedPlan ? createPhonePlanState(derivedPlan) : void 0;
|
|
818
|
+
if (enhancements.hierarchicalPlanning) {
|
|
819
|
+
session.report.diagnostics.plannedSubgoals = planning?.steps.length ?? 0;
|
|
820
|
+
session.report.diagnostics.completedSubgoals = 0;
|
|
821
|
+
}
|
|
318
822
|
let changed = false;
|
|
823
|
+
const entryObservation = {
|
|
824
|
+
...observation,
|
|
825
|
+
frame: Buffer.alloc(0),
|
|
826
|
+
elements: structuredClone(observation.elements)
|
|
827
|
+
};
|
|
828
|
+
const trajectoryStart = session.trajectoryCount;
|
|
829
|
+
let pendingFocus;
|
|
830
|
+
let numericIntent;
|
|
831
|
+
let numericPending;
|
|
832
|
+
const focusedIntents = /* @__PURE__ */ new Set();
|
|
833
|
+
let backReplans = 0;
|
|
834
|
+
let focusReplans = 0;
|
|
319
835
|
let previousSignature = observationSignature(observation);
|
|
320
836
|
let controlEpoch = session.report.controlEpoch;
|
|
321
837
|
const attempts = /* @__PURE__ */ new Map();
|
|
@@ -331,12 +847,51 @@ var PhoneRuntime = class {
|
|
|
331
847
|
if (controlEpoch !== epoch) {
|
|
332
848
|
attempts.clear();
|
|
333
849
|
recoveryHint = "The user handed back control. Re-evaluate the fresh screen before continuing.";
|
|
850
|
+
pendingFocus = void 0;
|
|
851
|
+
numericIntent = void 0;
|
|
852
|
+
numericPending = void 0;
|
|
334
853
|
controlEpoch = epoch;
|
|
335
854
|
}
|
|
336
855
|
const signature = observationSignature(observation);
|
|
337
856
|
if (signature !== previousSignature) changed = true;
|
|
338
857
|
previousSignature = signature;
|
|
339
858
|
this.recordObservation(session, observation);
|
|
859
|
+
if (planning) {
|
|
860
|
+
planning = advancePhonePlan(planning, observation);
|
|
861
|
+
session.report.diagnostics.completedSubgoals = planning.verifiedSteps;
|
|
862
|
+
}
|
|
863
|
+
let numericStep;
|
|
864
|
+
if (enhancements.hierarchicalPlanning) {
|
|
865
|
+
numericIntent ??= createPhoneNumericEntry(input.goal, completion, observation);
|
|
866
|
+
if (numericIntent) {
|
|
867
|
+
let next = nextPhoneNumericEntry(numericIntent, observation, numericPending);
|
|
868
|
+
for (let poll = 0; numericPending && next.kind === "blocked" && poll < 2; poll++) {
|
|
869
|
+
await setTimeout(150, void 0, { signal });
|
|
870
|
+
observation.frame.fill(0);
|
|
871
|
+
observation = await this.observe(session, signal);
|
|
872
|
+
this.guard(session, context);
|
|
873
|
+
this.allowedScreen(session, observation);
|
|
874
|
+
if (epoch !== session.report.controlEpoch || session.report.controlOwner !== "agent") break;
|
|
875
|
+
next = nextPhoneNumericEntry(numericIntent, observation, numericPending);
|
|
876
|
+
}
|
|
877
|
+
if (epoch !== session.report.controlEpoch || session.report.controlOwner !== "agent") continue;
|
|
878
|
+
this.recordObservation(session, observation);
|
|
879
|
+
if (next.kind === "blocked") {
|
|
880
|
+
session.report.diagnostics.numericMismatches = (session.report.diagnostics.numericMismatches ?? 0) + 1;
|
|
881
|
+
session.report.status = "paused";
|
|
882
|
+
session.report.controlOwner = "none";
|
|
883
|
+
session.report.controlEpoch++;
|
|
884
|
+
session.report.stopReason = "numeric_state_mismatch";
|
|
885
|
+
session.report.message = "Numeric input was not confirmed. Inspect the displayed value before continuing; no key was retried.";
|
|
886
|
+
session.budget?.pause();
|
|
887
|
+
await session.stream?.revoke();
|
|
888
|
+
return this.publish(session);
|
|
889
|
+
}
|
|
890
|
+
if (numericPending) session.report.diagnostics.numericConfirmedSteps = (session.report.diagnostics.numericConfirmedSteps ?? 0) + 1;
|
|
891
|
+
numericPending = void 0;
|
|
892
|
+
if (next.kind === "action") numericStep = next.step;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
340
895
|
if (session.report.mock ? isAboutScreen(observation) : Boolean(completion && phoneCompletionSatisfied(completion, observation, changed))) {
|
|
341
896
|
const confirmation = await this.observe(session, signal);
|
|
342
897
|
try {
|
|
@@ -350,6 +905,10 @@ var PhoneRuntime = class {
|
|
|
350
905
|
continue;
|
|
351
906
|
}
|
|
352
907
|
this.recordObservation(session, confirmation);
|
|
908
|
+
if (planning) {
|
|
909
|
+
planning = advancePhonePlan(planning, confirmation);
|
|
910
|
+
session.report.diagnostics.completedSubgoals = planning.verifiedSteps;
|
|
911
|
+
}
|
|
353
912
|
session.report.verified = true;
|
|
354
913
|
session.report.verificationLevel = "ui";
|
|
355
914
|
session.report.status = "completed";
|
|
@@ -359,57 +918,83 @@ var PhoneRuntime = class {
|
|
|
359
918
|
if (observation !== confirmation) confirmation.frame.fill(0);
|
|
360
919
|
}
|
|
361
920
|
}
|
|
921
|
+
if (session.report.actions - (session.report.humanActions ?? 0) - (session.taskStart?.actions ?? 0) >= (session.report.task?.budget?.maxActions ?? 80)) {
|
|
922
|
+
session.report.status = "ready";
|
|
923
|
+
session.report.stopReason = "task_action_limit";
|
|
924
|
+
return this.publish(session);
|
|
925
|
+
}
|
|
362
926
|
if (actions >= maxActions) {
|
|
363
927
|
session.report.status = "ready";
|
|
364
928
|
session.report.stopReason = "action_limit";
|
|
365
929
|
return this.publish(session);
|
|
366
930
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
931
|
+
let decision = numericStep ? {
|
|
932
|
+
kind: "action",
|
|
933
|
+
action: numericStep.action
|
|
934
|
+
} : void 0;
|
|
935
|
+
let resumedText = false;
|
|
936
|
+
if (!decision && pendingFocus) {
|
|
937
|
+
const pending = pendingFocus;
|
|
938
|
+
pendingFocus = void 0;
|
|
939
|
+
const intended = confirmPhoneFocusRecovery(pending, observation);
|
|
940
|
+
if (intended) {
|
|
941
|
+
decision = {
|
|
942
|
+
kind: "action",
|
|
943
|
+
action: intended
|
|
944
|
+
};
|
|
945
|
+
resumedText = true;
|
|
946
|
+
} else recoveryHint = "The focus transition was not confirmed. No text was sent. Reinspect the intended editable field before another action.";
|
|
947
|
+
}
|
|
948
|
+
if (!decision) {
|
|
949
|
+
if (session.report.modelRequests >= this.modelRequestLimit(session, context)) throw new PhoneError("PHONE_MODEL_LIMIT", "Phone model request limit reached");
|
|
950
|
+
session.report.modelRequests++;
|
|
951
|
+
session.report.currentAction = void 0;
|
|
952
|
+
this.publish(session);
|
|
953
|
+
session.prediction = new AbortController();
|
|
954
|
+
try {
|
|
955
|
+
decision = await session.adapter.predict({
|
|
956
|
+
goal: input.goal,
|
|
957
|
+
task: session.report.task,
|
|
958
|
+
observation,
|
|
959
|
+
completion,
|
|
960
|
+
allowedApps: session.device.allowedApps,
|
|
961
|
+
appAccess: phoneAppAccess(session.device),
|
|
962
|
+
applications: session.applications.filter((app) => phoneAllowsApp(session.device, app.packageName)),
|
|
963
|
+
history: session.report.steps.map((step) => step.action),
|
|
964
|
+
trajectory: session.trajectory,
|
|
965
|
+
progressSummary: JSON.stringify({
|
|
966
|
+
dispatched: session.trajectoryCount,
|
|
967
|
+
earlier: [...session.trajectorySummary, ...session.trajectory.slice(0, -8).map((entry) => JSON.stringify({
|
|
968
|
+
action: entry.action,
|
|
969
|
+
effect: entry.effect,
|
|
970
|
+
afterApp: entry.afterApp
|
|
971
|
+
}).slice(0, 250))].slice(-12)
|
|
972
|
+
}).slice(-1500),
|
|
973
|
+
recoveryHint,
|
|
974
|
+
protocolFeedback,
|
|
975
|
+
scenario: input.scenario,
|
|
976
|
+
enhancements,
|
|
977
|
+
planning
|
|
978
|
+
}, AbortSignal.any([signal, session.prediction.signal]));
|
|
979
|
+
} catch (error) {
|
|
980
|
+
if (!signal.aborted && epoch !== session.report.controlEpoch) {
|
|
981
|
+
await this.waitForAgent(session, signal);
|
|
982
|
+
observation.frame.fill(0);
|
|
983
|
+
observation = await this.observe(session, signal);
|
|
984
|
+
continue;
|
|
985
|
+
}
|
|
986
|
+
if (!signal.aborted && error instanceof PhoneError && ["PHONE_MODEL_PROTOCOL", "PHONE_MODEL_TRUNCATED"].includes(error.code) && repairs < 1 && session.report.modelRequests < this.modelRequestLimit(session, context)) {
|
|
987
|
+
repairs++;
|
|
988
|
+
session.report.diagnostics.protocolRepairs++;
|
|
989
|
+
protocolFeedback = "Your previous output was invalid or truncated. Return exactly one complete action in the specified format with no extra prose.";
|
|
990
|
+
observation.frame.fill(0);
|
|
991
|
+
observation = await this.observe(session, signal);
|
|
992
|
+
continue;
|
|
993
|
+
}
|
|
994
|
+
throw error;
|
|
995
|
+
} finally {
|
|
996
|
+
session.prediction = void 0;
|
|
409
997
|
}
|
|
410
|
-
throw error;
|
|
411
|
-
} finally {
|
|
412
|
-
session.prediction = void 0;
|
|
413
998
|
}
|
|
414
999
|
signal.throwIfAborted();
|
|
415
1000
|
this.guard(session, context);
|
|
@@ -420,8 +1005,13 @@ var PhoneRuntime = class {
|
|
|
420
1005
|
continue;
|
|
421
1006
|
}
|
|
422
1007
|
protocolFeedback = void 0;
|
|
1008
|
+
if (enhancements.hierarchicalPlanning && !planning && decision.plan) {
|
|
1009
|
+
planning = advancePhonePlan(createPhonePlanState(decision.plan), observation);
|
|
1010
|
+
session.report.diagnostics.plannedSubgoals = planning.steps.length;
|
|
1011
|
+
session.report.diagnostics.completedSubgoals = planning.verifiedSteps;
|
|
1012
|
+
}
|
|
423
1013
|
if (decision.kind !== "action") {
|
|
424
|
-
if (decision.kind === "complete" && !session.report.mock && (input.completion || input.expectText) && completionCorrections < 1 && session.report.modelRequests < context
|
|
1014
|
+
if (decision.kind === "complete" && !session.report.mock && (input.completion || input.expectText) && completionCorrections < 1 && session.report.modelRequests < this.modelRequestLimit(session, context)) {
|
|
425
1015
|
completionCorrections++;
|
|
426
1016
|
session.report.diagnostics.completionCorrections++;
|
|
427
1017
|
recoveryHint = `Your completion claim is not verified. These required native UI conditions are not all satisfied: ${JSON.stringify({
|
|
@@ -432,8 +1022,13 @@ var PhoneRuntime = class {
|
|
|
432
1022
|
observation = await this.observe(session, signal);
|
|
433
1023
|
continue;
|
|
434
1024
|
}
|
|
435
|
-
session.report.status = decision.kind === "needsUser" ? "needs_user" : "completed";
|
|
436
1025
|
session.report.message = decision.kind === "needsUser" ? decision.reason : decision.summary;
|
|
1026
|
+
if (decision.kind === "complete") {
|
|
1027
|
+
this.recordObservation(session, observation);
|
|
1028
|
+
await this.readScreen(session, observation, input.goal, context, signal);
|
|
1029
|
+
if (epoch !== session.report.controlEpoch || session.report.controlOwner !== "agent") return this.publish(session);
|
|
1030
|
+
}
|
|
1031
|
+
session.report.status = decision.kind === "needsUser" ? "needs_user" : "completed";
|
|
437
1032
|
session.report.stopReason = decision.kind === "needsUser" ? "user_takeover" : "model_finished_unverified";
|
|
438
1033
|
if (decision.kind === "needsUser" && !session.report.mock) {
|
|
439
1034
|
session.report.controlOwner = "none";
|
|
@@ -447,10 +1042,77 @@ var PhoneRuntime = class {
|
|
|
447
1042
|
}
|
|
448
1043
|
return this.publish(session);
|
|
449
1044
|
}
|
|
1045
|
+
let preparedFocus;
|
|
1046
|
+
if (enhancements.hierarchicalPlanning) {
|
|
1047
|
+
const operationActions = session.trajectoryCount - trajectoryStart;
|
|
1048
|
+
const back = phoneBackRecovery({
|
|
1049
|
+
action: decision.action,
|
|
1050
|
+
observation,
|
|
1051
|
+
entryObservation,
|
|
1052
|
+
completion,
|
|
1053
|
+
trajectory: operationActions ? session.trajectory.slice(-operationActions) : []
|
|
1054
|
+
});
|
|
1055
|
+
if (back) {
|
|
1056
|
+
session.report.diagnostics.backReplans = (session.report.diagnostics.backReplans ?? 0) + 1;
|
|
1057
|
+
if (backReplans++ >= 2) {
|
|
1058
|
+
session.report.status = "paused";
|
|
1059
|
+
session.report.controlOwner = "none";
|
|
1060
|
+
session.report.controlEpoch++;
|
|
1061
|
+
session.report.stopReason = "back_boundary";
|
|
1062
|
+
session.report.message = back.hint;
|
|
1063
|
+
session.budget?.pause();
|
|
1064
|
+
await session.stream?.revoke();
|
|
1065
|
+
return this.publish(session);
|
|
1066
|
+
}
|
|
1067
|
+
recoveryHint = back.hint;
|
|
1068
|
+
observation.frame.fill(0);
|
|
1069
|
+
observation = await this.observe(session, signal);
|
|
1070
|
+
continue;
|
|
1071
|
+
}
|
|
1072
|
+
const focusHint = phoneUnfocusedTypingHint(decision.action, observation, completion);
|
|
1073
|
+
if (focusHint) {
|
|
1074
|
+
const key = JSON.stringify(decision.action);
|
|
1075
|
+
preparedFocus = !focusedIntents.has(key) ? preparePhoneFocusRecovery(decision.action, observation, completion) : void 0;
|
|
1076
|
+
if (preparedFocus) decision = {
|
|
1077
|
+
kind: "action",
|
|
1078
|
+
action: preparedFocus.focusAction
|
|
1079
|
+
};
|
|
1080
|
+
else {
|
|
1081
|
+
session.report.diagnostics.focusReplans = (session.report.diagnostics.focusReplans ?? 0) + 1;
|
|
1082
|
+
if (focusReplans++ >= 2) throw new PhoneError("PHONE_INPUT_NOT_FOCUSED", "The requested editable field could not be focused; inspect before typing", 409);
|
|
1083
|
+
recoveryHint = focusHint;
|
|
1084
|
+
observation.frame.fill(0);
|
|
1085
|
+
observation = await this.observe(session, signal);
|
|
1086
|
+
continue;
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
450
1090
|
const fresh = await this.observe(session, signal);
|
|
451
1091
|
try {
|
|
452
1092
|
this.allowedScreen(session, fresh);
|
|
453
|
-
if (!canDispatchPhoneAction(decision.action, observation, fresh)) {
|
|
1093
|
+
if (decision.action.type !== "tapElement" && !canDispatchPhoneAction(decision.action, observation, fresh)) {
|
|
1094
|
+
session.report.diagnostics.stalePredictions++;
|
|
1095
|
+
recoveryHint = "The proposed action was not dispatched because its target changed. Locate it again on the fresh screen.";
|
|
1096
|
+
observation.frame.fill(0);
|
|
1097
|
+
observation = fresh;
|
|
1098
|
+
continue;
|
|
1099
|
+
}
|
|
1100
|
+
let action = enhancements.semanticControls ? groundPhoneCoordinateAction(decision.action, observation) : decision.action;
|
|
1101
|
+
const semanticAction = action.type === "tapElement";
|
|
1102
|
+
if (action.type === "tapElement") {
|
|
1103
|
+
if (!enhancements.semanticControls && !preparedFocus) throw new PhoneError("PHONE_SEMANTIC_DISABLED", "Semantic controls are disabled");
|
|
1104
|
+
try {
|
|
1105
|
+
action = resolvePhoneSemanticAction(action, observation, fresh);
|
|
1106
|
+
} catch (error) {
|
|
1107
|
+
if (!(error instanceof PhoneError) || !error.code.startsWith("PHONE_SEMANTIC_")) throw error;
|
|
1108
|
+
session.report.diagnostics.semanticRejections = (session.report.diagnostics.semanticRejections ?? 0) + 1;
|
|
1109
|
+
recoveryHint = "The semantic target was not dispatched: select one unique fully visible non-password control from the fresh native UI.";
|
|
1110
|
+
observation.frame.fill(0);
|
|
1111
|
+
observation = fresh;
|
|
1112
|
+
continue;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
if (!canDispatchPhoneAction(action, observation, fresh)) {
|
|
454
1116
|
session.report.diagnostics.stalePredictions++;
|
|
455
1117
|
recoveryHint = "The proposed action was not dispatched because its target changed. Locate it again on the fresh screen.";
|
|
456
1118
|
observation.frame.fill(0);
|
|
@@ -458,9 +1120,9 @@ var PhoneRuntime = class {
|
|
|
458
1120
|
continue;
|
|
459
1121
|
}
|
|
460
1122
|
if (epoch !== session.report.controlEpoch || session.report.controlOwner !== "agent") continue;
|
|
461
|
-
const attemptKey = `${observationSignature(fresh)}:${JSON.stringify(
|
|
1123
|
+
const attemptKey = `${observationSignature(fresh)}:${JSON.stringify(action)}`;
|
|
462
1124
|
const repetitions = attempts.get(attemptKey) ?? 0;
|
|
463
|
-
if (repetitions >= (
|
|
1125
|
+
if (repetitions >= (action.type === "wait" ? 3 : 2)) {
|
|
464
1126
|
session.report.status = "paused";
|
|
465
1127
|
session.report.controlOwner = "none";
|
|
466
1128
|
session.report.controlEpoch++;
|
|
@@ -471,7 +1133,20 @@ var PhoneRuntime = class {
|
|
|
471
1133
|
return this.publish(session);
|
|
472
1134
|
}
|
|
473
1135
|
attempts.set(attemptKey, repetitions + 1);
|
|
474
|
-
if (await this.dispatch(session,
|
|
1136
|
+
if (await this.dispatch(session, action, fresh, context, signal, epoch)) {
|
|
1137
|
+
actions++;
|
|
1138
|
+
if (semanticAction && enhancements.semanticControls) session.report.diagnostics.semanticActions = (session.report.diagnostics.semanticActions ?? 0) + 1;
|
|
1139
|
+
if (preparedFocus) {
|
|
1140
|
+
pendingFocus = preparedFocus;
|
|
1141
|
+
focusedIntents.add(JSON.stringify(preparedFocus.intendedAction));
|
|
1142
|
+
session.report.diagnostics.focusRecoveries = (session.report.diagnostics.focusRecoveries ?? 0) + 1;
|
|
1143
|
+
}
|
|
1144
|
+
if (resumedText) session.report.diagnostics.resumedTextInputs = (session.report.diagnostics.resumedTextInputs ?? 0) + 1;
|
|
1145
|
+
if (numericStep) {
|
|
1146
|
+
numericPending = numericStep;
|
|
1147
|
+
session.report.diagnostics.numericActions = (session.report.diagnostics.numericActions ?? 0) + 1;
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
475
1150
|
} finally {
|
|
476
1151
|
if (observation !== fresh) fresh.frame.fill(0);
|
|
477
1152
|
}
|
|
@@ -503,7 +1178,7 @@ var PhoneRuntime = class {
|
|
|
503
1178
|
await session.stream?.revoke();
|
|
504
1179
|
return this.publish(session);
|
|
505
1180
|
}
|
|
506
|
-
if (failure instanceof PhoneError && failure.code === "PHONE_OPERATION_TIMEOUT" && !terminal.has(session.report.status) && session.report.status !== "paused") {
|
|
1181
|
+
if (failure instanceof PhoneError && failure.code === "PHONE_OPERATION_TIMEOUT" && !terminal.has(session.report.status) && session.report.status !== "paused" && session.report.status !== "outcome_unknown") {
|
|
507
1182
|
session.report.status = "paused";
|
|
508
1183
|
session.report.controlOwner = "none";
|
|
509
1184
|
session.report.controlEpoch++;
|
|
@@ -562,10 +1237,67 @@ var PhoneRuntime = class {
|
|
|
562
1237
|
}
|
|
563
1238
|
}
|
|
564
1239
|
recordObservation(session, observation) {
|
|
1240
|
+
if (session.report.task && session.report.feedback) session.report.feedback.outputs = session.report.task.requestedOutputs.map((output) => nativePhoneOutput(output, observation));
|
|
565
1241
|
session.report.foregroundApp = observation.package;
|
|
566
1242
|
session.report.facts = [...new Set(observation.elements.flatMap((node) => node.password ? [] : [node.text, node.description]).filter(Boolean))].slice(0, 60);
|
|
1243
|
+
session.report.readings = [{
|
|
1244
|
+
source: "native_ui",
|
|
1245
|
+
verification: "observed",
|
|
1246
|
+
text: session.report.facts,
|
|
1247
|
+
frameId: observation.frameId,
|
|
1248
|
+
capturedAt: observation.capturedAt
|
|
1249
|
+
}];
|
|
1250
|
+
}
|
|
1251
|
+
modelRequestLimit(session, context) {
|
|
1252
|
+
return Math.min(context.config.phone.maxModelRequests, (session.taskStart?.modelRequests ?? 0) + (session.report.task?.budget?.maxModelRequests ?? 120));
|
|
1253
|
+
}
|
|
1254
|
+
async readScreen(session, observation, goal, context, signal) {
|
|
1255
|
+
if (session.report.mock) return;
|
|
1256
|
+
const reading = {
|
|
1257
|
+
source: "screenshot",
|
|
1258
|
+
verification: "unavailable",
|
|
1259
|
+
text: [],
|
|
1260
|
+
frameId: observation.frameId,
|
|
1261
|
+
capturedAt: observation.capturedAt
|
|
1262
|
+
};
|
|
1263
|
+
const epoch = session.report.controlEpoch;
|
|
1264
|
+
this.guard(session, context);
|
|
1265
|
+
this.allowedScreen(session, observation);
|
|
1266
|
+
signal.throwIfAborted();
|
|
1267
|
+
if (observation.elements.some((node) => node.password)) reading.reason = "password_field_visible";
|
|
1268
|
+
else if (!session.adapter.readScreen) reading.reason = "model_reading_unavailable";
|
|
1269
|
+
else if (session.report.modelRequests >= this.modelRequestLimit(session, context)) reading.reason = "model_request_limit";
|
|
1270
|
+
else {
|
|
1271
|
+
session.report.modelRequests++;
|
|
1272
|
+
session.prediction = new AbortController();
|
|
1273
|
+
try {
|
|
1274
|
+
const text = await session.adapter.readScreen({
|
|
1275
|
+
goal,
|
|
1276
|
+
observation,
|
|
1277
|
+
allowedApps: session.device.allowedApps,
|
|
1278
|
+
appAccess: phoneAppAccess(session.device),
|
|
1279
|
+
history: []
|
|
1280
|
+
}, AbortSignal.any([signal, session.prediction.signal]));
|
|
1281
|
+
signal.throwIfAborted();
|
|
1282
|
+
this.guard(session, context);
|
|
1283
|
+
this.allowedScreen(session, observation);
|
|
1284
|
+
if (epoch !== session.report.controlEpoch || session.report.controlOwner !== "agent") return;
|
|
1285
|
+
if (text.trim()) {
|
|
1286
|
+
reading.text = [text.slice(0, 1e3)];
|
|
1287
|
+
reading.verification = "unverified";
|
|
1288
|
+
} else reading.reason = "screen_unreadable";
|
|
1289
|
+
} catch (error) {
|
|
1290
|
+
signal.throwIfAborted();
|
|
1291
|
+
this.guard(session, context);
|
|
1292
|
+
if (epoch !== session.report.controlEpoch || session.report.controlOwner !== "agent") return;
|
|
1293
|
+
reading.reason = error instanceof PhoneError ? error.code : "screen_reading_failed";
|
|
1294
|
+
} finally {
|
|
1295
|
+
session.prediction = void 0;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
session.report.readings = [...session.report.readings ?? [], reading];
|
|
567
1299
|
}
|
|
568
|
-
async dispatch(session, action, observation, context, signal, epoch = session.report.controlEpoch, resetTask = false) {
|
|
1300
|
+
async dispatch(session, action, observation, context, signal, epoch = session.report.controlEpoch, resetTask = false, settingsPage) {
|
|
569
1301
|
return this.io(session, async () => {
|
|
570
1302
|
signal.throwIfAborted();
|
|
571
1303
|
this.guard(session, context);
|
|
@@ -610,7 +1342,10 @@ var PhoneRuntime = class {
|
|
|
610
1342
|
session.trajectorySummary = session.trajectorySummary.slice(-12);
|
|
611
1343
|
}
|
|
612
1344
|
try {
|
|
613
|
-
await session.driver.execute(session.device.serial, action, observation, signal,
|
|
1345
|
+
await session.driver.execute(session.device.serial, action, observation, signal, settingsPage ? {
|
|
1346
|
+
settleMs: session.human ? 0 : 350,
|
|
1347
|
+
settingsPage
|
|
1348
|
+
} : session.human ? {
|
|
614
1349
|
settleMs: 0,
|
|
615
1350
|
...resetTask ? { resetTask: true } : {}
|
|
616
1351
|
} : void 0);
|
|
@@ -652,6 +1387,7 @@ var PhoneRuntime = class {
|
|
|
652
1387
|
session.report.controlEpoch++;
|
|
653
1388
|
if (op === "pause") await session.stream?.revoke();
|
|
654
1389
|
else {
|
|
1390
|
+
session.videoGeneration = void 0;
|
|
655
1391
|
await session.stream?.close();
|
|
656
1392
|
session.stream = void 0;
|
|
657
1393
|
}
|
|
@@ -662,17 +1398,28 @@ var PhoneRuntime = class {
|
|
|
662
1398
|
if (op !== "pause") {
|
|
663
1399
|
session.report.facts = void 0;
|
|
664
1400
|
session.report.message = void 0;
|
|
1401
|
+
session.report.readings = void 0;
|
|
665
1402
|
session.trajectory = [];
|
|
666
1403
|
session.trajectorySummary = [];
|
|
667
1404
|
session.frames.clear();
|
|
668
|
-
session.adapter = { predict: async () => {
|
|
1405
|
+
if (op === "close") session.adapter = { predict: async () => {
|
|
669
1406
|
throw new PhoneError("PHONE_OPEN_REQUIRED", "Reopen the phone session");
|
|
670
1407
|
} };
|
|
671
1408
|
}
|
|
672
1409
|
this.publish(session);
|
|
673
1410
|
await session.active?.catch(() => {});
|
|
674
1411
|
await session.io.catch(() => {});
|
|
675
|
-
if (op
|
|
1412
|
+
if (op === "close") this.repository.release(session.device.serial, session.lease);
|
|
1413
|
+
if (op === "cancel") {
|
|
1414
|
+
session.controller = new AbortController();
|
|
1415
|
+
session.report.status = "ready";
|
|
1416
|
+
session.report.controlOwner = "none";
|
|
1417
|
+
session.taskPending = false;
|
|
1418
|
+
if (session.report.steps.at(-1)?.dispatch === "unknown") {
|
|
1419
|
+
session.report.status = "outcome_unknown";
|
|
1420
|
+
session.report.stopReason = "inspect_before_retry";
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
676
1423
|
return this.publish(session);
|
|
677
1424
|
}
|
|
678
1425
|
async io(session, work) {
|
|
@@ -753,6 +1500,11 @@ var PhoneRuntime = class {
|
|
|
753
1500
|
}
|
|
754
1501
|
try {
|
|
755
1502
|
this.guard(session, session.context);
|
|
1503
|
+
const idleLimit = session.context.config.phone.idleDisconnectMs;
|
|
1504
|
+
if (idleLimit && !session.active && !session.human && session.report.controlOwner === "none" && Date.now() - Math.max(session.viewedAt, session.report.updatedAt) >= idleLimit) {
|
|
1505
|
+
this.stopDevice(session.device.id);
|
|
1506
|
+
continue;
|
|
1507
|
+
}
|
|
756
1508
|
if (session.human && Date.now() > (session.humanExpiresAt ?? 0)) {
|
|
757
1509
|
session.human = void 0;
|
|
758
1510
|
session.report.controlOwner = "none";
|
|
@@ -765,7 +1517,7 @@ var PhoneRuntime = class {
|
|
|
765
1517
|
if (Date.now() - session.viewedAt > 3e4) session.frames.clear();
|
|
766
1518
|
} catch {
|
|
767
1519
|
session.frames.clear();
|
|
768
|
-
this.
|
|
1520
|
+
this.stopDevice(session.device.id);
|
|
769
1521
|
}
|
|
770
1522
|
}
|
|
771
1523
|
}, 3e3);
|
|
@@ -788,7 +1540,10 @@ var PhoneRuntime = class {
|
|
|
788
1540
|
liveStatus(owner, id, context, client) {
|
|
789
1541
|
const session = this.liveSession(owner, id, context);
|
|
790
1542
|
return {
|
|
791
|
-
report:
|
|
1543
|
+
report: {
|
|
1544
|
+
...structuredClone(session.report),
|
|
1545
|
+
nextExecutionMode: this.repository.executionMode(owner) ?? context.config.phone.executionMode
|
|
1546
|
+
},
|
|
792
1547
|
ownControl: Boolean(session.human === client),
|
|
793
1548
|
allowedApps: [...session.device.allowedApps],
|
|
794
1549
|
appAccess: phoneAppAccess(session.device),
|
|
@@ -803,7 +1558,7 @@ var PhoneRuntime = class {
|
|
|
803
1558
|
const session = this.liveSession(owner, id, context);
|
|
804
1559
|
if (terminal.has(session.report.status)) throw new PhoneError("PHONE_OPEN_REQUIRED", "Phone session ended", 409);
|
|
805
1560
|
if (session.streamOpening) return session.streamOpening;
|
|
806
|
-
const opening = this.openLiveVideo(
|
|
1561
|
+
const opening = this.openLiveVideo(session);
|
|
807
1562
|
session.streamOpening = opening;
|
|
808
1563
|
try {
|
|
809
1564
|
return await opening;
|
|
@@ -811,12 +1566,16 @@ var PhoneRuntime = class {
|
|
|
811
1566
|
if (session.streamOpening === opening) session.streamOpening = void 0;
|
|
812
1567
|
}
|
|
813
1568
|
}
|
|
814
|
-
async openLiveVideo(
|
|
1569
|
+
async openLiveVideo(session) {
|
|
815
1570
|
if (!session.stream) {
|
|
816
1571
|
await session.io;
|
|
817
1572
|
if (terminal.has(session.report.status)) throw new PhoneError("PHONE_VIDEO_ENDED", "Phone session ended", 409);
|
|
1573
|
+
const generation = Symbol();
|
|
1574
|
+
session.videoGeneration = generation;
|
|
818
1575
|
const failed = () => {
|
|
819
|
-
this.
|
|
1576
|
+
if (session.videoGeneration !== generation || ![...this.sessions.values()].includes(session)) return;
|
|
1577
|
+
session.videoGeneration = void 0;
|
|
1578
|
+
this.stop(session.report.owner, "pause");
|
|
820
1579
|
};
|
|
821
1580
|
const provider = session.device.connection ? await this.cloud.interactive(session.device, failed) : this.interactiveFactory(session.adbPath, session.device.serial, failed);
|
|
822
1581
|
if (terminal.has(session.report.status)) {
|
|
@@ -912,6 +1671,8 @@ var PhoneRuntime = class {
|
|
|
912
1671
|
}
|
|
913
1672
|
async liveControl(owner, id, context, client, input) {
|
|
914
1673
|
const session = this.liveSession(owner, id, context);
|
|
1674
|
+
if (session.switching) throw new PhoneError("PHONE_SESSION_BUSY", "Phone execution mode is changing", 409);
|
|
1675
|
+
if (this.deviceOpenings.has(session.device.id)) throw this.busy(session.device.id, session);
|
|
915
1676
|
if (input.op === "heartbeat") {
|
|
916
1677
|
if (terminal.has(session.report.status) || input.epoch !== session.report.controlEpoch || session.human !== client || Date.now() > (session.humanExpiresAt ?? 0)) throw new PhoneError("PHONE_CONTROL_REQUIRED", "Manual control is no longer available", 409);
|
|
917
1678
|
session.humanExpiresAt = Date.now() + 15e3;
|
|
@@ -932,6 +1693,7 @@ var PhoneRuntime = class {
|
|
|
932
1693
|
const result = session.commands.catch(() => {}).then(async () => {
|
|
933
1694
|
if (terminal.has(session.report.status)) throw new PhoneError("PHONE_OPEN_REQUIRED", "Phone session ended", 409);
|
|
934
1695
|
this.guard(session, context);
|
|
1696
|
+
if (session.switching) throw new PhoneError("PHONE_SESSION_BUSY", "Phone execution mode is changing", 409);
|
|
935
1697
|
if (input.epoch !== session.report.controlEpoch) throw new PhoneError("PHONE_CONTROL_CHANGED", "Control changed. Refresh before trying again.", 409);
|
|
936
1698
|
if (session.human && session.human !== client) throw new PhoneError("PHONE_CONTROL_BUSY", "Another browser window controls this phone", 409);
|
|
937
1699
|
if (input.op === "cancel") {
|
|
@@ -997,9 +1759,10 @@ var PhoneRuntime = class {
|
|
|
997
1759
|
} finally {
|
|
998
1760
|
observation?.frame.fill(0);
|
|
999
1761
|
}
|
|
1000
|
-
session.report.controlOwner = "agent";
|
|
1762
|
+
session.report.controlOwner = session.active || session.taskPending ? "agent" : "none";
|
|
1001
1763
|
session.report.status = session.active ? "running" : "ready";
|
|
1002
1764
|
session.report.handoff = "idle";
|
|
1765
|
+
session.modeHandbackRequired = false;
|
|
1003
1766
|
session.report.message = void 0;
|
|
1004
1767
|
session.report.stopReason = void 0;
|
|
1005
1768
|
session.budget?.resume();
|
|
@@ -1023,7 +1786,7 @@ var PhoneRuntime = class {
|
|
|
1023
1786
|
const video = input.geometry !== void 0 && session.stream?.verifyGeometry(input.geometry);
|
|
1024
1787
|
if (!video && (!frame || Date.now() - frame.capturedAt > 5e3)) throw new PhoneError("PHONE_FRAME_STALE", "Wait for a fresh phone image before interacting", 409);
|
|
1025
1788
|
if (video && input.action?.type !== "typeText" && input.action?.type !== "back") throw new PhoneError("PHONE_INVALID_INPUT", "Use the continuous input channel for video gestures", 409);
|
|
1026
|
-
if (!input.action || input.action.type === "launch" || input.action.type === "home" || input.action.type === "wait") throw new PhoneError("PHONE_INVALID_INPUT", "Unsupported manual input");
|
|
1789
|
+
if (!input.action || input.action.type === "launch" || input.action.type === "home" || input.action.type === "wait" || input.action.type === "tapElement") throw new PhoneError("PHONE_INVALID_INPUT", "Unsupported manual input");
|
|
1027
1790
|
const observation = input.action.type === "typeText" ? await this.observe(session, session.controller.signal, true) : await this.capture(session, session.controller.signal);
|
|
1028
1791
|
try {
|
|
1029
1792
|
if (input.epoch !== session.report.controlEpoch || session.human !== client || Date.now() > (session.humanExpiresAt ?? 0)) throw new PhoneError("PHONE_CONTROL_CHANGED", "Manual control expired while observing the phone", 409);
|
|
@@ -1039,7 +1802,7 @@ var PhoneRuntime = class {
|
|
|
1039
1802
|
}
|
|
1040
1803
|
return {
|
|
1041
1804
|
...this.liveStatus(owner, id, context, client),
|
|
1042
|
-
resumeTurnRequired: input.op === "handback" && !session.active
|
|
1805
|
+
resumeTurnRequired: input.op === "handback" && !session.active && Boolean(session.taskPending)
|
|
1043
1806
|
};
|
|
1044
1807
|
});
|
|
1045
1808
|
session.commands = result.catch(() => {
|
|
@@ -1058,14 +1821,19 @@ var PhoneRuntime = class {
|
|
|
1058
1821
|
return result;
|
|
1059
1822
|
}
|
|
1060
1823
|
async stopDevice(id) {
|
|
1061
|
-
|
|
1824
|
+
this.deviceOpenings.get(id)?.abort();
|
|
1825
|
+
await Promise.all(this.reports().filter((report) => report.deviceId === id).map((report) => this.stop(report.owner, "close")));
|
|
1062
1826
|
this.cloudPhones?.disconnect(id);
|
|
1063
1827
|
}
|
|
1064
1828
|
async shutdown() {
|
|
1829
|
+
this.wireless.close();
|
|
1830
|
+
this.reconnectAfter.clear();
|
|
1831
|
+
await Promise.allSettled(this.reconnecting.values());
|
|
1065
1832
|
for (const controller of this.openings.values()) controller.abort();
|
|
1066
1833
|
await Promise.all([...this.sessions.keys()].map((owner) => this.stop(owner, "close")));
|
|
1067
1834
|
this.cloudPhones?.close();
|
|
1068
1835
|
this.sessions.clear();
|
|
1836
|
+
this.lastDevices.clear();
|
|
1069
1837
|
if (this.maintenance) clearInterval(this.maintenance);
|
|
1070
1838
|
this.maintenance = void 0;
|
|
1071
1839
|
}
|