@xopcai/xopc 0.0.415 → 0.0.416

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 (251) hide show
  1. package/dist/browser-ext/_locales/en/messages.json +4 -1
  2. package/dist/browser-ext/_locales/zh_CN/messages.json +4 -1
  3. package/dist/browser-ext/dist/assets/{page-context-MuzjMBlJ.js → page-context-CVvmTWZb.js} +33 -9
  4. package/dist/browser-ext/dist/background.js +39 -10
  5. package/dist/browser-ext/dist/sidepanel.html +1 -1
  6. package/dist/browser-ext/dist/sidepanel.js +22 -3
  7. package/dist/browser-ext/manifest.json +1 -1
  8. package/dist/extensions/telegram/xopc.extension.json +1 -1
  9. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CJFwitU2.js → agent-avatar-dicebear-CufU7cqe.js} +1 -1
  10. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-DHDAcss8.js +1 -0
  11. package/dist/gateway/static/root/assets/agents-BV3dAoa0.js +77 -0
  12. package/dist/gateway/static/root/assets/{app-management-settings-panel-DgwqNi5i.js → app-management-settings-panel-D4-n1uBg.js} +1 -1
  13. package/dist/gateway/static/root/assets/{appearance-settings-C0wJfFyz.js → appearance-settings-Cgn4eNsX.js} +1 -1
  14. package/dist/gateway/static/root/assets/apps-page-BOYzD7Zz.js +1 -0
  15. package/dist/gateway/static/root/assets/{archive-plugin-Ch7wolHE.js → archive-plugin-B4btCsiV.js} +1 -1
  16. package/dist/gateway/static/root/assets/{automations-page-DK7AU79v.js → automations-page-yb1EL_3N.js} +1 -1
  17. package/dist/gateway/static/root/assets/automations-workspace-J7LJ4RuV.js +8 -0
  18. package/dist/gateway/static/root/assets/{binary-plugins-B4HcHYsC.js → binary-plugins-DQT9e258.js} +1 -1
  19. package/dist/gateway/static/root/assets/{block-editor-BQAWEZF-.js → block-editor-B50rU9tL.js} +4 -4
  20. package/dist/gateway/static/root/assets/browser-automations-page-BiQz6lJA.js +3 -0
  21. package/dist/gateway/static/root/assets/browser-settings-page-W9kuxBbE.js +3 -0
  22. package/dist/gateway/static/root/assets/capabilities-page-iXe87MdG.js +2 -0
  23. package/dist/gateway/static/root/assets/capabilities-settings-panel-CRLSXe7Z.js +8 -0
  24. package/dist/gateway/static/root/assets/{capability-header-actions-D4Yq35fD.js → capability-header-actions-BMnbzHms.js} +1 -1
  25. package/dist/gateway/static/root/assets/channels-CrRJkOKX.js +1 -0
  26. package/dist/gateway/static/root/assets/{chat-terminal-dock-zdMySdMm.js → chat-terminal-dock-Bd3af4gL.js} +2 -2
  27. package/dist/gateway/static/root/assets/{computer-settings-page-C5Z6Jr0p.js → computer-settings-page-DXfqy7xh.js} +1 -1
  28. package/dist/gateway/static/root/assets/{connector-service-page-Cxus0qrZ.js → connector-service-page-B-cw0CPU.js} +1 -1
  29. package/dist/gateway/static/root/assets/connectors-page-DbFxc0Fd.js +1 -0
  30. package/dist/gateway/static/root/assets/{date-picker-DuyyD6jz.js → date-picker-CqzXevH6.js} +1 -1
  31. package/dist/gateway/static/root/assets/{dependency-picker-BZN72rrk.js → dependency-picker-pgT4Gyaf.js} +1 -1
  32. package/dist/gateway/static/root/assets/{desktop-pet-settings-BcyP7Z6v.js → desktop-pet-settings-Dy_-i2L8.js} +1 -1
  33. package/dist/gateway/static/root/assets/{desktop-pet-BtvTIDCi.js → desktop-pet-zICeqw9c.js} +1 -1
  34. package/dist/gateway/static/root/assets/device-pairing-wizard-ByGbxqkg.js +1 -0
  35. package/dist/gateway/static/root/assets/{directory-picker-path-field-DOusKz-O.js → directory-picker-path-field-C-aQ7qoM.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-debug-page-Bt4FwsFu.js → extension-debug-page-2NwpYkS5.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-page-0vsxX3FB.js → extension-page-y9J0z7_Q.js} +1 -1
  38. package/dist/gateway/static/root/assets/{extension-settings-page-5Pt5_ELc.js → extension-settings-page-BtowusUh.js} +1 -1
  39. package/dist/gateway/static/root/assets/gateway-realtime-C52ghnBK.js +1 -0
  40. package/dist/gateway/static/root/assets/gateway-settings-BYSKzUMR.js +1 -0
  41. package/dist/gateway/static/root/assets/highlight-code-Cz6eeDH5.js +1 -0
  42. package/dist/gateway/static/root/assets/{highlighted-body-KQOG7T2V-Cbk7eMlg.js → highlighted-body-KQOG7T2V-BiAa8HKC.js} +1 -1
  43. package/dist/gateway/static/root/assets/home-page-Cd1BjYHj.js +2 -0
  44. package/dist/gateway/static/root/assets/{image-generation-api-CAS8QVla.js → image-generation-api-gBFro48x.js} +1 -1
  45. package/dist/gateway/static/root/assets/{imports-page-BCLBYzV1.js → imports-page-BZQpXgjj.js} +1 -1
  46. package/dist/gateway/static/root/assets/index-Cy16gQST.css +1 -0
  47. package/dist/gateway/static/root/assets/index-DRyGCING.js +710 -0
  48. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CM_kt5XN.js → keyboard-shortcuts-settings-CYunR34k.js} +1 -1
  49. package/dist/gateway/static/root/assets/local-app-workbench-page-B_Ac1lly.js +1 -0
  50. package/dist/gateway/static/root/assets/{local-apps-page-BTSOChhk.js → local-apps-page-w-J5bY02.js} +1 -1
  51. package/dist/gateway/static/root/assets/logs-page-Dnjvvx2i.js +2 -0
  52. package/dist/gateway/static/root/assets/management-settings-w1EDwgLW.js +1 -0
  53. package/dist/gateway/static/root/assets/{media-plugins-DYQDjCVQ.js → media-plugins-CIx1koXw.js} +1 -1
  54. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-DISkHmEC.js +1 -0
  55. package/dist/gateway/static/root/assets/note-detail-panel-CNkxMTFU.js +5 -0
  56. package/dist/gateway/static/root/assets/note-image-lightbox-D5GH2wuC.js +1 -0
  57. package/dist/gateway/static/root/assets/notes-page-DZgKqFBG.js +8 -0
  58. package/dist/gateway/static/root/assets/{page-context-capture-button-DVn_dU83.js → page-context-capture-button-DusR2Itk.js} +1 -1
  59. package/dist/gateway/static/root/assets/personal-page-CR5JFkQ9.js +1 -0
  60. package/dist/gateway/static/root/assets/{personal-settings-panel-C16Iqe7X.js → personal-settings-panel-B7undvlr.js} +1 -1
  61. package/dist/gateway/static/root/assets/phone-model-picker-fWDltRUJ.js +1 -0
  62. package/dist/gateway/static/root/assets/phone-settings-page-CsOirAiy.js +1 -0
  63. package/dist/gateway/static/root/assets/plugin-details-dialog-BOBVIB3j.js +1 -0
  64. package/dist/gateway/static/root/assets/{preview-open-alternatives-RlHk76TI.js → preview-open-alternatives-CMxjsKSw.js} +1 -1
  65. package/dist/gateway/static/root/assets/{product-open-page-Dh-HqLrE.js → product-open-page-CrlyJx5M.js} +1 -1
  66. package/dist/gateway/static/root/assets/{product-preview-content-c3K-4DWc.js → product-preview-content-B-Jhzi7W.js} +1 -1
  67. package/dist/gateway/static/root/assets/project-detail-page-DoYUbtcI.js +7 -0
  68. package/dist/gateway/static/root/assets/{projects-page-B8HAt9sD.js → projects-page-xGQd9oAZ.js} +1 -1
  69. package/dist/gateway/static/root/assets/refresh-cw-BRlGaq2w.js +1 -0
  70. package/dist/gateway/static/root/assets/remote-access-hub-Gs0Xkws9.js +1 -0
  71. package/dist/gateway/static/root/assets/runtime-tools-settings-panel-Bwg7U7TR.js +1 -0
  72. package/dist/gateway/static/root/assets/{schema-form-CXO1B1k4.js → schema-form-ByzTNR_C.js} +1 -1
  73. package/dist/gateway/static/root/assets/{session-manager-CA1NkTR_.js → session-manager-B_h0jlLb.js} +1 -1
  74. package/dist/gateway/static/root/assets/sessions-page-XzK1ftbR.js +1 -0
  75. package/dist/gateway/static/root/assets/settings-advanced-gate-D_8Mvnog.js +1 -0
  76. package/dist/gateway/static/root/assets/{settings-form-section-BQxKmbbJ.js → settings-form-section-Brgd8IOV.js} +1 -1
  77. package/dist/gateway/static/root/assets/{settings-page-DvVMpKiA.js → settings-page-B6Mv02eg.js} +1 -1
  78. package/dist/gateway/static/root/assets/settings-page-header-BWyxJKOG.js +1 -0
  79. package/dist/gateway/static/root/assets/{settings-page-layout-B20AfmFG.js → settings-page-layout-DLHcS-0T.js} +1 -1
  80. package/dist/gateway/static/root/assets/setup-status-panel-DSCj5yis.js +1 -0
  81. package/dist/gateway/static/root/assets/{share-preview-page-XgZk8Oa1.js → share-preview-page-DF8Of0aZ.js} +1 -1
  82. package/dist/gateway/static/root/assets/shares-settings-DXNPe4Tl.js +1 -0
  83. package/dist/gateway/static/root/assets/{skill-api-CV-WT2hj.js → skill-api-CKCDCHLq.js} +1 -1
  84. package/dist/gateway/static/root/assets/skill-reload-api-BH0WF6Br.js +1 -0
  85. package/dist/gateway/static/root/assets/skills-page-DFWMVRW4.js +2 -0
  86. package/dist/gateway/static/root/assets/system-settings-panel-DB-ttubV.js +1 -0
  87. package/dist/gateway/static/root/assets/task-detail-page-BJY7c8wb.js +2 -0
  88. package/dist/gateway/static/root/assets/{task-result-evidence-D-gGKNX9.js → task-result-evidence-B-vt1BgK.js} +1 -1
  89. package/dist/gateway/static/root/assets/{tracing-settings-page-CQw3G-FB.js → tracing-settings-page-Dt51Z_ws.js} +1 -1
  90. package/dist/gateway/static/root/assets/{tunnel-api-B2HnCi0U.js → tunnel-api-Dok3t7Qe.js} +1 -1
  91. package/dist/gateway/static/root/assets/usage-page-lJym5G7F.js +1 -0
  92. package/dist/gateway/static/root/assets/{use-autosave-Dc0nwUpX.js → use-autosave-D4EMIB-V.js} +1 -1
  93. package/dist/gateway/static/root/assets/user-model-page-BXdNkITp.js +2 -0
  94. package/dist/gateway/static/root/assets/{voice-api-key-field-BSWXZkGa.js → voice-api-key-field-CO3KuanA.js} +1 -1
  95. package/dist/gateway/static/root/assets/{work-discovery-overlay-H3cdwq3l.js → work-discovery-overlay-BJRtgQM3.js} +1 -1
  96. package/dist/gateway/static/root/assets/wrench-DFb4r8bH.js +1 -0
  97. package/dist/gateway/static/root/assets/xopc-cloud-account-card-CS-_GxHV.js +1 -0
  98. package/dist/gateway/static/root/browser-setup-test.html +5 -0
  99. package/dist/gateway/static/root/browser-setup-test.js +7 -0
  100. package/dist/gateway/static/root/index.html +7 -4
  101. package/dist/package.js +1 -1
  102. package/dist/packages/gateway-contract/src/browser-setup.js +6 -0
  103. package/dist/packages/gateway-contract/src/index.js +4 -0
  104. package/dist/packages/gateway-contract/src/phone-setup.js +6 -0
  105. package/dist/packages/realtime-client/src/index.js +1 -0
  106. package/dist/packages/realtime-protocol/src/index.js +1 -0
  107. package/dist/src/agent/agent-manager.d.ts +4 -0
  108. package/dist/src/agent/agent-manager.js +12 -1
  109. package/dist/src/agent/embedded/tool-search-extension.js +14 -1
  110. package/dist/src/agent/service.d.ts +1 -0
  111. package/dist/src/agent/service.js +5 -0
  112. package/dist/src/agent/service.types.d.ts +2 -0
  113. package/dist/src/agent/tool-manuals/phone.d.ts +1 -1
  114. package/dist/src/agent/tool-manuals/phone.js +1 -1
  115. package/dist/src/agent/tool-manuals/xopc-configuration.d.ts +2 -0
  116. package/dist/src/agent/tool-manuals/xopc-configuration.js +25 -0
  117. package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +2 -0
  118. package/dist/src/agent/tools/browser/tool/browser-use-tool.js +6 -2
  119. package/dist/src/agent/tools/factory.d.ts +3 -0
  120. package/dist/src/agent/tools/factory.js +11 -1
  121. package/dist/src/agent/tools/phone-use-tool.d.ts +1 -0
  122. package/dist/src/agent/tools/phone-use-tool.js +9 -1
  123. package/dist/src/agent/tools/tool-manual-tool.d.ts +1 -1
  124. package/dist/src/agent/tools/tool-manual-tool.js +3 -1
  125. package/dist/src/agent/tools/toolExposure.js +3 -0
  126. package/dist/src/agent/tools/xopc-use-tool.d.ts +4 -2
  127. package/dist/src/agent/tools/xopc-use-tool.js +40 -2
  128. package/dist/src/browser/drivers/browser-driver.d.ts +2 -2
  129. package/dist/src/browser/drivers/extension-driver.d.ts +2 -2
  130. package/dist/src/browser/drivers/extension-driver.js +6 -3
  131. package/dist/src/browser/providers/browser-ext-install.js +2 -1
  132. package/dist/src/browser/runtime/browser-runtime.d.ts +4 -1
  133. package/dist/src/browser/runtime/browser-runtime.js +29 -17
  134. package/dist/src/browser/setup/repository.d.ts +5 -0
  135. package/dist/src/browser/setup/repository.js +42 -0
  136. package/dist/src/browser/setup/service.d.ts +152 -0
  137. package/dist/src/browser/setup/service.js +404 -0
  138. package/dist/src/browser/setup/types.d.ts +38 -0
  139. package/dist/src/browser/setup/types.js +1 -0
  140. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  141. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  142. package/dist/src/config/schema.d.ts +2 -0
  143. package/dist/src/connectors/connected-source-understanding.js +1 -1
  144. package/dist/src/connectors/learning-coordinator.js +1 -1
  145. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  146. package/dist/src/gateway/hono/routes/browser-setup.d.ts +3 -0
  147. package/dist/src/gateway/hono/routes/browser-setup.js +114 -0
  148. package/dist/src/gateway/hono/routes/browser.d.ts +2 -1
  149. package/dist/src/gateway/hono/routes/browser.js +1 -1
  150. package/dist/src/gateway/hono/routes/connectors.js +7 -7
  151. package/dist/src/gateway/hono/routes/home.js +1 -1
  152. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  153. package/dist/src/gateway/hono/routes/phone-dependencies.js +1 -1
  154. package/dist/src/gateway/hono/routes/phone-setup.d.ts +7 -0
  155. package/dist/src/gateway/hono/routes/phone-setup.js +162 -0
  156. package/dist/src/gateway/hono/routes/phone.js +3 -7
  157. package/dist/src/gateway/hono/routes/public-gateway.js +3 -1
  158. package/dist/src/gateway/provider-model-setup.js +1 -1
  159. package/dist/src/gateway/service/config-coordinator.d.ts +2 -0
  160. package/dist/src/gateway/service.d.ts +5 -0
  161. package/dist/src/gateway/service.js +57 -12
  162. package/dist/src/gateway/xopc-cloud-capability-setup.js +7 -1
  163. package/dist/src/home-intelligence/host.js +2 -2
  164. package/dist/src/infra/update-restart.js +1 -1
  165. package/dist/src/phone/adb-driver.d.ts +2 -0
  166. package/dist/src/phone/adb-driver.js +35 -17
  167. package/dist/src/phone/contracts.d.ts +40 -0
  168. package/dist/src/phone/contracts.js +17 -4
  169. package/dist/src/phone/model-adapter.d.ts +59 -2
  170. package/dist/src/phone/model-adapter.js +107 -13
  171. package/dist/src/phone/numeric-entry.d.ts +31 -0
  172. package/dist/src/phone/numeric-entry.js +126 -0
  173. package/dist/src/phone/planning.d.ts +27 -0
  174. package/dist/src/phone/planning.js +79 -0
  175. package/dist/src/phone/recovery.d.ts +37 -0
  176. package/dist/src/phone/recovery.js +81 -0
  177. package/dist/src/phone/repository.d.ts +1 -0
  178. package/dist/src/phone/repository.js +3 -0
  179. package/dist/src/phone/runtime.js +232 -54
  180. package/dist/src/phone/semantic-controls.d.ts +13 -0
  181. package/dist/src/phone/semantic-controls.js +76 -0
  182. package/dist/src/phone/setup/service.d.ts +148 -0
  183. package/dist/src/phone/setup/service.js +251 -0
  184. package/dist/src/providers/presentation.js +2 -2
  185. package/dist/src/providers/xopc-cloud-model-source.js +6 -2
  186. package/dist/src/realtime/runtime.js +1 -1
  187. package/dist/src/storage/sqlite/schema.d.ts +2 -2
  188. package/dist/src/storage/sqlite/schema.js +7 -7
  189. package/dist/src/storage/sqlite/schema.sql +10 -0
  190. package/dist/src/storage/sqlite/upgrades/260_browser_setup.sql +9 -0
  191. package/dist/src/user-context/sources/index.js +1 -1
  192. package/dist/src/work-discovery/service.js +2 -2
  193. package/package.json +6 -6
  194. package/skills/tools/configure-xopc/SKILL.md +47 -0
  195. package/skills/tools/configure-xopc/references/browser/acceptance.md +31 -0
  196. package/skills/tools/configure-xopc/references/browser/chrome-extension.md +19 -0
  197. package/skills/tools/configure-xopc/references/browser/overview.md +22 -0
  198. package/skills/tools/configure-xopc/references/browser/permissions.md +25 -0
  199. package/skills/tools/configure-xopc/references/browser/troubleshooting.md +24 -0
  200. package/skills/tools/configure-xopc/references/phone/acceptance.md +25 -0
  201. package/skills/tools/configure-xopc/references/phone/aliyun.md +29 -0
  202. package/skills/tools/configure-xopc/references/phone/dependencies.md +18 -0
  203. package/skills/tools/configure-xopc/references/phone/local.md +19 -0
  204. package/skills/tools/configure-xopc/references/phone/models.md +18 -0
  205. package/skills/tools/configure-xopc/references/phone/overview.md +30 -0
  206. package/skills/tools/configure-xopc/references/phone/troubleshooting.md +24 -0
  207. package/skills/tools/configure-xopc/references/scene-index.md +12 -0
  208. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-DclyJr1N.js +0 -1
  209. package/dist/gateway/static/root/assets/agents-jhErNtzi.js +0 -77
  210. package/dist/gateway/static/root/assets/apps-page-C0LcnI4h.js +0 -1
  211. package/dist/gateway/static/root/assets/automations-workspace-CBxiV34x.js +0 -8
  212. package/dist/gateway/static/root/assets/browser-automations-page-vJIrTxdi.js +0 -3
  213. package/dist/gateway/static/root/assets/browser-settings-page-in5Roh_E.js +0 -3
  214. package/dist/gateway/static/root/assets/capabilities-page-CiGx8wpQ.js +0 -2
  215. package/dist/gateway/static/root/assets/capabilities-settings-panel-a8kqjzQu.js +0 -8
  216. package/dist/gateway/static/root/assets/channels-C_CxcjKT.js +0 -1
  217. package/dist/gateway/static/root/assets/connectors-page-DCBO2CxK.js +0 -1
  218. package/dist/gateway/static/root/assets/device-pairing-wizard-Ctbgr50F.js +0 -1
  219. package/dist/gateway/static/root/assets/gateway-realtime-DkWCHVzI.js +0 -1
  220. package/dist/gateway/static/root/assets/gateway-settings-BsVOcmV5.js +0 -1
  221. package/dist/gateway/static/root/assets/highlight-code-C8eS9949.js +0 -1
  222. package/dist/gateway/static/root/assets/home-page-BZDZnmyc.js +0 -2
  223. package/dist/gateway/static/root/assets/index-Bys6njTY.js +0 -710
  224. package/dist/gateway/static/root/assets/index-Vsf0bj5e.css +0 -1
  225. package/dist/gateway/static/root/assets/local-app-workbench-page-Dk87jtcc.js +0 -1
  226. package/dist/gateway/static/root/assets/logs-page-D3gVdm8S.js +0 -2
  227. package/dist/gateway/static/root/assets/management-settings-BQNYFE4J.js +0 -1
  228. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-ChweJKTv.js +0 -1
  229. package/dist/gateway/static/root/assets/note-detail-panel-CYKwUCte.js +0 -5
  230. package/dist/gateway/static/root/assets/note-image-lightbox-BTSZb9ZT.js +0 -1
  231. package/dist/gateway/static/root/assets/notes-page-CJ5nhWfL.js +0 -8
  232. package/dist/gateway/static/root/assets/personal-page-DcW14lqn.js +0 -1
  233. package/dist/gateway/static/root/assets/phone-dependencies-card-D3l9uPFM.js +0 -1
  234. package/dist/gateway/static/root/assets/phone-model-picker-DOv38vBn.js +0 -1
  235. package/dist/gateway/static/root/assets/phone-settings-page-DUHp1q_9.js +0 -1
  236. package/dist/gateway/static/root/assets/plugin-details-dialog-BpfgDlVa.js +0 -1
  237. package/dist/gateway/static/root/assets/project-detail-page-GD8TxKad.js +0 -7
  238. package/dist/gateway/static/root/assets/remote-access-hub-D3el7lHK.js +0 -1
  239. package/dist/gateway/static/root/assets/runtime-tools-settings-panel-Dbskk6RG.js +0 -1
  240. package/dist/gateway/static/root/assets/sessions-page-07liaSHH.js +0 -1
  241. package/dist/gateway/static/root/assets/settings-advanced-gate-BGjU8rfN.js +0 -1
  242. package/dist/gateway/static/root/assets/settings-page-header-CYpuTXUW.js +0 -1
  243. package/dist/gateway/static/root/assets/setup-status-panel-DKo_VTx-.js +0 -1
  244. package/dist/gateway/static/root/assets/shares-settings-BODFqK8k.js +0 -1
  245. package/dist/gateway/static/root/assets/skill-reload-api-Ce6OUk2C.js +0 -1
  246. package/dist/gateway/static/root/assets/skills-page-B7ehOIML.js +0 -2
  247. package/dist/gateway/static/root/assets/system-settings-panel-CxJkZRT4.js +0 -1
  248. package/dist/gateway/static/root/assets/task-detail-page-CxRR0QuW.js +0 -2
  249. package/dist/gateway/static/root/assets/usage-page-uUEkO38r.js +0 -1
  250. package/dist/gateway/static/root/assets/user-model-page-ICUutbKL.js +0 -2
  251. package/dist/gateway/static/root/assets/xopc-cloud-account-card-CvT_W6YS.js +0 -1
