@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.
Files changed (892) hide show
  1. package/README.md +2 -2
  2. package/README.zh-CN.md +2 -2
  3. package/dist/browser-ext/_locales/en/messages.json +4 -1
  4. package/dist/browser-ext/_locales/zh_CN/messages.json +4 -1
  5. package/dist/browser-ext/dist/assets/{page-context-MuzjMBlJ.js → page-context-BKnEwsOO.js} +2914 -1381
  6. package/dist/browser-ext/dist/background.js +39 -10
  7. package/dist/browser-ext/dist/sidepanel.html +1 -1
  8. package/dist/browser-ext/dist/sidepanel.js +502 -348
  9. package/dist/browser-ext/manifest.json +1 -1
  10. package/dist/extensions/telegram/xopc.extension.json +1 -1
  11. package/dist/gateway/static/root/assets/activity-YogQEteU.js +1 -0
  12. package/dist/gateway/static/root/assets/activity-store-DnqOM8GN.js +1 -0
  13. package/dist/gateway/static/root/assets/agent-avatar-dicebear-1UABT2KS.js +1 -0
  14. package/dist/gateway/static/root/assets/agent-avatar-display-Cy50vjbq.js +2 -0
  15. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-V4NX_cWz.js +1 -0
  16. package/dist/gateway/static/root/assets/agent-display-names-Bje7vfSn.js +1 -0
  17. package/dist/gateway/static/root/assets/agent-plugin-dialog-CQ5LLDMO.js +1 -0
  18. package/dist/gateway/static/root/assets/agents-O7mago-m.js +77 -0
  19. package/dist/gateway/static/root/assets/{agents-admin-api-B1p-ghg9.js → agents-admin-api-CyjykMEh.js} +2 -2
  20. package/dist/gateway/static/root/assets/agents-app-path-ciChvpCS.js +1 -0
  21. package/dist/gateway/static/root/assets/api-C1dxxDZx.js +1 -0
  22. package/dist/gateway/static/root/assets/api-Ddrs70xV.js +1 -0
  23. package/dist/gateway/static/root/assets/app-chrome-BeB4KgOf.js +1 -0
  24. package/dist/gateway/static/root/assets/app-link-CytZ5zkp.js +1 -0
  25. package/dist/gateway/static/root/assets/app-management-settings-panel-C1Zs-eha.js +1 -0
  26. package/dist/gateway/static/root/assets/appearance-settings-lIfGokbz.js +1 -0
  27. package/dist/gateway/static/root/assets/apps-page-CUvtsRYD.js +1 -0
  28. package/dist/gateway/static/root/assets/archive-Dz0hferG.js +1 -0
  29. package/dist/gateway/static/root/assets/{archive-plugin-Ch7wolHE.js → archive-plugin-n5lPr79c.js} +1 -1
  30. package/dist/gateway/static/root/assets/arrow-left-D880xG-P.js +1 -0
  31. package/dist/gateway/static/root/assets/arrow-right-DSSvoX71.js +1 -0
  32. package/dist/gateway/static/root/assets/arrow-up-D5ZtR1QT.js +1 -0
  33. package/dist/gateway/static/root/assets/arrow-up-right-T72JbQ1Q.js +1 -0
  34. package/dist/gateway/static/root/assets/{attachment-preview-renderer-wzIchDSv.js → attachment-preview-renderer-DdOEgexg.js} +3 -3
  35. package/dist/gateway/static/root/assets/{attachment-process-heavy-Db4nTY5N.js → attachment-process-heavy-DGZZ-M85.js} +2 -2
  36. package/dist/gateway/static/root/assets/automation-api-Bld8blNl.js +1 -0
  37. package/dist/gateway/static/root/assets/automation-display-BcfZOQTC.js +2 -0
  38. package/dist/gateway/static/root/assets/{automations-page-DK7AU79v.js → automations-page-oLsNzu_6.js} +1 -1
  39. package/dist/gateway/static/root/assets/automations-workspace-BgtYY2Mm.js +8 -0
  40. package/dist/gateway/static/root/assets/beta-badge-BnzdzIEl.js +1 -0
  41. package/dist/gateway/static/root/assets/{binary-plugins-B4HcHYsC.js → binary-plugins-D9VW7dWP.js} +2 -2
  42. package/dist/gateway/static/root/assets/{block-editor-BQAWEZF-.js → block-editor-C477bTtO.js} +23 -23
  43. package/dist/gateway/static/root/assets/book-open-CCGtrT3R.js +1 -0
  44. package/dist/gateway/static/root/assets/bot-DjLkhyZL.js +1 -0
  45. package/dist/gateway/static/root/assets/box-DvYoGszj.js +1 -0
  46. package/dist/gateway/static/root/assets/braces-Cfmtagno.js +1 -0
  47. package/dist/gateway/static/root/assets/brand-logo-CgT9zQfr.js +1 -0
  48. package/dist/gateway/static/root/assets/briefcase-business-BsoCaI_t.js +1 -0
  49. package/dist/gateway/static/root/assets/browser-BLJWD7WI.js +8 -0
  50. package/dist/gateway/static/root/assets/{browser-automation-inputs-D6AccXaA.js → browser-automation-inputs-CCiYXxmh.js} +1 -1
  51. package/dist/gateway/static/root/assets/browser-automations-page-DIUNY94X.js +3 -0
  52. package/dist/gateway/static/root/assets/browser-control-api-Y3fvmeBk.js +6 -0
  53. package/dist/gateway/static/root/assets/browser-notification-delivery-DmE2FgGc.js +1 -0
  54. package/dist/gateway/static/root/assets/browser-settings-page-DjkGahlz.js +3 -0
  55. package/dist/gateway/static/root/assets/{button-aIC072nz.js → button-CnRSIP6m.js} +1 -1
  56. package/dist/gateway/static/root/assets/calendar-clock-D-quYVPe.js +1 -0
  57. package/dist/gateway/static/root/assets/calendar-days-hw_Y-g-s.js +1 -0
  58. package/dist/gateway/static/root/assets/capabilities-DAyA681v.js +1 -0
  59. package/dist/gateway/static/root/assets/capabilities-DRVXLssH.js +1 -0
  60. package/dist/gateway/static/root/assets/capabilities-page-DFW4Y0x8.js +2 -0
  61. package/dist/gateway/static/root/assets/capabilities-settings-panel-uOHSMQPZ.js +8 -0
  62. package/dist/gateway/static/root/assets/capability-header-actions-CTUCuBlW.js +1 -0
  63. package/dist/gateway/static/root/assets/capability-icon-DVoZxEgW.js +1 -0
  64. package/dist/gateway/static/root/assets/capability-links-DzQWK1Fh.js +1 -0
  65. package/dist/gateway/static/root/assets/channels-D2a69dSt.js +1 -0
  66. package/dist/gateway/static/root/assets/channels-routes-r2g-9DdC.js +1 -0
  67. package/dist/gateway/static/root/assets/chat-agents-api-D5nR_JVe.js +1 -0
  68. package/dist/gateway/static/root/assets/chat-chart-block-K2t333qv.js +2 -0
  69. package/dist/gateway/static/root/assets/chat-page-CG38tCHE.js +71 -0
  70. package/dist/gateway/static/root/assets/chat-page-zQeUaawJ.css +1 -0
  71. package/dist/gateway/static/root/assets/chat-terminal-dock-CkFG6mA3.js +35 -0
  72. package/dist/gateway/static/root/assets/chevron-left-DqFhpbvK.js +1 -0
  73. package/dist/gateway/static/root/assets/chevron-right-BweFrslA.js +1 -0
  74. package/dist/gateway/static/root/assets/chunk-D32TOXHM-DQIy-Baq.js +156 -0
  75. package/dist/gateway/static/root/assets/chunk-KS7C4IRE-CiwuuyV8.js +4 -0
  76. package/dist/gateway/static/root/assets/circle-BoO4YvTx.js +1 -0
  77. package/dist/gateway/static/root/assets/circle-alert-BEjgurr2.js +1 -0
  78. package/dist/gateway/static/root/assets/circle-pause-CN9jYH2s.js +1 -0
  79. package/dist/gateway/static/root/assets/circle-x-DFsCKeya.js +1 -0
  80. package/dist/gateway/static/root/assets/clock-3-DnrAnuyZ.js +1 -0
  81. package/dist/gateway/static/root/assets/cloud-C4-yfnnk.js +1 -0
  82. package/dist/gateway/static/root/assets/cloud-credits-B-nbtkqv.js +1 -0
  83. package/dist/gateway/static/root/assets/code-xml-DJtYhZUF.js +1 -0
  84. package/dist/gateway/static/root/assets/coins-DjP27vUx.js +1 -0
  85. package/dist/gateway/static/root/assets/command-palette-api-Do_66X1B.js +1 -0
  86. package/dist/gateway/static/root/assets/composer-payload-handoff-BU3B-C26.js +1 -0
  87. package/dist/gateway/static/root/assets/computer-settings-page-DBxOcMko.js +1 -0
  88. package/dist/gateway/static/root/assets/confirm-dialog-XGclfBqe.js +1 -0
  89. package/dist/gateway/static/root/assets/connected-providers-grid-Dmnu2zle.js +1 -0
  90. package/dist/gateway/static/root/assets/connector-filters-Cfcx9EA2.js +1 -0
  91. package/dist/gateway/static/root/assets/connector-service-page-rWpnchb3.js +1 -0
  92. package/dist/gateway/static/root/assets/connectors-api-DIBG72k4.js +1 -0
  93. package/dist/gateway/static/root/assets/connectors-page-DT_WrC1y.js +1 -0
  94. package/dist/gateway/static/root/assets/constants-DBtMsXdW.js +1 -0
  95. package/dist/gateway/static/root/assets/copy-text-row-CYIv7RfP.js +1 -0
  96. package/dist/gateway/static/root/assets/cpu-B247669f.js +1 -0
  97. package/dist/gateway/static/root/assets/database-CjjeZfRG.js +1 -0
  98. package/dist/gateway/static/root/assets/date-picker-CE-cZFCU.js +1 -0
  99. package/dist/gateway/static/root/assets/dependency-picker-7SpSfDSg.js +1 -0
  100. package/dist/gateway/static/root/assets/desktop-pet-lorocS9j.js +1 -0
  101. package/dist/gateway/static/root/assets/desktop-pet-narrative-CS8qJpNO.js +1 -0
  102. package/dist/gateway/static/root/assets/desktop-pet-settings-CEcohlZq.js +1 -0
  103. package/dist/gateway/static/root/assets/{desktop-pet-sprite-Bd-aOI7N.js → desktop-pet-sprite-D5YYq2zC.js} +1 -1
  104. package/dist/gateway/static/root/assets/dev-view-store-57HgVuZ6.js +1 -0
  105. package/dist/gateway/static/root/assets/device-pairing-wizard-CLCPuf4R.js +1 -0
  106. package/dist/gateway/static/root/assets/directory-picker-path-field-D4jMhpka.js +1 -0
  107. package/dist/gateway/static/root/assets/discussion-annotation-sync-BKjf9gWe.js +1 -0
  108. package/dist/gateway/static/root/assets/dist-CaUuvp8-.js +1 -0
  109. package/dist/gateway/static/root/assets/dist-DNCdG_qB.js +1 -0
  110. package/dist/gateway/static/root/assets/dist-DfWfZ9iu.js +1 -0
  111. package/dist/gateway/static/root/assets/dist-DusecO_p.js +1 -0
  112. package/dist/gateway/static/root/assets/docx-preview-CnIClbYi.js +20 -0
  113. package/dist/gateway/static/root/assets/earth-BMhZtzcj.js +1 -0
  114. package/dist/gateway/static/root/assets/echarts-runtime-QSmTlXOu.js +18 -0
  115. package/dist/gateway/static/root/assets/electron-env-DHOGevH3.js +1 -0
  116. package/dist/gateway/static/root/assets/extension-debug-page-BsK2LMXQ.js +1 -0
  117. package/dist/gateway/static/root/assets/extension-iframe-host-Dhkk5JV2.js +1 -0
  118. package/dist/gateway/static/root/assets/extension-marketplace-api-CVJPqJOB.js +1 -0
  119. package/dist/gateway/static/root/assets/extension-page-Brps2XDP.js +1 -0
  120. package/dist/gateway/static/root/assets/extension-paths-DvuaZJuy.js +1 -0
  121. package/dist/gateway/static/root/assets/extension-provider-Byrd8Sor.js +1 -0
  122. package/dist/gateway/static/root/assets/extension-settings-page-CHY68DpG.js +1 -0
  123. package/dist/gateway/static/root/assets/file-BqMS_3DT.js +1 -0
  124. package/dist/gateway/static/root/assets/file-archive-DanfQJNe.js +1 -0
  125. package/dist/gateway/static/root/assets/file-preview-surface-BlprUrIs.js +1 -0
  126. package/dist/gateway/static/root/assets/file-text-D12HbeVy.js +1 -0
  127. package/dist/gateway/static/root/assets/file-tree-CFlZnV3Y.js +1 -0
  128. package/dist/gateway/static/root/assets/file-tree-utils-DJs1faGv.js +1 -0
  129. package/dist/gateway/static/root/assets/files-BNL4kkSB.js +1 -0
  130. package/dist/gateway/static/root/assets/floating-ui.dom-seOukHzT.js +1 -0
  131. package/dist/gateway/static/root/assets/folder-CN-pC3XL.js +1 -0
  132. package/dist/gateway/static/root/assets/folder-kanban-CpLlFI1o.js +1 -0
  133. package/dist/gateway/static/root/assets/form-field-width-DJw_jULe.js +1 -0
  134. package/dist/gateway/static/root/assets/{gateway-config-swr-fQKBHBi1.js → gateway-config-swr-BAmUhiP1.js} +1 -1
  135. package/dist/gateway/static/root/assets/gateway-realtime-CsykKL4l.js +1 -0
  136. package/dist/gateway/static/root/assets/gateway-realtime-store-DQqMBruB.js +1 -0
  137. package/dist/gateway/static/root/assets/gateway-restart-Ch128Lrr.js +1 -0
  138. package/dist/gateway/static/root/assets/gateway-settings-BA5-Uuwx.js +1 -0
  139. package/dist/gateway/static/root/assets/{gateway-startup-retry-Cfwxof4k.js → gateway-startup-retry-CtUB3g6N.js} +1 -1
  140. package/dist/gateway/static/root/assets/gauge-C78eD2BA.js +1 -0
  141. package/dist/gateway/static/root/assets/git-branch-Dh9uxTot.js +1 -0
  142. package/dist/gateway/static/root/assets/global-defaults-api-CINf-C6a.js +2 -0
  143. package/dist/gateway/static/root/assets/heart-Cp4rgrqn.js +1 -0
  144. package/dist/gateway/static/root/assets/highlight-code-BH65IIbJ.js +1 -0
  145. package/dist/gateway/static/root/assets/highlighted-body-KQOG7T2V-DKGma5wI.js +1 -0
  146. package/dist/gateway/static/root/assets/history-DXH_9jsE.js +1 -0
  147. package/dist/gateway/static/root/assets/home-page-DaMFBYo1.js +2 -0
  148. package/dist/gateway/static/root/assets/image-Cwyalflz.js +1 -0
  149. package/dist/gateway/static/root/assets/image-generation-api-I_JgLL_m.js +1 -0
  150. package/dist/gateway/static/root/assets/imports-page-BWShtGRQ.js +1 -0
  151. package/dist/gateway/static/root/assets/index-BpCi0TdG.js +11 -0
  152. package/dist/gateway/static/root/assets/index-DY2Y83b9.css +1 -0
  153. package/dist/gateway/static/root/assets/index.module-Cd9ENXfk.js +1 -0
  154. package/dist/gateway/static/root/assets/info-CDrmIZhb.js +1 -0
  155. package/dist/gateway/static/root/assets/install-connector-dialog-DU1Tz7B3.js +1 -0
  156. package/dist/gateway/static/root/assets/interaction-BdhHBbYa.js +1 -0
  157. package/dist/gateway/static/root/assets/is-masked-secret-DOkL5b_X.js +1 -0
  158. package/dist/gateway/static/root/assets/{jszip.min-DT31yWkU.js → jszip.min-Dj17eJqX.js} +1 -1
  159. package/dist/gateway/static/root/assets/key-round-DWbpyU2U.js +1 -0
  160. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-CdM4BQwp.js +1 -0
  161. package/dist/gateway/static/root/assets/languages-zXtNocoy.js +2 -0
  162. package/dist/gateway/static/root/assets/laptop-CI3hBVrl.js +1 -0
  163. package/dist/gateway/static/root/assets/layers-mJW7JJKm.js +1 -0
  164. package/dist/gateway/static/root/assets/layout-grid-CEVZdVFU.js +1 -0
  165. package/dist/gateway/static/root/assets/list-checks-BbsExAoq.js +1 -0
  166. package/dist/gateway/static/root/assets/list-filter-COkzTdOz.js +1 -0
  167. package/dist/gateway/static/root/assets/list-todo-CTVRto8O.js +1 -0
  168. package/dist/gateway/static/root/assets/list-tree-B0OMswgM.js +1 -0
  169. package/dist/gateway/static/root/assets/local-app-workbench-page-qPflPuQD.js +1 -0
  170. package/dist/gateway/static/root/assets/local-apps-Ck6kACsY.js +1 -0
  171. package/dist/gateway/static/root/assets/local-apps-page-CxyRVfjD.js +1 -0
  172. package/dist/gateway/static/root/assets/local-session-drafts-B9ZPwotC.js +1 -0
  173. package/dist/gateway/static/root/assets/{locale-store-B7s2Hb35.js → locale-store-lIXD1FMw.js} +1 -1
  174. package/dist/gateway/static/root/assets/lock-keyhole-DEK5kH0u.js +1 -0
  175. package/dist/gateway/static/root/assets/logs-page-CbY1N-zi.js +2 -0
  176. package/dist/gateway/static/root/assets/loopi-C09I2mNj.css +1 -0
  177. package/dist/gateway/static/root/assets/loopi-CNtmi9FU.js +1 -0
  178. package/dist/gateway/static/root/assets/management-settings-Diy12JfQ.js +1 -0
  179. package/dist/gateway/static/root/assets/{markdown-editor-phTQ0mox.js → markdown-editor-BuuGlcfG.js} +1 -1
  180. package/dist/gateway/static/root/assets/markdown-view-C-DHb3Io.css +1 -0
  181. package/dist/gateway/static/root/assets/markdown-view-CJt-i2Dp.js +324 -0
  182. package/dist/gateway/static/root/assets/{media-plugins-DYQDjCVQ.js → media-plugins-D_bR23mA.js} +1 -1
  183. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-Ur99GwOg.js +1 -0
  184. package/dist/gateway/static/root/assets/mermaid-render-oOellPHt.js +134 -0
  185. package/dist/gateway/static/root/assets/message-circle-Badhj-4D.js +1 -0
  186. package/dist/gateway/static/root/assets/message-square-fVE7Ghj1.js +1 -0
  187. package/dist/gateway/static/root/assets/message-square-plus-XP0tGdlV.js +1 -0
  188. package/dist/gateway/static/root/assets/{messages-BYq0cPbn.js → messages-DRR9N3HC.js} +1 -1
  189. package/dist/gateway/static/root/assets/messages-square-BckAJrEW.js +1 -0
  190. package/dist/gateway/static/root/assets/mic-CuUb7zc-.js +1 -0
  191. package/dist/gateway/static/root/assets/minimize-2-DtOGrlpo.js +1 -0
  192. package/dist/gateway/static/root/assets/mobile-pair-qr-CuIbmw5x.js +1 -0
  193. package/dist/gateway/static/root/assets/model-selector-DCYA_ntf.js +1 -0
  194. package/dist/gateway/static/root/assets/models-hub-cache-za2fWJLg.js +1 -0
  195. package/dist/gateway/static/root/assets/monitor-Af5eAvF7.js +1 -0
  196. package/dist/gateway/static/root/assets/mouse-pointer-2-DZ51Onvj.js +1 -0
  197. package/dist/gateway/static/root/assets/navigation-BkjnOw30.js +1 -0
  198. package/dist/gateway/static/root/assets/network-BUQLY1BV.js +1 -0
  199. package/dist/gateway/static/root/assets/new-session-preferences-gb411vZP.js +1 -0
  200. package/dist/gateway/static/root/assets/note-detail-panel-DBs1yHLy.js +5 -0
  201. package/dist/gateway/static/root/assets/note-image-lightbox-CivkB6LB.js +1 -0
  202. package/dist/gateway/static/root/assets/notes-api-C_458rv5.js +1 -0
  203. package/dist/gateway/static/root/assets/notes-page-DL3c-41a.js +8 -0
  204. package/dist/gateway/static/root/assets/number-input-El7Szeln.js +1 -0
  205. package/dist/gateway/static/root/assets/oauth-api-C3X9FLYw.js +1 -0
  206. package/dist/gateway/static/root/assets/oauth-authorization-window-o6URRos4.js +1 -0
  207. package/dist/gateway/static/root/assets/oauth-provider-connect-H81se_3n.js +1 -0
  208. package/dist/gateway/static/root/assets/package-wATCyihJ.js +1 -0
  209. package/dist/gateway/static/root/assets/page-context-capture-button-BkAlQ7cB.js +1 -0
  210. package/dist/gateway/static/root/assets/page-context-draft-ClLgaOaD.js +1 -0
  211. package/dist/gateway/static/root/assets/page-header-store-DH8K0xii.js +1 -0
  212. package/dist/gateway/static/root/assets/page-tabs-oeTY7z3_.js +1 -0
  213. package/dist/gateway/static/root/assets/panel-left-C8MqSXRZ.js +1 -0
  214. package/dist/gateway/static/root/assets/panel-right-CFGrHTsD.js +1 -0
  215. package/dist/gateway/static/root/assets/paperclip-f1HujQY1.js +1 -0
  216. package/dist/gateway/static/root/assets/pause-DuPxgSxk.js +1 -0
  217. package/dist/gateway/static/root/assets/{pdf-D4PI9qAw.js → pdf-EQHMWEbX.js} +3 -3
  218. package/dist/gateway/static/root/assets/pdf-runtime-JnUAvfIa.js +2 -0
  219. package/dist/gateway/static/root/assets/{pdf.worker.min-B4E34YdZ.js → pdf.worker.min-bpyjgR8v.js} +7 -7
  220. package/dist/gateway/static/root/assets/pencil-DmIY3Oa-.js +1 -0
  221. package/dist/gateway/static/root/assets/personal-avatar-BLtHt8fV.js +1 -0
  222. package/dist/gateway/static/root/assets/personal-avatar-BUCb7OiW.css +1 -0
  223. package/dist/gateway/static/root/assets/personal-page-B5DP3lO-.js +1 -0
  224. package/dist/gateway/static/root/assets/personal-proactivity-DaRnbB1f.js +1 -0
  225. package/dist/gateway/static/root/assets/personal-settings-panel-DjDc5Kaz.js +1 -0
  226. package/dist/gateway/static/root/assets/phone-dependencies-card-DISHarj8.js +1 -0
  227. package/dist/gateway/static/root/assets/phone-model-picker-u8YIQCgo.js +1 -0
  228. package/dist/gateway/static/root/assets/phone-settings-page-el3pT0PD.js +1 -0
  229. package/dist/gateway/static/root/assets/phone-workspace-store-fhnZrgy_.js +1 -0
  230. package/dist/gateway/static/root/assets/pin-off-BMRv-Kxr.js +1 -0
  231. package/dist/gateway/static/root/assets/play-kxZvpBg8.js +1 -0
  232. package/dist/gateway/static/root/assets/plug-DKYPEgkR.js +1 -0
  233. package/dist/gateway/static/root/assets/plug-zap-L8NMe3Sv.js +1 -0
  234. package/dist/gateway/static/root/assets/plugin-details-dialog-CTBs1Jde.js +1 -0
  235. package/dist/gateway/static/root/assets/plus-Q2yW6OE7.js +1 -0
  236. package/dist/gateway/static/root/assets/popover-select-DniHw2dy.js +1 -0
  237. package/dist/gateway/static/root/assets/power-ZI-pBczI.js +1 -0
  238. package/dist/gateway/static/root/assets/power-off-CwwQ7Gp7.js +1 -0
  239. package/dist/gateway/static/root/assets/preference-select-fields-D7oluyHN.js +1 -0
  240. package/dist/gateway/static/root/assets/preload-helper-Czpn1I53.js +1 -0
  241. package/dist/gateway/static/root/assets/preview-open-alternatives-CY_hjK4b.js +1 -0
  242. package/dist/gateway/static/root/assets/product-automation-feedback-DsUSqCOX.js +7 -0
  243. package/dist/gateway/static/root/assets/product-delivery-BU_H84jL.js +1 -0
  244. package/dist/gateway/static/root/assets/product-navigation-Co8pLbDP.js +1 -0
  245. package/dist/gateway/static/root/assets/product-open-page-xn9G4hSI.js +1 -0
  246. package/dist/gateway/static/root/assets/product-preview-content-DcoK-iZe.js +1 -0
  247. package/dist/gateway/static/root/assets/product-preview-modal-Ruw9WSKK.js +2 -0
  248. package/dist/gateway/static/root/assets/project-detail-page-BKvWLiMw.js +7 -0
  249. package/dist/gateway/static/root/assets/project-understanding-BCQr0AZ_.js +1 -0
  250. package/dist/gateway/static/root/assets/projects-page-D4g7bB7X.js +1 -0
  251. package/dist/gateway/static/root/assets/providers-api-CzVkFKFg.js +1 -0
  252. package/dist/gateway/static/root/assets/puzzle-BptcPjKI.js +1 -0
  253. package/dist/gateway/static/root/assets/recording-upload-0jxahBMo.js +1 -0
  254. package/dist/gateway/static/root/assets/refresh-button-bU_0NarN.js +1 -0
  255. package/dist/gateway/static/root/assets/refresh-cw-BRlGaq2w.js +1 -0
  256. package/dist/gateway/static/root/assets/{registry-api-BcfoLEna.js → registry-api-n8TwtJ_j.js} +2 -2
  257. package/dist/gateway/static/root/assets/remote-access-hub-cZpBi4Rk.js +1 -0
  258. package/dist/gateway/static/root/assets/rotate-ccw-JM1TBLpp.js +1 -0
  259. package/dist/gateway/static/root/assets/rotate-cw-LIg3Am9S.js +1 -0
  260. package/dist/gateway/static/root/assets/route-preload-B5UiReO7.js +2 -0
  261. package/dist/gateway/static/root/assets/runtime-health-D2TDFLLq.js +1 -0
  262. package/dist/gateway/static/root/assets/{runtime-tools-api-DesqGCnE.js → runtime-tools-api-D-8KjYK6.js} +1 -1
  263. package/dist/gateway/static/root/assets/runtime-tools-settings-panel-MKlLFuow.js +1 -0
  264. package/dist/gateway/static/root/assets/save-DRDABU--.js +1 -0
  265. package/dist/gateway/static/root/assets/schema-form-v4N4lawq.js +1 -0
  266. package/dist/gateway/static/root/assets/schemas-CCWMleym.js +55 -0
  267. package/dist/gateway/static/root/assets/search-DA7gz22f.js +1 -0
  268. package/dist/gateway/static/root/assets/secret-input-BQvFXqzz.js +1 -0
  269. package/dist/gateway/static/root/assets/secret-input-labels-B5Jl5HqK.js +1 -0
  270. package/dist/gateway/static/root/assets/segmented-styles-Cqb91xsn.js +1 -0
  271. package/dist/gateway/static/root/assets/send-1f1Ntw6E.js +1 -0
  272. package/dist/gateway/static/root/assets/server-BlHCBjiE.js +1 -0
  273. package/dist/gateway/static/root/assets/service-recommendation-list-B1xuVT3N.js +1 -0
  274. package/dist/gateway/static/root/assets/{session-api-DdQnMwkl.js → session-api-CsCoI2im.js} +1 -1
  275. package/dist/gateway/static/root/assets/session-channel-icon-SsY70Z6t.js +1 -0
  276. package/dist/gateway/static/root/assets/session-identity-label-B7sgG1PE.js +1 -0
  277. package/dist/gateway/static/root/assets/session-manager-5l9q0cd5.js +16 -0
  278. package/dist/gateway/static/root/assets/sessions-page-DsLw2aMD.js +1 -0
  279. package/dist/gateway/static/root/assets/settings-2-D-csvaET.js +1 -0
  280. package/dist/gateway/static/root/assets/settings-advanced-gate-B5lQeVNi.js +1 -0
  281. package/dist/gateway/static/root/assets/settings-advanced-section-BqoVSko2.js +1 -0
  282. package/dist/gateway/static/root/assets/settings-form-draft-Dy10ldo8.js +1 -0
  283. package/dist/gateway/static/root/assets/settings-form-section-num14vSv.js +1 -0
  284. package/dist/gateway/static/root/assets/settings-loading-skeleton-BTqvr_Fw.js +1 -0
  285. package/dist/gateway/static/root/assets/settings-mode-store-CBsJ-Qg2.js +1 -0
  286. package/dist/gateway/static/root/assets/settings-page-DROUGyJl.js +1 -0
  287. package/dist/gateway/static/root/assets/settings-page-header-Bv-kQFTm.js +1 -0
  288. package/dist/gateway/static/root/assets/settings-page-layout-DHP6MrrL.js +1 -0
  289. package/dist/gateway/static/root/assets/settings-uiTATseT.js +1 -0
  290. package/dist/gateway/static/root/assets/setup-status-panel-MJE3B_LX.js +1 -0
  291. package/dist/gateway/static/root/assets/share-link-dialog-BJHRQVKC.js +1 -0
  292. package/dist/gateway/static/root/assets/share-preview-page-Bsrv_zOQ.js +2 -0
  293. package/dist/gateway/static/root/assets/shares-api-rtWVHA_d.js +1 -0
  294. package/dist/gateway/static/root/assets/shares-settings-CfIRv4uX.js +1 -0
  295. package/dist/gateway/static/root/assets/shield-B1sI_cxl.js +1 -0
  296. package/dist/gateway/static/root/assets/shield-check-BU58siTV.js +1 -0
  297. package/dist/gateway/static/root/assets/shield-off-2jsucUds.js +1 -0
  298. package/dist/gateway/static/root/assets/side-chat-shortcut-BIw-1TTD.js +1 -0
  299. package/dist/gateway/static/root/assets/skill-api-B_W1K3sv.js +1 -0
  300. package/dist/gateway/static/root/assets/skill-api-utils-C7V4JVXM.js +1 -0
  301. package/dist/gateway/static/root/assets/skill-list-api-BzlKXPsE.js +1 -0
  302. package/dist/gateway/static/root/assets/skill-reload-api-Cff2GgZb.js +1 -0
  303. package/dist/gateway/static/root/assets/skill-wire-pattern-BPpeIcCi.js +1 -0
  304. package/dist/gateway/static/root/assets/skills-page-DtBloYeU.js +2 -0
  305. package/dist/gateway/static/root/assets/sliders-horizontal-DqsYor6I.js +1 -0
  306. package/dist/gateway/static/root/assets/sliding-tab-list-DuQyViqe.js +1 -0
  307. package/dist/gateway/static/root/assets/smartphone-DSSsQFqA.js +1 -0
  308. package/dist/gateway/static/root/assets/{source-workspace-editor-BIvi89Zx.js → source-workspace-editor-kxosllTu.js} +1 -1
  309. package/dist/gateway/static/root/assets/sparkles-DHlfQFAF.js +1 -0
  310. package/dist/gateway/static/root/assets/specialists-xbB3xL9e.js +1 -0
  311. package/dist/gateway/static/root/assets/square-DMK_fB-3.js +1 -0
  312. package/dist/gateway/static/root/assets/square-pen-B8FsvqNu.js +1 -0
  313. package/dist/gateway/static/root/assets/square-terminal-K87bylpZ.js +1 -0
  314. package/dist/gateway/static/root/assets/star-BUWJqJ5c.js +1 -0
  315. package/dist/gateway/static/root/assets/stethoscope-DRqTAtjD.js +1 -0
  316. package/dist/gateway/static/root/assets/sticky-note-fzP7NAJq.js +1 -0
  317. package/dist/gateway/static/root/assets/store-SzD1Jvgm.js +1 -0
  318. package/dist/gateway/static/root/assets/system-settings-panel-BeQeUUMH.js +1 -0
  319. package/dist/gateway/static/root/assets/task-detail-page-Drrv-Hp0.js +2 -0
  320. package/dist/gateway/static/root/assets/task-result-evidence-D1Kyskm_.js +1 -0
  321. package/dist/gateway/static/root/assets/tasks-DRmd6sWt.js +1 -0
  322. package/dist/gateway/static/root/assets/terminal-oKqqZdiG.js +1 -0
  323. package/dist/gateway/static/root/assets/terminal-panel-store-5Fzctajw.js +1 -0
  324. package/dist/gateway/static/root/assets/theme-store-DW45fWYQ.js +1 -0
  325. package/dist/gateway/static/root/assets/timer-rCwGHjuO.js +1 -0
  326. package/dist/gateway/static/root/assets/tool-friendly-title-DGmi7rCQ.js +1 -0
  327. package/dist/gateway/static/root/assets/tracing-settings-page-B12u5D9A.js +1 -0
  328. package/dist/gateway/static/root/assets/trash-2-DusmjVPV.js +1 -0
  329. package/dist/gateway/static/root/assets/triangle-alert-2JXFNNKU.js +1 -0
  330. package/dist/gateway/static/root/assets/tunnel-api-DGO56LQU.js +1 -0
  331. package/dist/gateway/static/root/assets/understanding-activity-store-CTe6TFB0.js +1 -0
  332. package/dist/gateway/static/root/assets/understanding-refresh-store-mE9OKG6q.js +1 -0
  333. package/dist/gateway/static/root/assets/unlink-BEuthaaq.js +1 -0
  334. package/dist/gateway/static/root/assets/upload-rrb46c3c.js +1 -0
  335. package/dist/gateway/static/root/assets/usage-page-Ud2U9UG1.js +1 -0
  336. package/dist/gateway/static/root/assets/use-async-resource-BHFGZCY2.js +1 -0
  337. package/dist/gateway/static/root/assets/use-autosave-Cs2Ga_Y_.js +1 -0
  338. package/dist/gateway/static/root/assets/use-composer-attachments-BCbMj-MN.js +2 -0
  339. package/dist/gateway/static/root/assets/use-directory-picker-C4p7AgWY.js +1 -0
  340. package/dist/gateway/static/root/assets/use-file-preview-expanded-DSpCRXUW.js +2 -0
  341. package/dist/gateway/static/root/assets/use-media-query-ady-FgjK.js +1 -0
  342. package/dist/gateway/static/root/assets/use-personal-profile-BHL2AxWU.js +1 -0
  343. package/dist/gateway/static/root/assets/use-workspace-tree-CnmPZrpx.js +1 -0
  344. package/dist/gateway/static/root/assets/user-model-page-p5iPfnwl.js +2 -0
  345. package/dist/gateway/static/root/assets/user-round-C9jxPhMR.js +1 -0
  346. package/dist/gateway/static/root/assets/{vendor-codemirror-Qdcjid65.js → vendor-codemirror-aCQ0FcJT.js} +8 -8
  347. package/dist/gateway/static/root/assets/{vendor-swr-BIWyz7Rc.js → vendor-swr-CdRzEUwF.js} +1 -1
  348. package/dist/gateway/static/root/assets/video-B6V0GFss.js +1 -0
  349. package/dist/gateway/static/root/assets/voice-api-key-field-3gyc2UV3.js +1 -0
  350. package/dist/gateway/static/root/assets/voice-call-context-BM2A4bLz.js +1 -0
  351. package/dist/gateway/static/root/assets/{voice-config-api-BkUlN7GH.js → voice-config-api-Cda2uBIC.js} +1 -1
  352. package/dist/gateway/static/root/assets/voice-input-shortcut-events-DtYHsPLF.js +1 -0
  353. package/dist/gateway/static/root/assets/voice-transcribe-api-TInEfIYo.js +1 -0
  354. package/dist/gateway/static/root/assets/volume-2-BSJhAY97.js +1 -0
  355. package/dist/gateway/static/root/assets/wand-sparkles-CkSL-3Fy.js +1 -0
  356. package/dist/gateway/static/root/assets/{with-selector-aYPsXwdl.js → with-selector-xonYxPoM.js} +1 -1
  357. package/dist/gateway/static/root/assets/work-discovery-overlay-Dqu5CQCS.js +1 -0
  358. package/dist/gateway/static/root/assets/work-discovery-page-p-8ciZ0i.js +1 -0
  359. package/dist/gateway/static/root/assets/working-directory-picker-modal-DHl2cZY1.js +1 -0
  360. package/dist/gateway/static/root/assets/workspace-api-CtDbI6T7.js +2 -0
  361. package/dist/gateway/static/root/assets/workspace-editor-agent-store-B94Q2nN8.js +1 -0
  362. package/dist/gateway/static/root/assets/workspace-file-preview-dialog-CTIbUfKb.js +1 -0
  363. package/dist/gateway/static/root/assets/workspace-open-location-menu-BwxouqdZ.js +1 -0
  364. package/dist/gateway/static/root/assets/wrench-DFb4r8bH.js +1 -0
  365. package/dist/gateway/static/root/assets/x-B_N4OPjy.js +1 -0
  366. package/dist/gateway/static/root/assets/{xlsx-CKkngM-o.js → xlsx-Cl_0CZaL.js} +11 -11
  367. package/dist/gateway/static/root/assets/xml-_d7dTN2Q.js +3 -0
  368. package/dist/gateway/static/root/assets/xopc-cloud-account-card-CFb-23rS.js +1 -0
  369. package/dist/gateway/static/root/assets/zap-dximCGjy.js +1 -0
  370. package/dist/gateway/static/root/browser-setup-test.html +5 -0
  371. package/dist/gateway/static/root/browser-setup-test.js +7 -0
  372. package/dist/gateway/static/root/index.html +267 -46
  373. package/dist/package.js +1 -1
  374. package/dist/packages/gateway-contract/src/browser-setup.js +6 -0
  375. package/dist/packages/gateway-contract/src/index.js +4 -0
  376. package/dist/packages/gateway-contract/src/phone-setup.js +6 -0
  377. package/dist/packages/realtime-client/src/index.js +1 -0
  378. package/dist/packages/realtime-protocol/src/index.js +1 -0
  379. package/dist/src/activity/emitter.js +1 -2
  380. package/dist/src/activity/service.js +1 -2
  381. package/dist/src/agent/agent-manager.d.ts +5 -0
  382. package/dist/src/agent/agent-manager.js +16 -6
  383. package/dist/src/agent/background-review/run-background-review.js +2 -3
  384. package/dist/src/agent/context/execution-context.js +1 -2
  385. package/dist/src/agent/context/execution-scope.js +1 -2
  386. package/dist/src/agent/context/project-context.js +1 -2
  387. package/dist/src/agent/embedded/agent-profile-context.js +1 -2
  388. package/dist/src/agent/embedded/run-turn.js +2 -4
  389. package/dist/src/agent/embedded/sqlite-hydrating-session-manager.js +1 -2
  390. package/dist/src/agent/embedded/tool-search-extension.js +14 -1
  391. package/dist/src/agent/external-tools/cliProvider.js +3 -4
  392. package/dist/src/agent/external-tools/composio-provider.js +3 -4
  393. package/dist/src/agent/external-tools/endpoint-provider.js +2 -2
  394. package/dist/src/agent/memory/compaction-promotion.js +1 -2
  395. package/dist/src/agent/orchestration/research-checkpoint.js +26 -31
  396. package/dist/src/agent/prompt/response-language.js +1 -2
  397. package/dist/src/agent/prompt/service-prompt-builder.js +3 -6
  398. package/dist/src/agent/prompt/system-prompt.js +1 -2
  399. package/dist/src/agent/service/direct-turn-helpers.js +1 -2
  400. package/dist/src/agent/service/process-direct-streaming.js +1 -2
  401. package/dist/src/agent/service/webchat-tts.js +1 -2
  402. package/dist/src/agent/service.d.ts +1 -0
  403. package/dist/src/agent/service.js +8 -3
  404. package/dist/src/agent/service.types.d.ts +3 -0
  405. package/dist/src/agent/skills/index.js +1 -1
  406. package/dist/src/agent/skills/managed-store.js +1 -1
  407. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  408. package/dist/src/agent/tool-manuals/computer.d.ts +1 -1
  409. package/dist/src/agent/tool-manuals/computer.js +2 -0
  410. package/dist/src/agent/tool-manuals/phone.d.ts +1 -1
  411. package/dist/src/agent/tool-manuals/phone.js +14 -4
  412. package/dist/src/agent/tool-manuals/xopc-configuration.d.ts +2 -0
  413. package/dist/src/agent/tool-manuals/xopc-configuration.js +29 -0
  414. package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +2 -0
  415. package/dist/src/agent/tools/browser/tool/browser-use-tool.js +6 -2
  416. package/dist/src/agent/tools/delegate-tool.js +2 -4
  417. package/dist/src/agent/tools/factory.d.ts +4 -0
  418. package/dist/src/agent/tools/factory.js +23 -9
  419. package/dist/src/agent/tools/personal-read-tool.js +1 -1
  420. package/dist/src/agent/tools/personal-task-tool.js +1 -2
  421. package/dist/src/agent/tools/phone-use-tool.d.ts +2 -0
  422. package/dist/src/agent/tools/phone-use-tool.js +79 -4
  423. package/dist/src/agent/tools/research-checkpoint-tool.js +1 -2
  424. package/dist/src/agent/tools/tool-manual-tool.d.ts +1 -1
  425. package/dist/src/agent/tools/tool-manual-tool.js +3 -1
  426. package/dist/src/agent/tools/toolExposure.js +3 -0
  427. package/dist/src/agent/tools/xopc-use-tool.d.ts +5 -2
  428. package/dist/src/agent/tools/xopc-use-tool.js +47 -6
  429. package/dist/src/agent-catalog/capabilities.js +2 -2
  430. package/dist/src/agent-catalog/repository.js +3 -4
  431. package/dist/src/agent-catalog/test-support.js +1 -2
  432. package/dist/src/agent-matching/selection-repository.js +1 -2
  433. package/dist/src/automations/capabilities/drafts.js +3 -5
  434. package/dist/src/bootstrap/application-state.js +1 -2
  435. package/dist/src/browser/automations/repository.js +1 -2
  436. package/dist/src/browser/drivers/browser-driver.d.ts +2 -2
  437. package/dist/src/browser/drivers/extension-driver.d.ts +2 -2
  438. package/dist/src/browser/drivers/extension-driver.js +6 -3
  439. package/dist/src/browser/native-messaging-host.js +2 -4
  440. package/dist/src/browser/providers/browser-ext-install.js +3 -2
  441. package/dist/src/browser/providers/realtime-extension.js +1 -2
  442. package/dist/src/browser/recordings/service.js +1 -2
  443. package/dist/src/browser/runtime/browser-runtime.d.ts +4 -1
  444. package/dist/src/browser/runtime/browser-runtime.js +29 -17
  445. package/dist/src/browser/setup/repository.d.ts +5 -0
  446. package/dist/src/browser/setup/repository.js +42 -0
  447. package/dist/src/browser/setup/service.d.ts +157 -0
  448. package/dist/src/browser/setup/service.js +433 -0
  449. package/dist/src/browser/setup/types.d.ts +38 -0
  450. package/dist/src/browser/setup/types.js +1 -0
  451. package/dist/src/capabilities/runtime/dispatcher.js +1 -1
  452. package/dist/src/capabilities/runtime/product.js +1 -1
  453. package/dist/src/chat-previews/store.js +1 -2
  454. package/dist/src/cli/commands/agents.js +1 -1
  455. package/dist/src/cli/commands/doctor/checks/automation-integrity.js +1 -2
  456. package/dist/src/cli/commands/doctor/checks/database-relations.js +1 -2
  457. package/dist/src/cli/commands/doctor/checks/database-schema.js +2 -3
  458. package/dist/src/cli/commands/doctor/checks/node-version.js +6 -6
  459. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -2
  460. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  461. package/dist/src/cli/commands/gateway/shared.js +1 -2
  462. package/dist/src/cli/commands/history.js +1 -2
  463. package/dist/src/cli/commands/models.js +1 -1
  464. package/dist/src/cli/commands/onboard/model.js +1 -1
  465. package/dist/src/cli/commands/project.js +1 -2
  466. package/dist/src/cli/utils/init-workspace-core.js +1 -1
  467. package/dist/src/computer/diagnostics.d.ts +7 -7
  468. package/dist/src/computer/diagnostics.js +8 -2
  469. package/dist/src/computer/errors.js +9 -1
  470. package/dist/src/computer/evaluation.d.ts +4 -4
  471. package/dist/src/computer/keyboard.d.ts +1 -1
  472. package/dist/src/computer/keyboard.js +10 -2
  473. package/dist/src/computer/model-adapter.js +27 -7
  474. package/dist/src/config/agent-profile.js +1 -1
  475. package/dist/src/config/gateway-bind.js +1 -2
  476. package/dist/src/config/schema.d.ts +7 -0
  477. package/dist/src/connectors/cli/lifecycle.js +1 -2
  478. package/dist/src/connectors/composio-managed-events.js +1 -2
  479. package/dist/src/connectors/connected-source-ingestion.js +1 -2
  480. package/dist/src/connectors/connected-source-understanding.js +3 -5
  481. package/dist/src/connectors/content-enrichment.js +1 -2
  482. package/dist/src/connectors/learning-coordinator.js +2 -3
  483. package/dist/src/connectors/runtime-adapter-registry.js +1 -2
  484. package/dist/src/daemon/constants.js +9 -14
  485. package/dist/src/daemon/index.js +1 -4
  486. package/dist/src/daemon/install-plan.js +1 -2
  487. package/dist/src/daemon/launchd.js +1 -2
  488. package/dist/src/daemon/schtasks.js +1 -2
  489. package/dist/src/daemon/service-audit.js +1 -2
  490. package/dist/src/daemon/service.js +1 -2
  491. package/dist/src/daemon/systemd.js +1 -2
  492. package/dist/src/discussions/analyzer.d.ts +3 -3
  493. package/dist/src/endpoint-tools/runtime.js +1 -2
  494. package/dist/src/execution-environments/local-worktree-manager.js +1 -1
  495. package/dist/src/execution-environments/subject.js +1 -2
  496. package/dist/src/extensions/agent-plugins/branding.js +2 -1
  497. package/dist/src/extensions/agent-plugins/cli-authorization.js +2 -1
  498. package/dist/src/extensions/agent-plugins/contained-path.d.ts +1 -0
  499. package/dist/src/extensions/agent-plugins/contained-path.js +29 -0
  500. package/dist/src/extensions/agent-plugins/mcp-adapter.js +2 -1
  501. package/dist/src/extensions/agent-plugins/resources.js +1 -1
  502. package/dist/src/extensions/agent-plugins/skill-catalog.js +3 -2
  503. package/dist/src/extensions/agent-plugins/source-catalog.js +1 -1
  504. package/dist/src/extensions/agent-plugins/store.js +2 -1
  505. package/dist/src/extensions/agent-plugins/validation.d.ts +1 -2
  506. package/dist/src/extensions/agent-plugins/validation.js +3 -26
  507. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  508. package/dist/src/gateway/agents-admin.js +2 -2
  509. package/dist/src/gateway/client-ip.js +1 -2
  510. package/dist/src/gateway/file-space-service.js +1 -2
  511. package/dist/src/gateway/global-defaults-admin.js +1 -1
  512. package/dist/src/gateway/hono/app.js +2 -4
  513. package/dist/src/gateway/hono/middleware/auth.js +3 -6
  514. package/dist/src/gateway/hono/middleware/logger.js +1 -2
  515. package/dist/src/gateway/hono/middleware/public-device-rate-limit.js +1 -2
  516. package/dist/src/gateway/hono/middleware/scopes.js +1 -2
  517. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +1 -2
  518. package/dist/src/gateway/hono/oauth-async.js +1 -2
  519. package/dist/src/gateway/hono/routes/agents.js +1 -1
  520. package/dist/src/gateway/hono/routes/browser-session.js +1 -2
  521. package/dist/src/gateway/hono/routes/browser-setup.d.ts +3 -0
  522. package/dist/src/gateway/hono/routes/browser-setup.js +114 -0
  523. package/dist/src/gateway/hono/routes/browser.d.ts +2 -1
  524. package/dist/src/gateway/hono/routes/browser.js +4 -7
  525. package/dist/src/gateway/hono/routes/cli-connectors.js +1 -2
  526. package/dist/src/gateway/hono/routes/composer-history.js +1 -2
  527. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  528. package/dist/src/gateway/hono/routes/config.js +1 -2
  529. package/dist/src/gateway/hono/routes/connectors.js +9 -11
  530. package/dist/src/gateway/hono/routes/context-sources.js +1 -2
  531. package/dist/src/gateway/hono/routes/device-pairing-approval.js +2 -4
  532. package/dist/src/gateway/hono/routes/device-push.js +1 -2
  533. package/dist/src/gateway/hono/routes/devices.js +4 -8
  534. package/dist/src/gateway/hono/routes/discussions.js +1 -2
  535. package/dist/src/gateway/hono/routes/endpoint-tools.js +1 -2
  536. package/dist/src/gateway/hono/routes/home.js +2 -3
  537. package/dist/src/gateway/hono/routes/interaction-state.js +1 -2
  538. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  539. package/dist/src/gateway/hono/routes/memory-learning.js +1 -2
  540. package/dist/src/gateway/hono/routes/notes.js +2 -2
  541. package/dist/src/gateway/hono/routes/personal-agent.js +1 -2
  542. package/dist/src/gateway/hono/routes/phone-dependencies.js +2 -7
  543. package/dist/src/gateway/hono/routes/phone-setup.d.ts +7 -0
  544. package/dist/src/gateway/hono/routes/phone-setup.js +231 -0
  545. package/dist/src/gateway/hono/routes/phone-wireless.d.ts +4 -0
  546. package/dist/src/gateway/hono/routes/phone-wireless.js +63 -0
  547. package/dist/src/gateway/hono/routes/phone.js +119 -28
  548. package/dist/src/gateway/hono/routes/projects.js +3 -4
  549. package/dist/src/gateway/hono/routes/public-gateway.js +4 -3
  550. package/dist/src/gateway/hono/routes/session-input-handler.js +1 -1
  551. package/dist/src/gateway/hono/routes/sessions.js +2 -4
  552. package/dist/src/gateway/hono/routes/shares.js +2 -4
  553. package/dist/src/gateway/hono/routes/tasks.js +2 -3
  554. package/dist/src/gateway/hono/routes/user-model-refresh.js +1 -2
  555. package/dist/src/gateway/hono/routes/user-model.js +1 -2
  556. package/dist/src/gateway/host.js +4 -9
  557. package/dist/src/gateway/image-generation-setup.js +1 -1
  558. package/dist/src/gateway/index.js +2 -6
  559. package/dist/src/gateway/listen.js +1 -2
  560. package/dist/src/gateway/next-turn-suggestions/service.js +1 -2
  561. package/dist/src/gateway/next-turn-suggestions/snapshot.js +1 -2
  562. package/dist/src/gateway/provider-model-setup.js +1 -1
  563. package/dist/src/gateway/rate-limit/auth-policy.js +11 -7
  564. package/dist/src/gateway/rate-limit/buckets.js +220 -211
  565. package/dist/src/gateway/rate-limit/env-flags.js +1 -4
  566. package/dist/src/gateway/rate-limit/index.js +4 -13
  567. package/dist/src/gateway/runtime-config.js +2 -4
  568. package/dist/src/gateway/security/audit.js +1 -2
  569. package/dist/src/gateway/security/browser-session.js +1 -2
  570. package/dist/src/gateway/security/device-request-proof.d.ts +1 -2
  571. package/dist/src/gateway/security/device-request-proof.js +2 -4
  572. package/dist/src/gateway/security/gateway-scopes.js +2 -6
  573. package/dist/src/gateway/security/index.js +1 -4
  574. package/dist/src/gateway/security/loopback.js +6 -7
  575. package/dist/src/gateway/service/agent-runner.js +2 -4
  576. package/dist/src/gateway/service/app-context-access.js +1 -2
  577. package/dist/src/gateway/service/config-coordinator.d.ts +4 -0
  578. package/dist/src/gateway/service/run-gateway-agent.js +2 -4
  579. package/dist/src/gateway/service/session-input-coordinator.js +3 -6
  580. package/dist/src/gateway/service.d.ts +5 -0
  581. package/dist/src/gateway/service.js +64 -22
  582. package/dist/src/gateway/session-context-summary.js +2 -4
  583. package/dist/src/gateway/tailscale-auth.js +1 -2
  584. package/dist/src/gateway/ws-security.js +1 -2
  585. package/dist/src/gateway/xopc-cloud-capability-setup.js +8 -2
  586. package/dist/src/home-intelligence/host.js +2 -2
  587. package/dist/src/imports/importService.js +1 -1
  588. package/dist/src/infra/rate-limit/failure-limiter.js +90 -78
  589. package/dist/src/infra/rate-limit/index.js +3 -11
  590. package/dist/src/infra/rate-limit/keyed-store.js +47 -52
  591. package/dist/src/infra/rate-limit/rate-limiter.js +58 -55
  592. package/dist/src/infra/update-restart.js +1 -1
  593. package/dist/src/infra/update-service-refresh.js +1 -2
  594. package/dist/src/knowledge/chunks.js +1 -4
  595. package/dist/src/knowledge/connected-knowledge-pipeline.js +3 -6
  596. package/dist/src/knowledge/ingestion-service.js +1 -2
  597. package/dist/src/knowledge-memory/repository.js +1 -2
  598. package/dist/src/local-apps/service.js +1 -1
  599. package/dist/src/local-apps/store.js +1 -2
  600. package/dist/src/media/session-references.js +1 -2
  601. package/dist/src/memory-learning/forget-capture.js +1 -2
  602. package/dist/src/memory-learning/forgotten-history.js +3 -6
  603. package/dist/src/memory-learning/service.js +1 -2
  604. package/dist/src/memory-learning/source-learning.js +3 -3
  605. package/dist/src/memory-learning/task-receipts.js +1 -2
  606. package/dist/src/memory-learning/work-candidate.d.ts +29 -0
  607. package/dist/src/memory-learning/work-candidate.js +31 -0
  608. package/dist/src/memory-learning/work-capture.d.ts +2 -29
  609. package/dist/src/memory-learning/work-capture.js +2 -30
  610. package/dist/src/memory-maintenance/service.js +1 -2
  611. package/dist/src/notes/agent-context.js +1 -2
  612. package/dist/src/notes/attachment-ref.js +4 -8
  613. package/dist/src/notes/note-attachment-sync.js +1 -2
  614. package/dist/src/notes/note-index-meta.js +7 -14
  615. package/dist/src/notes/note-markdown.js +7 -13
  616. package/dist/src/notes/service.js +3 -6
  617. package/dist/src/notes/store.js +2 -4
  618. package/dist/src/notifications/clarification.js +1 -2
  619. package/dist/src/notifications/service.js +1 -2
  620. package/dist/src/personal-agent/proactivity/repository.js +1 -2
  621. package/dist/src/personal-agent/proactivity/service.js +1 -2
  622. package/dist/src/personal-agent/prompt-context.js +1 -2
  623. package/dist/src/personal-agent/reply-composer.js +4 -5
  624. package/dist/src/personal-agent/repository.js +1 -2
  625. package/dist/src/personal-agent/request-delivery.js +1 -2
  626. package/dist/src/personal-agent/result-extraction.js +71 -71
  627. package/dist/src/personal-agent/service.js +2 -3
  628. package/dist/src/phone/adb-command.d.ts +1 -0
  629. package/dist/src/phone/adb-command.js +12 -0
  630. package/dist/src/phone/adb-driver.d.ts +6 -2
  631. package/dist/src/phone/adb-driver.js +45 -21
  632. package/dist/src/phone/cloud-adb-connection.d.ts +34 -0
  633. package/dist/src/phone/cloud-adb-connection.js +324 -0
  634. package/dist/src/phone/cloud-adb-writable.d.ts +3 -0
  635. package/dist/src/phone/cloud-adb-writable.js +21 -0
  636. package/dist/src/phone/cloud-adb.d.ts +3 -32
  637. package/dist/src/phone/cloud-adb.js +3 -259
  638. package/dist/src/phone/cloud-key-permissions.d.ts +2 -0
  639. package/dist/src/phone/cloud-key-permissions.js +66 -0
  640. package/dist/src/phone/cloud-phones.js +2 -1
  641. package/dist/src/phone/cloud-scrcpy.d.ts +1 -1
  642. package/dist/src/phone/cloud-scrcpy.js +3 -2
  643. package/dist/src/phone/contracts.d.ts +197 -1
  644. package/dist/src/phone/contracts.js +55 -6
  645. package/dist/src/phone/foreground.d.ts +1 -0
  646. package/dist/src/phone/foreground.js +18 -0
  647. package/dist/src/phone/live-state.d.ts +2 -0
  648. package/dist/src/phone/live-state.js +5 -0
  649. package/dist/src/phone/model-adapter.d.ts +65 -4
  650. package/dist/src/phone/model-adapter.js +157 -48
  651. package/dist/src/phone/numeric-entry.d.ts +31 -0
  652. package/dist/src/phone/numeric-entry.js +126 -0
  653. package/dist/src/phone/planning.d.ts +27 -0
  654. package/dist/src/phone/planning.js +79 -0
  655. package/dist/src/phone/recovery.d.ts +37 -0
  656. package/dist/src/phone/recovery.js +81 -0
  657. package/dist/src/phone/reliability.d.ts +2 -2
  658. package/dist/src/phone/reliability.js +19 -6
  659. package/dist/src/phone/repository.d.ts +4 -1
  660. package/dist/src/phone/repository.js +12 -1
  661. package/dist/src/phone/runtime.d.ts +79 -3
  662. package/dist/src/phone/runtime.js +861 -93
  663. package/dist/src/phone/scrcpy.js +3 -2
  664. package/dist/src/phone/semantic-controls.d.ts +13 -0
  665. package/dist/src/phone/semantic-controls.js +76 -0
  666. package/dist/src/phone/setup/service.d.ts +101 -0
  667. package/dist/src/phone/setup/service.js +296 -0
  668. package/dist/src/phone/task-feedback.d.ts +4 -0
  669. package/dist/src/phone/task-feedback.js +47 -0
  670. package/dist/src/phone/ui-dump-binary.d.ts +1 -0
  671. package/dist/src/phone/ui-dump-binary.js +4 -0
  672. package/dist/src/phone/wireless.d.ts +80 -0
  673. package/dist/src/phone/wireless.js +244 -0
  674. package/dist/src/projects/capabilities/write.js +1 -2
  675. package/dist/src/projects/project-service.js +1 -2
  676. package/dist/src/projects/workspace.js +1 -2
  677. package/dist/src/providers/presentation.js +2 -2
  678. package/dist/src/providers/xopc-cloud-model-source.js +6 -2
  679. package/dist/src/realtime/runtime.d.ts +3 -0
  680. package/dist/src/realtime/runtime.js +16 -3
  681. package/dist/src/remote-access/exposure-guards.js +1 -2
  682. package/dist/src/runtime-tools/archive.js +1 -1
  683. package/dist/src/runtime-tools/catalog.d.ts +1 -1
  684. package/dist/src/runtime-tools/catalog.js +2 -2
  685. package/dist/src/session/config-store.js +1 -2
  686. package/dist/src/session/init-session-turn.js +1 -2
  687. package/dist/src/session/resolve-session.js +1 -2
  688. package/dist/src/session/store.js +2 -4
  689. package/dist/src/share/share-rate-limit.js +1 -2
  690. package/dist/src/share/share-url.js +1 -2
  691. package/dist/src/share/site-share-router.js +1 -2
  692. package/dist/src/storage/sqlite/activity-repository.js +2 -6
  693. package/dist/src/storage/sqlite/browser-tab-binding-repository.js +2 -6
  694. package/dist/src/storage/sqlite/clarification-wait-repository.js +9 -14
  695. package/dist/src/storage/sqlite/collaboration-rule-repository.js +3 -8
  696. package/dist/src/storage/sqlite/composer-input-history-repository.js +3 -8
  697. package/dist/src/storage/sqlite/config-repository.js +5 -9
  698. package/dist/src/storage/sqlite/connector-learning-repository.js +2 -6
  699. package/dist/src/storage/sqlite/connector-sync-policy-repository.js +2 -6
  700. package/dist/src/storage/sqlite/context-evidence-repository.js +3 -8
  701. package/dist/src/storage/sqlite/context-extraction-repository.js +3 -8
  702. package/dist/src/storage/sqlite/device-access-repository.js +16 -23
  703. package/dist/src/storage/sqlite/device-pairing-approval.js +2 -6
  704. package/dist/src/storage/sqlite/device-pairing-repository.js +5 -10
  705. package/dist/src/storage/sqlite/endpoint-principal-repository.js +2 -6
  706. package/dist/src/storage/sqlite/endpoint-session-binding-repository.js +2 -6
  707. package/dist/src/storage/sqlite/endpoint-tool-invocation-repository.js +2 -6
  708. package/dist/src/storage/sqlite/gateway-identity-repository.js +2 -6
  709. package/dist/src/storage/sqlite/home-attention-repository.js +2 -6
  710. package/dist/src/storage/sqlite/index.js +40 -72
  711. package/dist/src/storage/sqlite/interaction-state-repository.js +4 -10
  712. package/dist/src/storage/sqlite/knowledge-repository.js +3 -8
  713. package/dist/src/storage/sqlite/note-agent-context-repository.js +2 -6
  714. package/dist/src/storage/sqlite/notes-repository.js +4 -9
  715. package/dist/src/storage/sqlite/research-checkpoint-repository.js +3 -8
  716. package/dist/src/storage/sqlite/schema.d.ts +2 -2
  717. package/dist/src/storage/sqlite/schema.js +7 -7
  718. package/dist/src/storage/sqlite/schema.sql +10 -0
  719. package/dist/src/storage/sqlite/session-creation-repository.js +2 -4
  720. package/dist/src/storage/sqlite/session-task-plan-repository.js +9 -14
  721. package/dist/src/storage/sqlite/session-turn-replace-repository.js +5 -9
  722. package/dist/src/storage/sqlite/sidebar-layout-repository.js +9 -14
  723. package/dist/src/storage/sqlite/transcript-repository.js +6 -10
  724. package/dist/src/storage/sqlite/upgrades/260_browser_setup.sql +9 -0
  725. package/dist/src/storage/sqlite/user-people-repository.js +3 -8
  726. package/dist/src/storage/sqlite/user-trust-repository.js +4 -9
  727. package/dist/src/tasks/capabilities/read.js +2 -2
  728. package/dist/src/tasks/capabilities/write.js +1 -1
  729. package/dist/src/tasks/execution-context.js +1 -2
  730. package/dist/src/tasks/home-query-service.js +1 -2
  731. package/dist/src/tasks/task-allocation-repository.js +1 -2
  732. package/dist/src/tasks/task-context-assembler.js +1 -2
  733. package/dist/src/tasks/task-handoff.js +2 -4
  734. package/dist/src/tasks/task-instruction-sequence.d.ts +1 -0
  735. package/dist/src/tasks/task-instruction-sequence.js +7 -0
  736. package/dist/src/tasks/task-language.js +1 -2
  737. package/dist/src/tasks/task-research-result.d.ts +1 -2
  738. package/dist/src/tasks/task-research-result.js +1 -3
  739. package/dist/src/tasks/task-result-delivery-repository.js +1 -1
  740. package/dist/src/tasks/task-result-delivery-service.js +3 -3
  741. package/dist/src/tasks/task-run-coordinator.js +3 -3
  742. package/dist/src/tasks/task-run-dispatcher.js +1 -2
  743. package/dist/src/tasks/task-value-metrics-service.js +1 -2
  744. package/dist/src/tui/backends/embedded-backend.js +2 -3
  745. package/dist/src/tui/tui-commands.js +1 -2
  746. package/dist/src/tunnel/registration-proof.js +1 -2
  747. package/dist/src/tunnel/tunnel-rate-limit.js +1 -2
  748. package/dist/src/user-context/access-policy.js +1 -2
  749. package/dist/src/user-context/domain.js +13 -18
  750. package/dist/src/user-context/extraction/registry.js +1 -2
  751. package/dist/src/user-context/interaction-state.js +1 -4
  752. package/dist/src/user-context/relationship-continuity.js +1 -2
  753. package/dist/src/user-context/sources/consent-repository.js +1 -2
  754. package/dist/src/user-context/sources/index.js +1 -1
  755. package/dist/src/user-context/trust-policy.js +8 -13
  756. package/dist/src/user-model/action-rule-suggestions.js +1 -2
  757. package/dist/src/user-model/bootstrap.js +1 -2
  758. package/dist/src/user-model/capture/executor.js +2 -4
  759. package/dist/src/user-model/capture/semantic.d.ts +1 -1
  760. package/dist/src/user-model/capture/semantic.js +1 -1
  761. package/dist/src/user-model/domain.js +30 -35
  762. package/dist/src/user-model/goals.js +1 -2
  763. package/dist/src/user-model/index.js +1 -4
  764. package/dist/src/user-model/observation-repository.js +1 -2
  765. package/dist/src/user-model/repository.js +1 -2
  766. package/dist/src/user-model/usage-policy.js +1 -2
  767. package/dist/src/voice/realtime/memory-context.js +1 -2
  768. package/dist/src/voice/realtime/persona-context.js +1 -1
  769. package/dist/src/work-discovery/service.js +4 -6
  770. package/package.json +8 -8
  771. package/skills/tools/configure-xopc/SKILL.md +54 -0
  772. package/skills/tools/configure-xopc/references/browser/acceptance.md +32 -0
  773. package/skills/tools/configure-xopc/references/browser/chrome-extension.md +23 -0
  774. package/skills/tools/configure-xopc/references/browser/overview.md +19 -0
  775. package/skills/tools/configure-xopc/references/browser/permissions.md +23 -0
  776. package/skills/tools/configure-xopc/references/browser/troubleshooting.md +24 -0
  777. package/skills/tools/configure-xopc/references/phone/acceptance.md +27 -0
  778. package/skills/tools/configure-xopc/references/phone/aliyun.md +29 -0
  779. package/skills/tools/configure-xopc/references/phone/dependencies.md +18 -0
  780. package/skills/tools/configure-xopc/references/phone/local.md +19 -0
  781. package/skills/tools/configure-xopc/references/phone/models.md +21 -0
  782. package/skills/tools/configure-xopc/references/phone/overview.md +25 -0
  783. package/skills/tools/configure-xopc/references/phone/troubleshooting.md +27 -0
  784. package/skills/tools/configure-xopc/references/scene-index.md +12 -0
  785. package/dist/gateway/static/root/assets/agent-avatar-dicebear-CJFwitU2.js +0 -1
  786. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-DclyJr1N.js +0 -1
  787. package/dist/gateway/static/root/assets/agents-jhErNtzi.js +0 -77
  788. package/dist/gateway/static/root/assets/app-management-settings-panel-DgwqNi5i.js +0 -1
  789. package/dist/gateway/static/root/assets/appearance-settings-C0wJfFyz.js +0 -1
  790. package/dist/gateway/static/root/assets/apps-page-C0LcnI4h.js +0 -1
  791. package/dist/gateway/static/root/assets/automation-display-BFN7zWBg.js +0 -2
  792. package/dist/gateway/static/root/assets/automations-workspace-CBxiV34x.js +0 -8
  793. package/dist/gateway/static/root/assets/browser-automations-page-vJIrTxdi.js +0 -3
  794. package/dist/gateway/static/root/assets/browser-settings-page-in5Roh_E.js +0 -3
  795. package/dist/gateway/static/root/assets/capabilities-BlxF36t-.js +0 -1
  796. package/dist/gateway/static/root/assets/capabilities-page-CiGx8wpQ.js +0 -2
  797. package/dist/gateway/static/root/assets/capabilities-settings-panel-a8kqjzQu.js +0 -8
  798. package/dist/gateway/static/root/assets/capability-header-actions-D4Yq35fD.js +0 -1
  799. package/dist/gateway/static/root/assets/channels-C_CxcjKT.js +0 -1
  800. package/dist/gateway/static/root/assets/chat-terminal-dock-zdMySdMm.js +0 -36
  801. package/dist/gateway/static/root/assets/chunk-KS7C4IRE-BvcCCgTW.js +0 -4
  802. package/dist/gateway/static/root/assets/cloud-credits-BMYMiiNn.js +0 -1
  803. package/dist/gateway/static/root/assets/computer-settings-page-C5Z6Jr0p.js +0 -1
  804. package/dist/gateway/static/root/assets/connector-service-page-Cxus0qrZ.js +0 -1
  805. package/dist/gateway/static/root/assets/connectors-page-DCBO2CxK.js +0 -1
  806. package/dist/gateway/static/root/assets/constants-DeXt1mV-.js +0 -1
  807. package/dist/gateway/static/root/assets/date-picker-DuyyD6jz.js +0 -1
  808. package/dist/gateway/static/root/assets/dependency-picker-BZN72rrk.js +0 -1
  809. package/dist/gateway/static/root/assets/desktop-pet-BtvTIDCi.js +0 -1
  810. package/dist/gateway/static/root/assets/desktop-pet-settings-BcyP7Z6v.js +0 -1
  811. package/dist/gateway/static/root/assets/device-pairing-wizard-Ctbgr50F.js +0 -1
  812. package/dist/gateway/static/root/assets/directory-picker-path-field-DOusKz-O.js +0 -1
  813. package/dist/gateway/static/root/assets/dist-C3DSFZCi.js +0 -1
  814. package/dist/gateway/static/root/assets/dist-CI_fqRk-.js +0 -1
  815. package/dist/gateway/static/root/assets/docx-preview-CajIk2FR.js +0 -20
  816. package/dist/gateway/static/root/assets/echarts-runtime-tcHc9TOS.js +0 -18
  817. package/dist/gateway/static/root/assets/electron-env-Dit0bHgy.js +0 -1
  818. package/dist/gateway/static/root/assets/extension-debug-page-Bt4FwsFu.js +0 -1
  819. package/dist/gateway/static/root/assets/extension-page-0vsxX3FB.js +0 -1
  820. package/dist/gateway/static/root/assets/extension-settings-page-5Pt5_ELc.js +0 -1
  821. package/dist/gateway/static/root/assets/files-Bw4SBGdM.js +0 -1
  822. package/dist/gateway/static/root/assets/floating-ui.dom-B7uQOZZW.js +0 -1
  823. package/dist/gateway/static/root/assets/gateway-realtime-DkWCHVzI.js +0 -1
  824. package/dist/gateway/static/root/assets/gateway-realtime-store-Bx9KCID-.js +0 -1
  825. package/dist/gateway/static/root/assets/gateway-settings-BsVOcmV5.js +0 -1
  826. package/dist/gateway/static/root/assets/highlight-code-C8eS9949.js +0 -1
  827. package/dist/gateway/static/root/assets/highlighted-body-KQOG7T2V-Cbk7eMlg.js +0 -1
  828. package/dist/gateway/static/root/assets/home-page-BZDZnmyc.js +0 -2
  829. package/dist/gateway/static/root/assets/image-generation-api-CAS8QVla.js +0 -1
  830. package/dist/gateway/static/root/assets/imports-page-BCLBYzV1.js +0 -1
  831. package/dist/gateway/static/root/assets/index-Bys6njTY.js +0 -710
  832. package/dist/gateway/static/root/assets/index-Vsf0bj5e.css +0 -1
  833. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-CM_kt5XN.js +0 -1
  834. package/dist/gateway/static/root/assets/languages-byq_L2Ae.js +0 -2
  835. package/dist/gateway/static/root/assets/local-app-workbench-page-Dk87jtcc.js +0 -1
  836. package/dist/gateway/static/root/assets/local-apps-page-BTSOChhk.js +0 -1
  837. package/dist/gateway/static/root/assets/local-apps-yys1VChX.js +0 -1
  838. package/dist/gateway/static/root/assets/local-session-drafts-iGX_6O0O.js +0 -1
  839. package/dist/gateway/static/root/assets/logs-page-D3gVdm8S.js +0 -2
  840. package/dist/gateway/static/root/assets/management-settings-BQNYFE4J.js +0 -1
  841. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-ChweJKTv.js +0 -1
  842. package/dist/gateway/static/root/assets/note-detail-panel-CYKwUCte.js +0 -5
  843. package/dist/gateway/static/root/assets/note-image-lightbox-BTSZb9ZT.js +0 -1
  844. package/dist/gateway/static/root/assets/notes-page-CJ5nhWfL.js +0 -8
  845. package/dist/gateway/static/root/assets/number-input-DDeqHK-G.js +0 -1
  846. package/dist/gateway/static/root/assets/page-context-capture-button-DVn_dU83.js +0 -1
  847. package/dist/gateway/static/root/assets/pdf-runtime-DU_sMPjG.js +0 -2
  848. package/dist/gateway/static/root/assets/personal-page-DcW14lqn.js +0 -1
  849. package/dist/gateway/static/root/assets/personal-proactivity-BJcZ3Yhi.js +0 -1
  850. package/dist/gateway/static/root/assets/personal-settings-panel-C16Iqe7X.js +0 -1
  851. package/dist/gateway/static/root/assets/phone-dependencies-card-D3l9uPFM.js +0 -1
  852. package/dist/gateway/static/root/assets/phone-model-picker-DOv38vBn.js +0 -1
  853. package/dist/gateway/static/root/assets/phone-settings-page-DUHp1q_9.js +0 -1
  854. package/dist/gateway/static/root/assets/plugin-details-dialog-BpfgDlVa.js +0 -1
  855. package/dist/gateway/static/root/assets/popover-select-DGKUpVsz.js +0 -1
  856. package/dist/gateway/static/root/assets/preload-helper-zJ_50EbN.js +0 -1
  857. package/dist/gateway/static/root/assets/preview-open-alternatives-RlHk76TI.js +0 -1
  858. package/dist/gateway/static/root/assets/product-delivery-BqNm-8S5.js +0 -1
  859. package/dist/gateway/static/root/assets/product-open-page-Dh-HqLrE.js +0 -1
  860. package/dist/gateway/static/root/assets/product-preview-content-c3K-4DWc.js +0 -1
  861. package/dist/gateway/static/root/assets/project-detail-page-GD8TxKad.js +0 -7
  862. package/dist/gateway/static/root/assets/projects-page-B8HAt9sD.js +0 -1
  863. package/dist/gateway/static/root/assets/remote-access-hub-D3el7lHK.js +0 -1
  864. package/dist/gateway/static/root/assets/runtime-tools-settings-panel-Dbskk6RG.js +0 -1
  865. package/dist/gateway/static/root/assets/schema-form-CXO1B1k4.js +0 -1
  866. package/dist/gateway/static/root/assets/schemas-CObaziC7.js +0 -64
  867. package/dist/gateway/static/root/assets/session-manager-CA1NkTR_.js +0 -16
  868. package/dist/gateway/static/root/assets/sessions-page-07liaSHH.js +0 -1
  869. package/dist/gateway/static/root/assets/settings-advanced-gate-BGjU8rfN.js +0 -1
  870. package/dist/gateway/static/root/assets/settings-form-section-BQxKmbbJ.js +0 -1
  871. package/dist/gateway/static/root/assets/settings-page-DvVMpKiA.js +0 -1
  872. package/dist/gateway/static/root/assets/settings-page-header-CYpuTXUW.js +0 -1
  873. package/dist/gateway/static/root/assets/settings-page-layout-B20AfmFG.js +0 -1
  874. package/dist/gateway/static/root/assets/setup-status-panel-DKo_VTx-.js +0 -1
  875. package/dist/gateway/static/root/assets/share-preview-page-XgZk8Oa1.js +0 -2
  876. package/dist/gateway/static/root/assets/shares-settings-BODFqK8k.js +0 -1
  877. package/dist/gateway/static/root/assets/skill-api-CV-WT2hj.js +0 -1
  878. package/dist/gateway/static/root/assets/skill-reload-api-Ce6OUk2C.js +0 -1
  879. package/dist/gateway/static/root/assets/skills-page-B7ehOIML.js +0 -2
  880. package/dist/gateway/static/root/assets/specialists-4bkS5rZ4.js +0 -1
  881. package/dist/gateway/static/root/assets/system-settings-panel-CxJkZRT4.js +0 -1
  882. package/dist/gateway/static/root/assets/task-detail-page-CxRR0QuW.js +0 -2
  883. package/dist/gateway/static/root/assets/task-result-evidence-D-gGKNX9.js +0 -1
  884. package/dist/gateway/static/root/assets/tasks-TVRjEggr.js +0 -1
  885. package/dist/gateway/static/root/assets/tracing-settings-page-CQw3G-FB.js +0 -1
  886. package/dist/gateway/static/root/assets/tunnel-api-B2HnCi0U.js +0 -1
  887. package/dist/gateway/static/root/assets/usage-page-uUEkO38r.js +0 -1
  888. package/dist/gateway/static/root/assets/use-autosave-Dc0nwUpX.js +0 -1
  889. package/dist/gateway/static/root/assets/user-model-page-ICUutbKL.js +0 -2
  890. package/dist/gateway/static/root/assets/voice-api-key-field-BSWXZkGa.js +0 -1
  891. package/dist/gateway/static/root/assets/work-discovery-overlay-H3cdwq3l.js +0 -1
  892. 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 { canDispatchPhoneAction, observationSignature, phoneCompletionSatisfied } from "./reliability.js";
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
- return this.driverFactory(resolveAdbPath(config.phone.adbPath)).discover(signal);
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", "Close an existing phone session before opening another", 409);
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
- if (previous && !terminal.has(previous.report.status)) throw new PhoneError("PHONE_ALREADY_OPEN", "Close the current phone session before opening another");
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
- const device = this.repository.get(deviceId);
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
- const found = (await driver.discover(signal)).find((item) => item.serial === device.serial);
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 = await this.modelFactory(modelRef, context.config, context.agentId);
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)) throw new PhoneError("PHONE_OPEN_REQUIRED", "Open a phone session first");
246
- if ((session.human || session.report.controlOwner === "none" && !(input.op === "resume" && session.controller.signal.aborted)) && input.op !== "run" && input.op !== "step") throw new PhoneError("PHONE_PAUSED", "The user controls this phone. Wait for explicit handback in the phone panel", 409);
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 (session.report.status === "paused" || session.report.status === "needs_user") throw new PhoneError("PHONE_PAUSED", "Complete manual interaction and resume the phone session");
259
- session.budget = new PhoneOperationBudget(context.config.phone.maxOperationDurationMs);
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 = this.perform(session, input, context, combined);
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
- return await operation;
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.status = "ready";
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
- if (session.report.modelRequests >= context.config.phone.maxModelRequests) throw new PhoneError("PHONE_MODEL_LIMIT", "Phone model request limit reached");
368
- session.report.modelRequests++;
369
- session.report.currentAction = void 0;
370
- this.publish(session);
371
- session.prediction = new AbortController();
372
- let decision;
373
- try {
374
- decision = await session.adapter.predict({
375
- goal: input.goal,
376
- observation,
377
- completion,
378
- allowedApps: session.device.allowedApps,
379
- appAccess: phoneAppAccess(session.device),
380
- applications: session.applications.filter((app) => phoneAllowsApp(session.device, app.packageName)),
381
- history: session.report.steps.map((step) => step.action),
382
- trajectory: session.trajectory,
383
- progressSummary: JSON.stringify({
384
- dispatched: session.trajectoryCount,
385
- earlier: [...session.trajectorySummary, ...session.trajectory.slice(0, -8).map((entry) => JSON.stringify({
386
- action: entry.action,
387
- effect: entry.effect,
388
- afterApp: entry.afterApp
389
- }).slice(0, 250))].slice(-12)
390
- }).slice(-1500),
391
- recoveryHint,
392
- protocolFeedback,
393
- scenario: input.scenario
394
- }, AbortSignal.any([signal, session.prediction.signal]));
395
- } catch (error) {
396
- if (!signal.aborted && epoch !== session.report.controlEpoch) {
397
- await this.waitForAgent(session, signal);
398
- observation.frame.fill(0);
399
- observation = await this.observe(session, signal);
400
- continue;
401
- }
402
- if (!signal.aborted && error instanceof PhoneError && ["PHONE_MODEL_PROTOCOL", "PHONE_MODEL_TRUNCATED"].includes(error.code) && repairs < 1 && session.report.modelRequests < context.config.phone.maxModelRequests) {
403
- repairs++;
404
- session.report.diagnostics.protocolRepairs++;
405
- protocolFeedback = "Your previous output was invalid or truncated. Return exactly one complete action in the specified format with no extra prose.";
406
- observation.frame.fill(0);
407
- observation = await this.observe(session, signal);
408
- continue;
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.config.phone.maxModelRequests) {
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(decision.action)}`;
1123
+ const attemptKey = `${observationSignature(fresh)}:${JSON.stringify(action)}`;
462
1124
  const repetitions = attempts.get(attemptKey) ?? 0;
463
- if (repetitions >= (decision.action.type === "wait" ? 3 : 2)) {
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, decision.action, fresh, context, signal, epoch)) actions++;
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, session.human ? {
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 !== "pause") this.repository.release(session.device.serial, session.lease);
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.stop(session.report.owner, "cancel");
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: structuredClone(session.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(owner, session);
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(owner, session) {
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.stop(owner, "cancel");
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
- await Promise.all(this.reports().filter((report) => report.deviceId === id).map((report) => this.stop(report.owner, "cancel")));
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
  }