@@ -0,0 +1,152 @@
1
+ import { type BrowserActionInput, type BrowserControlResult } from '@xopcai/browser-control-contract';
2
+ import type { BrowserSetupView } from '@xopcai/gateway-contract';
3
+ import type { Config } from '../../config/schema.js';
4
+ import type { EndpointToolRuntime } from '../../endpoint-tools/index.js';
5
+ import type { BrowserSetup } from './types.js';
6
+ export declare const browserConfigRevision: (config: Config) => string;
7
+ export interface BrowserSetupDeps {
8
+ getConfig: () => Config;
9
+ saveConfig: (next: Config, expected: Config) => Promise<{
10
+ saved: boolean;
11
+ error?: string;
12
+ }>;
13
+ endpoints: EndpointToolRuntime;
14
+ canUseBrowser: (agentId: string) => boolean;
15
+ canSwitchDriver?: (conversationId: string) => boolean;
16
+ policyRevision?: (agentId: string) => string;
17
+ prepare: () => Promise<unknown>;
18
+ release: (endpointId: string, sessionId: string) => Promise<BrowserControlResult>;
19
+ open: (action: 'chrome' | 'folder' | 'both') => Promise<unknown>;
20
+ doctor: () => Promise<{
21
+ installed: boolean;
22
+ needsRefresh?: boolean;
23
+ extensionDir?: string;
24
+ nativeHost?: {
25
+ installed: boolean;
26
+ };
27
+ }>;
28
+ }
29
+ /** Mutations require a local-owner grant created by the product UI, never model-supplied identity. */
30
+ export declare class BrowserSetupService {
31
+ private readonly deps;
32
+ private readonly preparing;
33
+ constructor(deps: BrowserSetupDeps);
34
+ private policyRevision;
35
+ endpoints(): {
36
+ endpointId: string;
37
+ principalId: string;
38
+ displayName: string;
39
+ appVersion: string;
40
+ }[];
41
+ owned(id: string, conversationId: string, agentId: string): BrowserSetup;
42
+ view(setup: BrowserSetup): BrowserSetupView & Record<string, unknown>;
43
+ inspect(conversationId: string, agentId: string): Promise<{
44
+ sceneId: string;
45
+ supportedConnection: string;
46
+ configRevision: string;
47
+ installation: {
48
+ installed: boolean;
49
+ needsRefresh: boolean;
50
+ nativeHostInstalled: boolean;
51
+ };
52
+ toolPermission: string;
53
+ enabled: boolean;
54
+ driverKind: "extension" | "playwright" | "cdp" | "remote";
55
+ sharedScope: string;
56
+ endpoints: {
57
+ endpointId: string;
58
+ principalId: string;
59
+ displayName: string;
60
+ appVersion: string;
61
+ }[];
62
+ setup: BrowserSetupView & Record<string, unknown>;
63
+ guidanceRefs: {
64
+ section?: string;
65
+ sceneId: string;
66
+ path: string;
67
+ resourceVersion: string;
68
+ }[];
69
+ ownerActionRequired: boolean;
70
+ supportedActions: string[];
71
+ }>;
72
+ command(command: string, args: Record<string, unknown>, context: {
73
+ conversationId: string;
74
+ agentId: string;
75
+ }, dryRun?: boolean): Promise<(BrowserSetupView & Record<string, unknown>) | {
76
+ sceneId: string;
77
+ supportedConnection: string;
78
+ configRevision: string;
79
+ installation: {
80
+ installed: boolean;
81
+ needsRefresh: boolean;
82
+ nativeHostInstalled: boolean;
83
+ };
84
+ toolPermission: string;
85
+ enabled: boolean;
86
+ driverKind: "extension" | "playwright" | "cdp" | "remote";
87
+ sharedScope: string;
88
+ endpoints: {
89
+ endpointId: string;
90
+ principalId: string;
91
+ displayName: string;
92
+ appVersion: string;
93
+ }[];
94
+ setup: BrowserSetupView & Record<string, unknown>;
95
+ guidanceRefs: {
96
+ section?: string;
97
+ sceneId: string;
98
+ path: string;
99
+ resourceVersion: string;
100
+ }[];
101
+ ownerActionRequired: boolean;
102
+ supportedActions: string[];
103
+ } | {
104
+ message: string;
105
+ sceneId: string;
106
+ supportedConnection: string;
107
+ configRevision: string;
108
+ installation: {
109
+ installed: boolean;
110
+ needsRefresh: boolean;
111
+ nativeHostInstalled: boolean;
112
+ };
113
+ toolPermission: string;
114
+ enabled: boolean;
115
+ driverKind: "extension" | "playwright" | "cdp" | "remote";
116
+ sharedScope: string;
117
+ endpoints: {
118
+ endpointId: string;
119
+ principalId: string;
120
+ displayName: string;
121
+ appVersion: string;
122
+ }[];
123
+ setup: BrowserSetupView & Record<string, unknown>;
124
+ guidanceRefs: {
125
+ section?: string;
126
+ sceneId: string;
127
+ path: string;
128
+ resourceVersion: string;
129
+ }[];
130
+ ownerActionRequired: boolean;
131
+ supportedActions: string[];
132
+ dryRun: boolean;
133
+ }>;
134
+ approve(setup: BrowserSetup, principalId: string, revision: number): BrowserSetup;
135
+ private revision;
136
+ prepare(setup: BrowserSetup): Promise<BrowserSetup>;
137
+ recheck(setup: BrowserSetup): Promise<BrowserSetup>;
138
+ open(setup: BrowserSetup, action: 'chrome' | 'folder' | 'both'): Promise<unknown>;
139
+ begin(setup: BrowserSetup, endpointId: string, origin: string, revision: number): BrowserSetup;
140
+ cancel(setup: BrowserSetup): BrowserSetup;
141
+ release(setup: BrowserSetup): Promise<BrowserSetup>;
142
+ canRestoreSession(taskKey: string, sessionId: string): boolean;
143
+ allowsVerificationUrl(taskKey: string, url: string): boolean;
144
+ /** Called only by the real Agent browser tool, before its normal runtime/policy path. */
145
+ beforeAction(conversationId: string, agentId: string, input: BrowserActionInput): {
146
+ setupId: string;
147
+ attemptId: string;
148
+ taskKey: string;
149
+ input: BrowserActionInput;
150
+ };
151
+ afterAction(setupId: string, attemptId: string, input: BrowserActionInput, result: BrowserControlResult): BrowserSetup;
152
+ }
@@ -0,0 +1,404 @@
1
+ import { createLogger } from "../../utils/logger/index.js";
2
+ import { init_logger } from "../../utils/logger.js";
3
+ import { getBrowserTabBinding, init_browser_tab_binding_repository } from "../../storage/sqlite/browser-tab-binding-repository.js";
4
+ import "../../../packages/browser-control-contract/src/index.js";
5
+ import { createBrowserSetup, findBrowserSetup, readBrowserSetup, saveBrowserSetup } from "./repository.js";
6
+ import { createHash, randomUUID } from "node:crypto";
7
+ //#region src/browser/setup/service.ts
8
+ init_browser_tab_binding_repository();
9
+ init_logger();
10
+ const log = createLogger("BrowserSetup");
11
+ const VERSION = "1";
12
+ const MAX_ACTIONS = 12;
13
+ const VERIFY_MS = 12e4;
14
+ const ref = (name, section) => ({
15
+ sceneId: "browser",
16
+ path: `references/browser/${name}.md`,
17
+ resourceVersion: VERSION,
18
+ ...section ? { section } : {}
19
+ });
20
+ const browserConfigRevision = (config) => createHash("sha256").update(JSON.stringify(config.browser)).digest("hex");
21
+ /** Mutations require a local-owner grant created by the product UI, never model-supplied identity. */
22
+ var BrowserSetupService = class {
23
+ preparing = /* @__PURE__ */ new Set();
24
+ constructor(deps) {
25
+ this.deps = deps;
26
+ }
27
+ policyRevision(agentId) {
28
+ return this.deps.policyRevision?.(agentId) ?? String(this.deps.canUseBrowser(agentId));
29
+ }
30
+ endpoints() {
31
+ return this.deps.endpoints.registry.list().filter((e) => e.kind === "browser" && e.tools.some((t) => t.descriptor.name === "browser.control")).map((e) => ({
32
+ endpointId: e.endpointId,
33
+ principalId: e.principalId,
34
+ displayName: e.displayName,
35
+ appVersion: e.appVersion
36
+ }));
37
+ }
38
+ owned(id, conversationId, agentId) {
39
+ const setup = readBrowserSetup(id);
40
+ if (!setup || setup.conversationId !== conversationId || setup.agentId !== agentId) throw new Error("SETUP_NOT_FOUND");
41
+ return setup;
42
+ }
43
+ view(setup) {
44
+ if (setup.state === "verifying" && setup.attempt && Date.now() > setup.attempt.expiresAt) setup = {
45
+ ...setup,
46
+ state: "needs_attention",
47
+ error: "VERIFICATION_EXPIRED: Release the demo session before starting a new test."
48
+ };
49
+ const attempt = setup.attempt ? (({ observation: _observation, ...summary }) => summary)(setup.attempt) : void 0;
50
+ const endpoint = setup.attempt ? this.endpoints().find((e) => e.endpointId === setup.attempt.endpointId) : void 0;
51
+ const changed = setup.configRevision !== browserConfigRevision(this.deps.getConfig()) || Boolean(setup.attempt && (setup.attempt.policyRevision !== this.policyRevision(setup.agentId) || !this.deps.canUseBrowser(setup.agentId) || endpoint && (endpoint.principalId !== setup.attempt.principalId || endpoint.appVersion !== setup.attempt.appVersion)));
52
+ return {
53
+ ...setup,
54
+ attempt: setup.attempt ? attempt : void 0,
55
+ sceneId: "browser",
56
+ skillName: "configure-xopc",
57
+ resourceVersion: VERSION,
58
+ stale: changed,
59
+ toolPermission: this.deps.canUseBrowser(setup.agentId) ? "allowed" : "denied",
60
+ currentDriverKind: this.deps.getConfig().browser.driver.kind,
61
+ endpoints: this.endpoints(),
62
+ settingsPath: `/settings/agent-browser?browserSetup=${setup.id}&conversationId=${setup.conversationId}`,
63
+ checks: {
64
+ configured: this.deps.getConfig().browser.enabled && this.deps.getConfig().browser.driver.kind === "extension",
65
+ read: setup.attempt?.read ?? false,
66
+ clicked: setup.attempt?.clicked ?? false,
67
+ filled: setup.attempt?.filled ?? false,
68
+ released: setup.attempt?.released ?? false
69
+ },
70
+ guidanceRefs: [ref(setup.state === "verifying" || setup.state === "completed" ? "acceptance" : setup.error ? "troubleshooting" : "chrome-extension")],
71
+ allowedActions: setup.state === "cancelled" ? ["get"] : setup.state === "completed" ? ["get", "verification_report"] : [
72
+ "get",
73
+ "recheck",
74
+ "cancel",
75
+ ...setup.approvedBy && !changed ? ["advance"] : []
76
+ ]
77
+ };
78
+ }
79
+ async inspect(conversationId, agentId) {
80
+ const config = this.deps.getConfig();
81
+ const existing = findBrowserSetup(conversationId, agentId);
82
+ const installation = await this.deps.doctor();
83
+ return {
84
+ sceneId: "browser",
85
+ supportedConnection: "extension",
86
+ configRevision: browserConfigRevision(config),
87
+ installation: {
88
+ installed: installation.installed,
89
+ needsRefresh: installation.needsRefresh ?? false,
90
+ nativeHostInstalled: installation.nativeHost?.installed === true
91
+ },
92
+ toolPermission: this.deps.canUseBrowser(agentId) ? "allowed" : "denied",
93
+ enabled: config.browser.enabled,
94
+ driverKind: config.browser.driver.kind,
95
+ sharedScope: "gateway",
96
+ endpoints: this.endpoints(),
97
+ setup: existing ? this.view(existing) : null,
98
+ guidanceRefs: [ref("overview")],
99
+ ownerActionRequired: true,
100
+ supportedActions: [
101
+ "inspect",
102
+ "preview",
103
+ "start",
104
+ "get",
105
+ "advance",
106
+ "recheck",
107
+ "request_interaction",
108
+ "begin_verification",
109
+ "verification_report",
110
+ "cancel"
111
+ ]
112
+ };
113
+ }
114
+ async command(command, args, context, dryRun = false) {
115
+ if (command === "inspect" || command === "preview") return this.inspect(context.conversationId, context.agentId);
116
+ if (dryRun) return {
117
+ dryRun: true,
118
+ ...await this.inspect(context.conversationId, context.agentId),
119
+ message: "No changes made. Open the product setup panel to approve installation."
120
+ };
121
+ if (command === "start") {
122
+ const previous = findBrowserSetup(context.conversationId, context.agentId);
123
+ if (previous?.attempt && !previous.attempt.released) return this.view(previous);
124
+ if (previous && this.view(previous).stale && (!previous.attempt || previous.attempt.released)) this.cancel(previous);
125
+ return this.view(createBrowserSetup(context.conversationId, context.agentId, browserConfigRevision(this.deps.getConfig())));
126
+ }
127
+ if (typeof args.setupId !== "string") throw new Error("setupId is required");
128
+ const setup = this.owned(args.setupId, context.conversationId, context.agentId);
129
+ if (command === "get" || command === "verification_report" || command === "request_interaction") return this.view(setup);
130
+ if (command === "recheck") return this.view(await this.recheck(setup));
131
+ if (command === "advance") {
132
+ if (!setup.approvedBy) return {
133
+ ...this.view(setup),
134
+ message: "Approve this plan in the local-owner setup panel first."
135
+ };
136
+ return this.view(await this.prepare(setup));
137
+ }
138
+ if (command === "begin_verification") return {
139
+ ...this.view(setup),
140
+ message: "Select Chrome and start the test in the local-owner setup panel. The test uses normal browser_use calls."
141
+ };
142
+ if (command === "cancel") return this.view(this.cancel(setup));
143
+ throw new Error("Unsupported browser_setup command");
144
+ }
145
+ approve(setup, principalId, revision) {
146
+ this.revision(setup, revision);
147
+ if (setup.state === "cancelled" || setup.state === "verifying" || setup.state === "completed") throw new Error("SETUP_STATE_CHANGED");
148
+ if (setup.configRevision !== browserConfigRevision(this.deps.getConfig())) throw new Error("CONFIG_CHANGED: Review the current configuration before approving.");
149
+ return saveBrowserSetup({
150
+ ...setup,
151
+ approvedBy: principalId,
152
+ error: void 0
153
+ }, setup.revision);
154
+ }
155
+ revision(setup, revision) {
156
+ if (setup.revision !== revision) throw new Error("SETUP_CONFLICT: Read the current progress.");
157
+ }
158
+ async prepare(setup) {
159
+ if (!setup.approvedBy || setup.state === "cancelled" || setup.state === "verifying" || setup.state === "completed") throw new Error("OWNER_APPROVAL_REQUIRED");
160
+ if (setup.attempt && !setup.attempt.released) throw new Error("CONTROL_RELEASE_REQUIRED");
161
+ if (this.preparing.has(setup.id)) return readBrowserSetup(setup.id);
162
+ if (["waiting_extension", "ready_for_verification"].includes(setup.state) && !setup.error) return this.recheck(setup);
163
+ const config = this.deps.getConfig();
164
+ if (setup.configRevision !== browserConfigRevision(config)) throw new Error("CONFIG_CHANGED: Review a new plan.");
165
+ if (config.browser.enabled && config.browser.driver.kind !== "extension" && this.deps.canSwitchDriver?.(setup.conversationId) === false) return saveBrowserSetup({
166
+ ...setup,
167
+ state: "needs_attention",
168
+ error: "BROWSER_BUSY: Release existing browser sessions and wait for other runs before switching the shared driver."
169
+ }, setup.revision);
170
+ this.preparing.add(setup.id);
171
+ let current = saveBrowserSetup({
172
+ ...setup,
173
+ state: "preparing",
174
+ error: void 0,
175
+ operation: {
176
+ key: setup.operation?.key ?? randomUUID(),
177
+ startedAt: Date.now()
178
+ }
179
+ }, setup.revision);
180
+ try {
181
+ const next = structuredClone(config);
182
+ next.browser.enabled = true;
183
+ next.browser.driver = { kind: "extension" };
184
+ if (browserConfigRevision(next) !== browserConfigRevision(config)) {
185
+ if (!(await this.deps.saveConfig(next, config)).saved) throw new Error("CONFIG_CHANGED: Configuration was not saved. Review the current settings.");
186
+ }
187
+ current = readBrowserSetup(setup.id);
188
+ if (current.state === "cancelled") return current;
189
+ current = saveBrowserSetup({
190
+ ...current,
191
+ configRevision: browserConfigRevision(this.deps.getConfig())
192
+ }, current.revision);
193
+ await this.deps.prepare();
194
+ current = readBrowserSetup(setup.id);
195
+ if (current.state === "cancelled") return current;
196
+ this.preparing.delete(setup.id);
197
+ return await this.recheck(saveBrowserSetup({
198
+ ...current,
199
+ state: "waiting_extension",
200
+ operation: void 0
201
+ }, current.revision));
202
+ } catch (error) {
203
+ log.warn({
204
+ err: error,
205
+ setupId: setup.id
206
+ }, "Browser setup preparation failed");
207
+ current = readBrowserSetup(setup.id);
208
+ if (current.state === "cancelled") return current;
209
+ return saveBrowserSetup({
210
+ ...current,
211
+ state: "needs_attention",
212
+ operation: void 0,
213
+ error: "PREPARE_FAILED: Check the local installation and retry. Existing settings and files may have been prepared."
214
+ }, current.revision);
215
+ } finally {
216
+ this.preparing.delete(setup.id);
217
+ }
218
+ }
219
+ async recheck(setup) {
220
+ if (setup.state === "cancelled" || setup.state === "completed" || setup.state === "verifying" || this.preparing.has(setup.id)) return setup;
221
+ if (!setup.approvedBy || setup.attempt && !setup.attempt.released) return setup;
222
+ if (setup.configRevision !== browserConfigRevision(this.deps.getConfig())) return saveBrowserSetup({
223
+ ...setup,
224
+ state: "needs_attention",
225
+ approvedBy: void 0,
226
+ error: "CONFIG_CHANGED: Restart the plan using the current settings."
227
+ }, setup.revision);
228
+ const doctor = await this.deps.doctor();
229
+ const current = readBrowserSetup(setup.id);
230
+ if (current.revision !== setup.revision) return current;
231
+ const ready = doctor.installed && !doctor.needsRefresh && doctor.nativeHost?.installed === true;
232
+ return saveBrowserSetup({
233
+ ...setup,
234
+ state: ready ? this.endpoints().length ? "ready_for_verification" : "waiting_extension" : "needs_attention",
235
+ operation: void 0,
236
+ error: ready ? void 0 : "INSTALLATION_REQUIRED: Prepare or repair the local extension files."
237
+ }, setup.revision);
238
+ }
239
+ async open(setup, action) {
240
+ if (!setup.approvedBy || setup.state === "cancelled") throw new Error("OWNER_APPROVAL_REQUIRED");
241
+ return this.deps.open(action);
242
+ }
243
+ begin(setup, endpointId, origin, revision) {
244
+ this.revision(setup, revision);
245
+ if (!setup.approvedBy || setup.state !== "ready_for_verification") throw new Error("SETUP_NOT_READY");
246
+ if (setup.configRevision !== browserConfigRevision(this.deps.getConfig())) throw new Error("CONFIG_CHANGED");
247
+ if (setup.attempt && !setup.attempt.released) throw new Error("CONTROL_RELEASE_REQUIRED");
248
+ if (!this.deps.canUseBrowser(setup.agentId)) throw new Error("AGENT_BROWSER_DENIED: Enable browser_use for this Agent and start a refreshed turn.");
249
+ if (getBrowserTabBinding(setup.conversationId)) throw new Error("TAB_ALREADY_ATTACHED: Release the existing tab before starting this test.");
250
+ const endpoint = this.endpoints().find((e) => e.endpointId === endpointId);
251
+ if (!endpoint) throw new Error("ENDPOINT_OFFLINE");
252
+ const url = new URL(origin);
253
+ if (!["http:", "https:"].includes(url.protocol) || url.username || url.password) throw new Error("INVALID_ORIGIN");
254
+ const id = randomUUID();
255
+ const marker = `XOPC-${randomUUID()}`;
256
+ return saveBrowserSetup({
257
+ ...setup,
258
+ state: "verifying",
259
+ error: void 0,
260
+ attempt: {
261
+ id,
262
+ endpointId,
263
+ principalId: endpoint.principalId,
264
+ appVersion: endpoint.appVersion,
265
+ policyRevision: this.policyRevision(setup.agentId),
266
+ fixtureUrl: `${url.origin}/browser-setup-test.html#${marker}`,
267
+ marker,
268
+ sample: `Hello-${id.slice(0, 8)}`,
269
+ sessionId: randomUUID(),
270
+ expiresAt: Date.now() + VERIFY_MS,
271
+ actions: 0,
272
+ read: false,
273
+ clicked: false,
274
+ filled: false,
275
+ released: false
276
+ }
277
+ }, setup.revision);
278
+ }
279
+ cancel(setup) {
280
+ if (setup.state === "cancelled") return setup;
281
+ return saveBrowserSetup({
282
+ ...setup,
283
+ state: "cancelled",
284
+ approvedBy: void 0,
285
+ error: setup.attempt && !setup.attempt.released ? "CONTROL_RELEASE_REQUIRED: Close the verification browser session; cancellation does not prove release." : void 0
286
+ }, setup.revision);
287
+ }
288
+ async release(setup) {
289
+ if (!setup.attempt || setup.attempt.released) return setup;
290
+ const endpoint = this.endpoints().find((e) => e.endpointId === setup.attempt.endpointId);
291
+ if (!endpoint || endpoint.principalId !== setup.attempt.principalId) throw new Error("ENDPOINT_OFFLINE: Control release cannot be confirmed.");
292
+ const result = await this.deps.release(setup.attempt.endpointId, setup.attempt.sessionId);
293
+ return this.afterAction(setup.id, setup.attempt.id, { action: "close" }, result) ?? readBrowserSetup(setup.id);
294
+ }
295
+ canRestoreSession(taskKey, sessionId) {
296
+ const [prefix, setupId, attemptId] = taskKey.split(":");
297
+ if (prefix !== "browser-setup" || !setupId) return false;
298
+ const setup = readBrowserSetup(setupId);
299
+ return Boolean(setup?.attempt?.id === attemptId && setup.attempt.sessionId === sessionId && !setup.attempt.released);
300
+ }
301
+ allowsVerificationUrl(taskKey, url) {
302
+ const [prefix, setupId, attemptId] = taskKey.split(":");
303
+ if (prefix !== "browser-setup" || !setupId) return false;
304
+ const setup = readBrowserSetup(setupId);
305
+ return Boolean(setup?.approvedBy && setup.state === "verifying" && setup.attempt?.id === attemptId && setup.attempt.fixtureUrl === url && Date.now() <= setup.attempt.expiresAt && setup.configRevision === browserConfigRevision(this.deps.getConfig()));
306
+ }
307
+ /** Called only by the real Agent browser tool, before its normal runtime/policy path. */
308
+ beforeAction(conversationId, agentId, input) {
309
+ let setup = findBrowserSetup(conversationId, agentId);
310
+ if (setup?.attempt?.released && input.action === "close" && input.sessionId === setup.attempt.sessionId) throw new Error("VERIFICATION_ALREADY_RELEASED");
311
+ if (!setup?.attempt || setup.attempt.released || ![
312
+ "verifying",
313
+ "needs_attention",
314
+ "cancelled"
315
+ ].includes(setup.state)) return void 0;
316
+ const a = setup.attempt;
317
+ if (!(input.action === "close")) {
318
+ if (setup.state !== "verifying") throw new Error("VERIFICATION_STOPPED: Close the verification session first.");
319
+ if (Date.now() > a.expiresAt || a.actions >= MAX_ACTIONS) throw new Error("VERIFICATION_BUDGET_EXCEEDED: Close the verification session.");
320
+ if (setup.configRevision !== browserConfigRevision(this.deps.getConfig()) || a.policyRevision !== this.policyRevision(setup.agentId)) throw new Error("CONFIG_CHANGED: Close the verification session.");
321
+ const endpoint = this.endpoints().find((e) => e.endpointId === a.endpointId);
322
+ if (!endpoint || endpoint.principalId !== a.principalId || endpoint.appVersion !== a.appVersion) throw new Error("ENDPOINT_CHANGED");
323
+ const node = "ref" in input ? a.observation?.nodes.find((n) => n.ref === input.ref) : void 0;
324
+ if (!(input.action === "navigate" ? !a.tabId && input.url === a.fixtureUrl : input.action === "observe" ? Boolean(a.sessionId) : input.action === "click" ? a.read && !a.clicked && node?.role === "button" && node.name === "Test click" && input.revision === a.observation?.revision : input.action === "fill" ? a.clicked && !a.filled && node?.name === "Test input" && input.value === a.sample && input.submit !== true && input.revision === a.observation?.revision : false)) throw new Error("VERIFICATION_ACTION_DENIED: Follow the test instructions using fresh observation refs.");
325
+ }
326
+ if (input.sessionId && input.sessionId !== a.sessionId) throw new Error("VERIFICATION_SESSION_MISMATCH");
327
+ setup = saveBrowserSetup({
328
+ ...setup,
329
+ attempt: {
330
+ ...a,
331
+ actions: a.actions + 1
332
+ }
333
+ }, setup.revision);
334
+ return {
335
+ setupId: setup.id,
336
+ attemptId: a.id,
337
+ taskKey: `browser-setup:${setup.id}:${a.id}`,
338
+ input: {
339
+ ...input,
340
+ ...a.sessionId ? { sessionId: a.sessionId } : {},
341
+ target: {
342
+ kind: "endpoint",
343
+ endpointId: a.endpointId
344
+ }
345
+ }
346
+ };
347
+ }
348
+ afterAction(setupId, attemptId, input, result) {
349
+ const setup = readBrowserSetup(setupId);
350
+ if (!setup?.attempt || setup.attempt.id !== attemptId) return;
351
+ const a = { ...setup.attempt };
352
+ if (input.action === "close" && result.ok && result.receipt.action === "close" && result.receipt.verified) {
353
+ a.released = true;
354
+ delete a.observation;
355
+ const complete = setup.state === "verifying" && setup.configRevision === browserConfigRevision(this.deps.getConfig()) && Date.now() <= a.expiresAt && a.policyRevision === this.policyRevision(setup.agentId) && this.deps.canUseBrowser(setup.agentId) && a.read && a.clicked && a.filled;
356
+ return saveBrowserSetup({
357
+ ...setup,
358
+ attempt: a,
359
+ state: setup.state === "cancelled" ? "cancelled" : complete ? "completed" : "needs_attention",
360
+ error: complete || setup.state === "cancelled" ? void 0 : setup.error?.startsWith("BROWSER_CONTROL_REVOKED") ? setup.error : "VERIFICATION_INCOMPLETE: Review the checks and start a new test."
361
+ }, setup.revision);
362
+ }
363
+ if ("error" in result) return saveBrowserSetup({
364
+ ...setup,
365
+ state: setup.state === "cancelled" ? "cancelled" : "needs_attention",
366
+ error: result.error.message.includes("BROWSER_CONTROL_REVOKED") ? "BROWSER_CONTROL_REVOKED: Chrome control was stopped by the user. Release the demo, then resume control in the extension before starting a new test." : "BROWSER_ACTION_FAILED: Close the verification session before retrying."
367
+ }, setup.revision);
368
+ if (result.receipt.action !== input.action) return saveBrowserSetup({
369
+ ...setup,
370
+ state: setup.state === "cancelled" ? "cancelled" : "needs_attention",
371
+ error: "VERIFICATION_RECEIPT_MISMATCH: Release the demo session."
372
+ }, setup.revision);
373
+ const o = result.receipt.observation;
374
+ if (!o || !result.receipt.verified) return;
375
+ if (o.url !== a.fixtureUrl || a.tabId && o.tabId !== a.tabId || a.documentId && o.documentId !== a.documentId || a.sessionId && o.sessionId !== a.sessionId) return saveBrowserSetup({
376
+ ...setup,
377
+ state: setup.state === "cancelled" ? "cancelled" : "needs_attention",
378
+ error: "VERIFICATION_TARGET_CHANGED: Close the verification session."
379
+ }, setup.revision);
380
+ a.sessionId = o.sessionId;
381
+ a.tabId = o.tabId;
382
+ a.documentId = o.documentId;
383
+ a.observation = {
384
+ revision: o.revision,
385
+ nodes: o.nodes.map(({ ref, role, name, value, states }) => ({
386
+ ref,
387
+ role,
388
+ name,
389
+ value,
390
+ states
391
+ }))
392
+ };
393
+ const names = o.nodes.map((n) => n.name);
394
+ if (names.includes(`Read check: ${a.marker}`)) a.read = true;
395
+ if (input.action === "click" && names.includes(`Click passed: ${a.marker}`)) a.clicked = true;
396
+ if (input.action === "fill" && a.clicked && names.includes(`Input passed: ${a.sample}`)) a.filled = true;
397
+ return saveBrowserSetup({
398
+ ...setup,
399
+ attempt: a
400
+ }, setup.revision);
401
+ }
402
+ };
403
+ //#endregion
404
+ export { BrowserSetupService, browserConfigRevision };
@@ -0,0 +1,38 @@
1
+ import type { BrowserObservation } from '@xopcai/browser-control-contract';
2
+ export type SetupState = 'plan_ready' | 'preparing' | 'waiting_extension' | 'ready_for_verification' | 'verifying' | 'needs_attention' | 'completed' | 'cancelled';
3
+ export interface BrowserSetup {
4
+ id: string;
5
+ conversationId: string;
6
+ agentId: string;
7
+ revision: number;
8
+ state: SetupState;
9
+ configRevision: string;
10
+ approvedBy?: string;
11
+ createdAt: number;
12
+ updatedAt: number;
13
+ operation?: {
14
+ key: string;
15
+ startedAt: number;
16
+ };
17
+ error?: string;
18
+ attempt?: {
19
+ id: string;
20
+ endpointId: string;
21
+ principalId: string;
22
+ appVersion: string;
23
+ policyRevision: string;
24
+ fixtureUrl: string;
25
+ marker: string;
26
+ sample: string;
27
+ expiresAt: number;
28
+ actions: number;
29
+ sessionId?: string;
30
+ tabId?: string;
31
+ documentId?: string;
32
+ observation?: Pick<BrowserObservation, 'revision' | 'nodes'>;
33
+ read: boolean;
34
+ clicked: boolean;
35
+ filled: boolean;
36
+ released: boolean;
37
+ };
38
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -32,7 +32,7 @@ async function checkDatabaseSchema(ctx) {
32
32
  id: "database-schema",
33
33
  label: "Database schema",
34
34
  status: "pass",
35
- message: `SQLite schema v${readSchemaVersion(getSqliteDatabase())} (current release v259).`,
35
+ message: `SQLite schema v${readSchemaVersion(getSqliteDatabase())} (current release v260).`,
36
36
  hints: []
37
37
  };
38
38
  }
@@ -1,8 +1,8 @@
1
1
  import { init_paths, resolveConfigPath } from "../../../config/paths.js";
2
2
  import { loadConfig } from "../../../config/loader.js";
3
3
  import "../../../config/index.js";
4
- import { resolveGatewayService } from "../../../daemon/service.js";
5
4
  import { isRestartEnabled } from "../../../config/commands.flags.js";
5
+ import { resolveGatewayService } from "../../../daemon/service.js";
6
6
  import { authorizeGatewaySigusr1Restart, writeGatewayRestartIntentSync } from "../../../infra/restart.js";
7
7
  import { findVerifiedGatewayListenerPidsOnPortSync, formatGatewayPidList, signalVerifiedGatewayPidSync } from "../../../infra/gateway-processes.js";
8
8
  import { runServiceRestart, runServiceStop } from "./lifecycle-core.js";
@@ -1781,6 +1781,8 @@ export declare const ConfigSchema: z.ZodDefault<z.ZodObject<{
1781
1781
  phone: z.ZodPrefault<z.ZodObject<{
1782
1782
  enabled: z.ZodDefault<z.ZodBoolean>;
1783
1783
  adbPath: z.ZodOptional<z.ZodString>;
1784
+ semanticControls: z.ZodDefault<z.ZodBoolean>;
1785
+ hierarchicalPlanning: z.ZodDefault<z.ZodBoolean>;
1784
1786
  maxActionsPerSession: z.ZodDefault<z.ZodNumber>;
1785
1787
  maxModelRequests: z.ZodDefault<z.ZodNumber>;
1786
1788
  maxOperationDurationMs: z.ZodDefault<z.ZodNumber>;
@@ -12,9 +12,9 @@ import { claimRegisteredExtraction } from "../user-context/extraction/registry.j
12
12
  import { reconcileAssertion } from "../user-model/repository.js";
13
13
  import "../user-model/index.js";
14
14
  import { getUnderstandingSourceRun } from "../user-context/sources/repository.js";
15
+ import { recordConnectedSourceObservations } from "./connected-source-observations.js";
15
16
  import { allowsRemoteSourceProcessing } from "../user-context/sources/processing-policy.js";
16
17
  import { analyzeUnderstandingSources } from "../work-discovery/analyzer.js";
17
- import { recordConnectedSourceObservations } from "./connected-source-observations.js";
18
18
  import { createHash } from "node:crypto";
19
19
  //#region src/connectors/connected-source-understanding.ts
20
20
  init_sqlite();
@@ -12,8 +12,8 @@ import { ComposioSessionsAdapter } from "./composio-sessions.js";
12
12
  import { buildConnectorLearningArguments, getConnectorLearningPlan } from "./learning-recipes.js";
13
13
  import { getConnectorDefinition } from "./catalog.js";
14
14
  import { getConnectorUnderstandingSourceRun, getOrCreateConnectorUnderstandingSourceRun, getUnderstandingSourceGrant, listUnderstandingSourceGrants, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceRun, upsertUnderstandingSourceGrant } from "../user-context/sources/repository.js";
15
- import { deriveConnectedSourceUnderstanding } from "./connected-source-understanding.js";
16
15
  import { ingestComposioConnectedSource } from "./connected-source-ingestion.js";
16
+ import { deriveConnectedSourceUnderstanding } from "./connected-source-understanding.js";
17
17
  import { listConnectedContentCandidates, readConnectedContent } from "./content-enrichment.js";
18
18
  //#region src/connectors/learning-coordinator.ts
19
19
  init_sqlite();
@@ -277,4 +277,4 @@ export declare const GATEWAY_BUILTIN_TOOLS: readonly [{
277
277
  readonly zh: "使用已验证的参数执行选定的外部工具。";
278
278
  };
279
279
  }];
280
- export declare const GATEWAY_BUILTIN_TOOL_IDS: ("automation" | "find" | "image" | "knowledge_search" | "knowledge_get" | "knowledge_write" | "user_context_search" | "user_context_get" | "user_context_update" | "web_search" | "web_fetch" | "browser_use" | "grep" | "session_search" | "read_file" | "list_dir" | "write_file" | "apply_patch" | "exec_command" | "update_plan" | "todo" | "web_extract" | "clarify" | "xopc_tool_execute" | "tool_manual" | "session_status" | "read_media" | "xopc_tool_search" | "xopc_tool_describe" | "phone_use" | "image_generate" | "skills_list" | "skill_view" | "skill_manage" | "skills_marketplace_search" | "computer_use" | "send_message" | "text_to_speech" | "execute_code" | "send_media" | "create_share" | "memory_maintenance" | "delegate_task" | "skill_install" | "create_desktop_pet")[];
280
+ export declare const GATEWAY_BUILTIN_TOOL_IDS: ("automation" | "find" | "image" | "knowledge_search" | "knowledge_get" | "knowledge_write" | "user_context_search" | "user_context_get" | "user_context_update" | "web_search" | "web_fetch" | "browser_use" | "grep" | "session_search" | "read_file" | "list_dir" | "write_file" | "apply_patch" | "exec_command" | "update_plan" | "todo" | "web_extract" | "clarify" | "xopc_tool_execute" | "tool_manual" | "session_status" | "read_media" | "xopc_tool_search" | "xopc_tool_describe" | "phone_use" | "skill_view" | "skills_list" | "image_generate" | "skill_manage" | "skills_marketplace_search" | "computer_use" | "send_message" | "text_to_speech" | "execute_code" | "send_media" | "create_share" | "memory_maintenance" | "delegate_task" | "skill_install" | "create_desktop_pet")[];
@@ -0,0 +1,3 @@
1
+ import type { Hono } from 'hono';
2
+ import type { AuthenticatedRouteDeps } from './deps.js';
3
+ export declare function registerBrowserSetupRoutes(app: Hono, deps: AuthenticatedRouteDeps): void;