@withbuddi/buddi 0.1.0-pre.37 → 0.1.0-pre.38

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 (703) hide show
  1. package/extension/background.js +130 -12
  2. package/extension/manifest.json +2 -2
  3. package/node_modules/@buddi/cli/dist/.tsbuildinfo +1 -1
  4. package/node_modules/@buddi/cli/dist/access-cmd.d.ts +10 -0
  5. package/node_modules/@buddi/cli/dist/access-cmd.d.ts.map +1 -0
  6. package/node_modules/@buddi/cli/dist/access-cmd.js +160 -0
  7. package/node_modules/@buddi/cli/dist/access-cmd.js.map +1 -0
  8. package/node_modules/@buddi/cli/dist/args.d.ts +10 -0
  9. package/node_modules/@buddi/cli/dist/args.d.ts.map +1 -1
  10. package/node_modules/@buddi/cli/dist/args.js +29 -1
  11. package/node_modules/@buddi/cli/dist/args.js.map +1 -1
  12. package/node_modules/@buddi/cli/dist/commands.d.ts.map +1 -1
  13. package/node_modules/@buddi/cli/dist/commands.js +28 -2
  14. package/node_modules/@buddi/cli/dist/commands.js.map +1 -1
  15. package/node_modules/@buddi/cli/dist/doctor-probes.d.ts.map +1 -1
  16. package/node_modules/@buddi/cli/dist/doctor-probes.js +54 -29
  17. package/node_modules/@buddi/cli/dist/doctor-probes.js.map +1 -1
  18. package/node_modules/@buddi/cli/dist/doctor.d.ts +36 -12
  19. package/node_modules/@buddi/cli/dist/doctor.d.ts.map +1 -1
  20. package/node_modules/@buddi/cli/dist/doctor.js +32 -9
  21. package/node_modules/@buddi/cli/dist/doctor.js.map +1 -1
  22. package/node_modules/@buddi/cli/dist/main.d.ts +2 -0
  23. package/node_modules/@buddi/cli/dist/main.d.ts.map +1 -1
  24. package/node_modules/@buddi/cli/dist/main.js +18 -1
  25. package/node_modules/@buddi/cli/dist/main.js.map +1 -1
  26. package/node_modules/@buddi/core/dist/.tsbuildinfo +1 -1
  27. package/node_modules/@buddi/core/dist/agents/catalog.d.ts +2 -0
  28. package/node_modules/@buddi/core/dist/agents/catalog.d.ts.map +1 -1
  29. package/node_modules/@buddi/core/dist/agents/catalog.js +1 -0
  30. package/node_modules/@buddi/core/dist/agents/catalog.js.map +1 -1
  31. package/node_modules/@buddi/core/dist/agents/edit.d.ts +2 -0
  32. package/node_modules/@buddi/core/dist/agents/edit.d.ts.map +1 -1
  33. package/node_modules/@buddi/core/dist/agents/edit.js +3 -1
  34. package/node_modules/@buddi/core/dist/agents/edit.js.map +1 -1
  35. package/node_modules/@buddi/core/dist/agents/frontmatter.d.ts +11 -0
  36. package/node_modules/@buddi/core/dist/agents/frontmatter.d.ts.map +1 -1
  37. package/node_modules/@buddi/core/dist/agents/frontmatter.js +7 -0
  38. package/node_modules/@buddi/core/dist/agents/frontmatter.js.map +1 -1
  39. package/node_modules/@buddi/core/dist/index.d.ts +1 -0
  40. package/node_modules/@buddi/core/dist/index.d.ts.map +1 -1
  41. package/node_modules/@buddi/core/dist/index.js +1 -0
  42. package/node_modules/@buddi/core/dist/index.js.map +1 -1
  43. package/node_modules/@buddi/core/dist/plugin/index.d.ts +3 -0
  44. package/node_modules/@buddi/core/dist/plugin/index.d.ts.map +1 -1
  45. package/node_modules/@buddi/core/dist/plugin/index.js +3 -0
  46. package/node_modules/@buddi/core/dist/plugin/index.js.map +1 -1
  47. package/node_modules/@buddi/core/dist/plugin/version.d.ts +1 -1
  48. package/node_modules/@buddi/core/dist/plugin/version.js +1 -1
  49. package/node_modules/@buddi/core/dist/questions/store.d.ts +12 -0
  50. package/node_modules/@buddi/core/dist/questions/store.d.ts.map +1 -1
  51. package/node_modules/@buddi/core/dist/questions/store.js +11 -1
  52. package/node_modules/@buddi/core/dist/questions/store.js.map +1 -1
  53. package/node_modules/@buddi/core/dist/questions/types.d.ts +8 -0
  54. package/node_modules/@buddi/core/dist/questions/types.d.ts.map +1 -1
  55. package/node_modules/@buddi/core/dist/questions/types.js +15 -0
  56. package/node_modules/@buddi/core/dist/questions/types.js.map +1 -1
  57. package/node_modules/@buddi/core/dist/queue/jobs.d.ts +8 -0
  58. package/node_modules/@buddi/core/dist/queue/jobs.d.ts.map +1 -1
  59. package/node_modules/@buddi/core/dist/queue/jobs.js +9 -3
  60. package/node_modules/@buddi/core/dist/queue/jobs.js.map +1 -1
  61. package/node_modules/@buddi/core/dist/queue/worker.d.ts +2 -0
  62. package/node_modules/@buddi/core/dist/queue/worker.d.ts.map +1 -1
  63. package/node_modules/@buddi/core/dist/queue/worker.js +2 -1
  64. package/node_modules/@buddi/core/dist/queue/worker.js.map +1 -1
  65. package/node_modules/@buddi/core/dist/registry.d.ts +7 -1
  66. package/node_modules/@buddi/core/dist/registry.d.ts.map +1 -1
  67. package/node_modules/@buddi/core/dist/registry.js +73 -11
  68. package/node_modules/@buddi/core/dist/registry.js.map +1 -1
  69. package/node_modules/@buddi/core/dist/routes.d.ts +153 -0
  70. package/node_modules/@buddi/core/dist/routes.d.ts.map +1 -0
  71. package/node_modules/@buddi/core/dist/routes.js +47 -0
  72. package/node_modules/@buddi/core/dist/routes.js.map +1 -0
  73. package/node_modules/@buddi/core/dist/scheduler/missions.d.ts +5 -3
  74. package/node_modules/@buddi/core/dist/scheduler/missions.d.ts.map +1 -1
  75. package/node_modules/@buddi/core/dist/scheduler/missions.js +9 -7
  76. package/node_modules/@buddi/core/dist/scheduler/missions.js.map +1 -1
  77. package/node_modules/@buddi/core/dist/scheduler/types.d.ts +7 -0
  78. package/node_modules/@buddi/core/dist/scheduler/types.d.ts.map +1 -1
  79. package/node_modules/@buddi/core/dist/scheduler/types.js +1 -0
  80. package/node_modules/@buddi/core/dist/scheduler/types.js.map +1 -1
  81. package/node_modules/@buddi/core/dist/tools.d.ts +59 -2
  82. package/node_modules/@buddi/core/dist/tools.d.ts.map +1 -1
  83. package/node_modules/@buddi/core/dist/tools.js.map +1 -1
  84. package/node_modules/@buddi/core/migrations/075_access_providers.sql +43 -0
  85. package/node_modules/@buddi/core/migrations/076_mission_browser.sql +7 -0
  86. package/node_modules/@buddi/gateway/dist/.tsbuildinfo +1 -1
  87. package/node_modules/@buddi/gateway/dist/agents/canvas.d.ts +12 -12
  88. package/node_modules/@buddi/gateway/dist/agents/catalogue-package.d.ts +38 -20
  89. package/node_modules/@buddi/gateway/dist/agents/catalogue-package.d.ts.map +1 -1
  90. package/node_modules/@buddi/gateway/dist/agents/catalogue-package.js +6 -0
  91. package/node_modules/@buddi/gateway/dist/agents/catalogue-package.js.map +1 -1
  92. package/node_modules/@buddi/gateway/dist/agents/delegation.d.ts +10 -0
  93. package/node_modules/@buddi/gateway/dist/agents/delegation.d.ts.map +1 -1
  94. package/node_modules/@buddi/gateway/dist/agents/delegation.js +1 -0
  95. package/node_modules/@buddi/gateway/dist/agents/delegation.js.map +1 -1
  96. package/node_modules/@buddi/gateway/dist/agents/platform-catalogue.d.ts +7 -1
  97. package/node_modules/@buddi/gateway/dist/agents/platform-catalogue.d.ts.map +1 -1
  98. package/node_modules/@buddi/gateway/dist/agents/platform-catalogue.js +15 -6
  99. package/node_modules/@buddi/gateway/dist/agents/platform-catalogue.js.map +1 -1
  100. package/node_modules/@buddi/gateway/dist/bootstrap.d.ts.map +1 -1
  101. package/node_modules/@buddi/gateway/dist/bootstrap.js +8 -0
  102. package/node_modules/@buddi/gateway/dist/bootstrap.js.map +1 -1
  103. package/node_modules/@buddi/gateway/dist/browser-host.d.ts +30 -1
  104. package/node_modules/@buddi/gateway/dist/browser-host.d.ts.map +1 -1
  105. package/node_modules/@buddi/gateway/dist/browser-host.js +56 -1
  106. package/node_modules/@buddi/gateway/dist/browser-host.js.map +1 -1
  107. package/node_modules/@buddi/gateway/dist/chat/session.d.ts.map +1 -1
  108. package/node_modules/@buddi/gateway/dist/chat/session.js +9 -5
  109. package/node_modules/@buddi/gateway/dist/chat/session.js.map +1 -1
  110. package/node_modules/@buddi/gateway/dist/index.d.ts +2 -1
  111. package/node_modules/@buddi/gateway/dist/index.d.ts.map +1 -1
  112. package/node_modules/@buddi/gateway/dist/index.js +2 -1
  113. package/node_modules/@buddi/gateway/dist/index.js.map +1 -1
  114. package/node_modules/@buddi/gateway/dist/missions/execute.d.ts +34 -1
  115. package/node_modules/@buddi/gateway/dist/missions/execute.d.ts.map +1 -1
  116. package/node_modules/@buddi/gateway/dist/missions/execute.js +92 -8
  117. package/node_modules/@buddi/gateway/dist/missions/execute.js.map +1 -1
  118. package/node_modules/@buddi/gateway/dist/missions/parked.d.ts +133 -0
  119. package/node_modules/@buddi/gateway/dist/missions/parked.d.ts.map +1 -0
  120. package/node_modules/@buddi/gateway/dist/missions/parked.js +249 -0
  121. package/node_modules/@buddi/gateway/dist/missions/parked.js.map +1 -0
  122. package/node_modules/@buddi/gateway/dist/serve.d.ts +7 -0
  123. package/node_modules/@buddi/gateway/dist/serve.d.ts.map +1 -1
  124. package/node_modules/@buddi/gateway/dist/serve.js +49 -9
  125. package/node_modules/@buddi/gateway/dist/serve.js.map +1 -1
  126. package/node_modules/@buddi/gateway/dist/surfaces/browser-cards.d.ts +18 -0
  127. package/node_modules/@buddi/gateway/dist/surfaces/browser-cards.d.ts.map +1 -0
  128. package/node_modules/@buddi/gateway/dist/surfaces/browser-cards.js +42 -0
  129. package/node_modules/@buddi/gateway/dist/surfaces/browser-cards.js.map +1 -0
  130. package/node_modules/@buddi/gateway/dist/surfaces/browser-continuation.js +1 -1
  131. package/node_modules/@buddi/gateway/dist/surfaces/browser-continuation.js.map +1 -1
  132. package/node_modules/@buddi/gateway/dist/surfaces/owner-request.d.ts +6 -0
  133. package/node_modules/@buddi/gateway/dist/surfaces/owner-request.d.ts.map +1 -1
  134. package/node_modules/@buddi/gateway/dist/surfaces/owner-request.js +7 -1
  135. package/node_modules/@buddi/gateway/dist/surfaces/owner-request.js.map +1 -1
  136. package/node_modules/@buddi/gateway/dist/system-context.d.ts.map +1 -1
  137. package/node_modules/@buddi/gateway/dist/system-context.js +6 -7
  138. package/node_modules/@buddi/gateway/dist/system-context.js.map +1 -1
  139. package/node_modules/@buddi/gateway/dist/telegram/browser-view.d.ts +17 -17
  140. package/node_modules/@buddi/gateway/dist/telegram/browser-view.d.ts.map +1 -1
  141. package/node_modules/@buddi/gateway/dist/telegram/browser-view.js +33 -37
  142. package/node_modules/@buddi/gateway/dist/telegram/browser-view.js.map +1 -1
  143. package/node_modules/@buddi/gateway/dist/telegram/channel.d.ts.map +1 -1
  144. package/node_modules/@buddi/gateway/dist/telegram/channel.js +17 -1
  145. package/node_modules/@buddi/gateway/dist/telegram/channel.js.map +1 -1
  146. package/node_modules/@buddi/gateway/dist/telegram/main.d.ts.map +1 -1
  147. package/node_modules/@buddi/gateway/dist/telegram/main.js +11 -3
  148. package/node_modules/@buddi/gateway/dist/telegram/main.js.map +1 -1
  149. package/node_modules/@buddi/gateway/dist/telegram/surface.d.ts.map +1 -1
  150. package/node_modules/@buddi/gateway/dist/telegram/surface.js +10 -0
  151. package/node_modules/@buddi/gateway/dist/telegram/surface.js.map +1 -1
  152. package/node_modules/@buddi/gateway/dist/tips/facts.d.ts +8 -0
  153. package/node_modules/@buddi/gateway/dist/tips/facts.d.ts.map +1 -1
  154. package/node_modules/@buddi/gateway/dist/tips/facts.js +8 -2
  155. package/node_modules/@buddi/gateway/dist/tips/facts.js.map +1 -1
  156. package/node_modules/@buddi/gateway/dist/tips/rules.d.ts +2 -0
  157. package/node_modules/@buddi/gateway/dist/tips/rules.d.ts.map +1 -1
  158. package/node_modules/@buddi/gateway/dist/tips/rules.js +15 -0
  159. package/node_modules/@buddi/gateway/dist/tips/rules.js.map +1 -1
  160. package/node_modules/@buddi/gateway/dist/web/access/arrival.d.ts +24 -0
  161. package/node_modules/@buddi/gateway/dist/web/access/arrival.d.ts.map +1 -0
  162. package/node_modules/@buddi/gateway/dist/web/access/arrival.js +18 -0
  163. package/node_modules/@buddi/gateway/dist/web/access/arrival.js.map +1 -0
  164. package/node_modules/@buddi/gateway/dist/web/access/cloudflare-api.d.ts +124 -0
  165. package/node_modules/@buddi/gateway/dist/web/access/cloudflare-api.d.ts.map +1 -0
  166. package/node_modules/@buddi/gateway/dist/web/access/cloudflare-api.js +206 -0
  167. package/node_modules/@buddi/gateway/dist/web/access/cloudflare-api.js.map +1 -0
  168. package/node_modules/@buddi/gateway/dist/web/access/cloudflare-setup.d.ts +163 -0
  169. package/node_modules/@buddi/gateway/dist/web/access/cloudflare-setup.d.ts.map +1 -0
  170. package/node_modules/@buddi/gateway/dist/web/access/cloudflare-setup.js +438 -0
  171. package/node_modules/@buddi/gateway/dist/web/access/cloudflare-setup.js.map +1 -0
  172. package/node_modules/@buddi/gateway/dist/web/access/cloudflare-token.d.ts +31 -0
  173. package/node_modules/@buddi/gateway/dist/web/access/cloudflare-token.d.ts.map +1 -0
  174. package/node_modules/@buddi/gateway/dist/web/access/cloudflare-token.js +74 -0
  175. package/node_modules/@buddi/gateway/dist/web/access/cloudflare-token.js.map +1 -0
  176. package/node_modules/@buddi/gateway/dist/web/access/cloudflare.d.ts +145 -0
  177. package/node_modules/@buddi/gateway/dist/web/access/cloudflare.d.ts.map +1 -0
  178. package/node_modules/@buddi/gateway/dist/web/access/cloudflare.js +474 -0
  179. package/node_modules/@buddi/gateway/dist/web/access/cloudflare.js.map +1 -0
  180. package/node_modules/@buddi/gateway/dist/web/access/index.d.ts +9 -0
  181. package/node_modules/@buddi/gateway/dist/web/access/index.d.ts.map +1 -0
  182. package/node_modules/@buddi/gateway/dist/web/access/index.js +9 -0
  183. package/node_modules/@buddi/gateway/dist/web/access/index.js.map +1 -0
  184. package/node_modules/@buddi/gateway/dist/web/access/ingress.d.ts +30 -0
  185. package/node_modules/@buddi/gateway/dist/web/access/ingress.d.ts.map +1 -0
  186. package/node_modules/@buddi/gateway/dist/web/access/ingress.js +76 -0
  187. package/node_modules/@buddi/gateway/dist/web/access/ingress.js.map +1 -0
  188. package/node_modules/@buddi/gateway/dist/web/access/provider.d.ts +173 -0
  189. package/node_modules/@buddi/gateway/dist/web/access/provider.d.ts.map +1 -0
  190. package/node_modules/@buddi/gateway/dist/web/access/provider.js +11 -0
  191. package/node_modules/@buddi/gateway/dist/web/access/provider.js.map +1 -0
  192. package/node_modules/@buddi/gateway/dist/web/access/registry.d.ts +33 -0
  193. package/node_modules/@buddi/gateway/dist/web/access/registry.d.ts.map +1 -0
  194. package/node_modules/@buddi/gateway/dist/web/access/registry.js +32 -0
  195. package/node_modules/@buddi/gateway/dist/web/access/registry.js.map +1 -0
  196. package/node_modules/@buddi/gateway/dist/web/{tailscale.d.ts → access/tailscale.d.ts} +27 -0
  197. package/node_modules/@buddi/gateway/dist/web/access/tailscale.d.ts.map +1 -0
  198. package/node_modules/@buddi/gateway/dist/web/{tailscale.js → access/tailscale.js} +118 -3
  199. package/node_modules/@buddi/gateway/dist/web/access/tailscale.js.map +1 -0
  200. package/node_modules/@buddi/gateway/dist/web/agents.d.ts +2 -0
  201. package/node_modules/@buddi/gateway/dist/web/agents.d.ts.map +1 -1
  202. package/node_modules/@buddi/gateway/dist/web/agents.js +19 -1
  203. package/node_modules/@buddi/gateway/dist/web/agents.js.map +1 -1
  204. package/node_modules/@buddi/gateway/dist/web/api-routes.d.ts +4 -3
  205. package/node_modules/@buddi/gateway/dist/web/api-routes.d.ts.map +1 -1
  206. package/node_modules/@buddi/gateway/dist/web/api-routes.js +96 -17
  207. package/node_modules/@buddi/gateway/dist/web/api-routes.js.map +1 -1
  208. package/node_modules/@buddi/gateway/dist/web/attention.d.ts.map +1 -1
  209. package/node_modules/@buddi/gateway/dist/web/attention.js +11 -3
  210. package/node_modules/@buddi/gateway/dist/web/attention.js.map +1 -1
  211. package/node_modules/@buddi/gateway/dist/web/chat.d.ts +23 -0
  212. package/node_modules/@buddi/gateway/dist/web/chat.d.ts.map +1 -1
  213. package/node_modules/@buddi/gateway/dist/web/chat.js +62 -2
  214. package/node_modules/@buddi/gateway/dist/web/chat.js.map +1 -1
  215. package/node_modules/@buddi/gateway/dist/web/client-key.d.ts +3 -0
  216. package/node_modules/@buddi/gateway/dist/web/client-key.d.ts.map +1 -1
  217. package/node_modules/@buddi/gateway/dist/web/client-key.js +8 -1
  218. package/node_modules/@buddi/gateway/dist/web/client-key.js.map +1 -1
  219. package/node_modules/@buddi/gateway/dist/web/extension.d.ts +9 -1
  220. package/node_modules/@buddi/gateway/dist/web/extension.d.ts.map +1 -1
  221. package/node_modules/@buddi/gateway/dist/web/extension.js +61 -1
  222. package/node_modules/@buddi/gateway/dist/web/extension.js.map +1 -1
  223. package/node_modules/@buddi/gateway/dist/web/http.d.ts +7 -0
  224. package/node_modules/@buddi/gateway/dist/web/http.d.ts.map +1 -1
  225. package/node_modules/@buddi/gateway/dist/web/http.js +15 -1
  226. package/node_modules/@buddi/gateway/dist/web/http.js.map +1 -1
  227. package/node_modules/@buddi/gateway/dist/web/index.d.ts +1 -1
  228. package/node_modules/@buddi/gateway/dist/web/index.d.ts.map +1 -1
  229. package/node_modules/@buddi/gateway/dist/web/index.js +1 -1
  230. package/node_modules/@buddi/gateway/dist/web/index.js.map +1 -1
  231. package/node_modules/@buddi/gateway/dist/web/onboarding.js +1 -1
  232. package/node_modules/@buddi/gateway/dist/web/onboarding.js.map +1 -1
  233. package/node_modules/@buddi/gateway/dist/web/server.d.ts +38 -2
  234. package/node_modules/@buddi/gateway/dist/web/server.d.ts.map +1 -1
  235. package/node_modules/@buddi/gateway/dist/web/server.js +576 -145
  236. package/node_modules/@buddi/gateway/dist/web/server.js.map +1 -1
  237. package/node_modules/@buddi/gateway/dist/web/sessions.d.ts +24 -14
  238. package/node_modules/@buddi/gateway/dist/web/sessions.d.ts.map +1 -1
  239. package/node_modules/@buddi/gateway/dist/web/sessions.js +42 -14
  240. package/node_modules/@buddi/gateway/dist/web/sessions.js.map +1 -1
  241. package/node_modules/@buddi/gateway/dist/web/signed-out.d.ts +10 -0
  242. package/node_modules/@buddi/gateway/dist/web/signed-out.d.ts.map +1 -1
  243. package/node_modules/@buddi/gateway/dist/web/signed-out.js +47 -0
  244. package/node_modules/@buddi/gateway/dist/web/signed-out.js.map +1 -1
  245. package/node_modules/@buddi/install/dist/.tsbuildinfo +1 -1
  246. package/node_modules/@buddi/runtime/dist/.tsbuildinfo +1 -1
  247. package/node_modules/@buddi/runtime/dist/delegate.d.ts +8 -0
  248. package/node_modules/@buddi/runtime/dist/delegate.d.ts.map +1 -1
  249. package/node_modules/@buddi/runtime/dist/delegate.js +19 -1
  250. package/node_modules/@buddi/runtime/dist/delegate.js.map +1 -1
  251. package/node_modules/@buddi/runtime/dist/loop.d.ts +2 -0
  252. package/node_modules/@buddi/runtime/dist/loop.d.ts.map +1 -1
  253. package/node_modules/@buddi/runtime/dist/loop.js +18 -4
  254. package/node_modules/@buddi/runtime/dist/loop.js.map +1 -1
  255. package/node_modules/@buddi/tool-artifacts/dist/.tsbuildinfo +1 -1
  256. package/node_modules/@buddi/tool-browser/dist/.tsbuildinfo +1 -1
  257. package/node_modules/@buddi/tool-browser/dist/availability.d.ts +2 -2
  258. package/node_modules/@buddi/tool-browser/dist/availability.d.ts.map +1 -1
  259. package/node_modules/@buddi/tool-browser/dist/availability.js +2 -2
  260. package/node_modules/@buddi/tool-browser/dist/availability.js.map +1 -1
  261. package/node_modules/@buddi/tool-browser/dist/controller.d.ts +76 -58
  262. package/node_modules/@buddi/tool-browser/dist/controller.d.ts.map +1 -1
  263. package/node_modules/@buddi/tool-browser/dist/controller.js +751 -219
  264. package/node_modules/@buddi/tool-browser/dist/controller.js.map +1 -1
  265. package/node_modules/@buddi/tool-browser/dist/extension.d.ts +12 -0
  266. package/node_modules/@buddi/tool-browser/dist/extension.d.ts.map +1 -1
  267. package/node_modules/@buddi/tool-browser/dist/extension.js +8 -0
  268. package/node_modules/@buddi/tool-browser/dist/extension.js.map +1 -1
  269. package/node_modules/@buddi/tool-browser/dist/index.d.ts +13 -5
  270. package/node_modules/@buddi/tool-browser/dist/index.d.ts.map +1 -1
  271. package/node_modules/@buddi/tool-browser/dist/index.js +29 -12
  272. package/node_modules/@buddi/tool-browser/dist/index.js.map +1 -1
  273. package/node_modules/@buddi/tool-browser/dist/manager.d.ts +39 -21
  274. package/node_modules/@buddi/tool-browser/dist/manager.d.ts.map +1 -1
  275. package/node_modules/@buddi/tool-browser/dist/manager.js +229 -136
  276. package/node_modules/@buddi/tool-browser/dist/manager.js.map +1 -1
  277. package/node_modules/@buddi/tool-browser/dist/routes.d.ts +130 -0
  278. package/node_modules/@buddi/tool-browser/dist/routes.d.ts.map +1 -0
  279. package/node_modules/@buddi/tool-browser/dist/routes.js +283 -0
  280. package/node_modules/@buddi/tool-browser/dist/routes.js.map +1 -0
  281. package/node_modules/@buddi/tool-browser/dist/service.d.ts +157 -114
  282. package/node_modules/@buddi/tool-browser/dist/service.d.ts.map +1 -1
  283. package/node_modules/@buddi/tool-browser/dist/service.js +379 -390
  284. package/node_modules/@buddi/tool-browser/dist/service.js.map +1 -1
  285. package/node_modules/@buddi/tool-browser/dist/settings.d.ts +88 -0
  286. package/node_modules/@buddi/tool-browser/dist/settings.d.ts.map +1 -0
  287. package/node_modules/@buddi/tool-browser/dist/settings.js +86 -0
  288. package/node_modules/@buddi/tool-browser/dist/settings.js.map +1 -0
  289. package/node_modules/@buddi/tool-browser/dist/telemetry.d.ts +203 -0
  290. package/node_modules/@buddi/tool-browser/dist/telemetry.d.ts.map +1 -0
  291. package/node_modules/@buddi/tool-browser/dist/telemetry.js +142 -0
  292. package/node_modules/@buddi/tool-browser/dist/telemetry.js.map +1 -0
  293. package/node_modules/@buddi/tool-browser/dist/types.d.ts +14 -3
  294. package/node_modules/@buddi/tool-browser/dist/types.d.ts.map +1 -1
  295. package/node_modules/@buddi/tool-browser/dist/types.js +9 -9
  296. package/node_modules/@buddi/tool-browser/dist/types.js.map +1 -1
  297. package/node_modules/@buddi/tool-email/dist/.tsbuildinfo +1 -1
  298. package/node_modules/@buddi/tool-host/dist/.tsbuildinfo +1 -1
  299. package/node_modules/@buddi/tool-mcp/dist/.tsbuildinfo +1 -1
  300. package/node_modules/@buddi/tool-memory/dist/.tsbuildinfo +1 -1
  301. package/node_modules/@buddi/tool-web/dist/.tsbuildinfo +1 -1
  302. package/node_modules/imapflow/CHANGELOG.md +15 -0
  303. package/node_modules/imapflow/dist/cjs/package-info.d.ts +1 -1
  304. package/node_modules/imapflow/dist/cjs/package-info.js +1 -1
  305. package/node_modules/imapflow/dist/cjs/search-compiler.js +21 -31
  306. package/node_modules/imapflow/dist/esm/package-info.d.ts +1 -1
  307. package/node_modules/imapflow/dist/esm/package-info.js +1 -1
  308. package/node_modules/imapflow/dist/esm/search-compiler.js +21 -31
  309. package/node_modules/imapflow/package.json +2 -2
  310. package/node_modules/pino/CONTRIBUTING.md +1 -5
  311. package/node_modules/pino/LICENSE +1 -1
  312. package/node_modules/pino/README.md +1 -1
  313. package/node_modules/pino/SECURITY.md +2 -18
  314. package/node_modules/pino/browser.js +8 -68
  315. package/node_modules/pino/docs/api.md +4 -75
  316. package/node_modules/pino/docs/asynchronous.md +3 -18
  317. package/node_modules/pino/docs/browser.md +0 -63
  318. package/node_modules/pino/docs/child-loggers.md +1 -22
  319. package/node_modules/pino/docs/ecosystem.md +0 -1
  320. package/node_modules/pino/docs/help.md +3 -11
  321. package/node_modules/pino/docs/lts.md +0 -29
  322. package/node_modules/pino/docs/pretty.md +0 -3
  323. package/node_modules/pino/docs/redaction.md +8 -3
  324. package/node_modules/pino/docs/transports.md +0 -71
  325. package/node_modules/pino/docs/web.md +14 -11
  326. package/node_modules/pino/eslint.config.js +7 -15
  327. package/node_modules/pino/lib/caller.js +0 -10
  328. package/node_modules/pino/lib/meta.js +1 -1
  329. package/node_modules/pino/lib/multistream.js +7 -15
  330. package/node_modules/pino/lib/redaction.js +3 -8
  331. package/node_modules/pino/lib/symbols.js +1 -3
  332. package/node_modules/pino/lib/tools.js +2 -2
  333. package/node_modules/pino/lib/transport.js +1 -14
  334. package/node_modules/pino/lib/worker.js +1 -4
  335. package/node_modules/pino/package.json +22 -14
  336. package/node_modules/pino/pino.d.ts +736 -709
  337. package/node_modules/pino/pino.js +2 -27
  338. package/node_modules/pino/test/basic.test.js +0 -66
  339. package/node_modules/pino/test/escaping.test.js +0 -17
  340. package/node_modules/pino/test/fixtures/ts/transpile.cjs +3 -3
  341. package/node_modules/pino/test/helper.js +2 -6
  342. package/node_modules/pino/test/multistream.test.js +0 -64
  343. package/node_modules/pino/test/redact.test.js +0 -30
  344. package/node_modules/pino/test/transport/core.test.js +0 -85
  345. package/node_modules/pino/test/transport/sync-false.test.js +0 -12
  346. package/node_modules/pino/test/transport/uses-pino-config.test.js +4 -4
  347. package/node_modules/pino/test/types/pino-import.test-d.cts +30 -0
  348. package/node_modules/pino/test/types/pino-multistream.test-d.ts +28 -0
  349. package/node_modules/pino/test/types/pino-top-export.test-d.ts +34 -0
  350. package/node_modules/pino/test/types/{pino-transport.tst.ts → pino-transport.test-d.ts} +70 -85
  351. package/node_modules/pino/test/types/pino-type-only.test-d.ts +75 -0
  352. package/node_modules/pino/test/types/{pino.tst.ts → pino.test-d.ts} +137 -135
  353. package/node_modules/pino/test/types/pino.ts +7 -14
  354. package/node_modules/pino/tsconfig.json +6 -6
  355. package/node_modules/real-require/README.md +6 -6
  356. package/node_modules/real-require/package.json +21 -10
  357. package/node_modules/real-require/src/index.js +2 -2
  358. package/node_modules/thread-stream/node_modules/real-require/LICENSE.md +21 -0
  359. package/node_modules/thread-stream/node_modules/real-require/README.md +51 -0
  360. package/node_modules/thread-stream/node_modules/real-require/package.json +38 -0
  361. package/node_modules/thread-stream/node_modules/real-require/src/index.js +14 -0
  362. package/package.json +2 -2
  363. package/packages/cli/dist/.tsbuildinfo +1 -1
  364. package/packages/cli/dist/access-cmd.d.ts +10 -0
  365. package/packages/cli/dist/access-cmd.d.ts.map +1 -0
  366. package/packages/cli/dist/access-cmd.js +160 -0
  367. package/packages/cli/dist/access-cmd.js.map +1 -0
  368. package/packages/cli/dist/args.d.ts +10 -0
  369. package/packages/cli/dist/args.d.ts.map +1 -1
  370. package/packages/cli/dist/args.js +29 -1
  371. package/packages/cli/dist/args.js.map +1 -1
  372. package/packages/cli/dist/commands.d.ts.map +1 -1
  373. package/packages/cli/dist/commands.js +28 -2
  374. package/packages/cli/dist/commands.js.map +1 -1
  375. package/packages/cli/dist/doctor-probes.d.ts.map +1 -1
  376. package/packages/cli/dist/doctor-probes.js +54 -29
  377. package/packages/cli/dist/doctor-probes.js.map +1 -1
  378. package/packages/cli/dist/doctor.d.ts +36 -12
  379. package/packages/cli/dist/doctor.d.ts.map +1 -1
  380. package/packages/cli/dist/doctor.js +32 -9
  381. package/packages/cli/dist/doctor.js.map +1 -1
  382. package/packages/cli/dist/main.d.ts +2 -0
  383. package/packages/cli/dist/main.d.ts.map +1 -1
  384. package/packages/cli/dist/main.js +18 -1
  385. package/packages/cli/dist/main.js.map +1 -1
  386. package/packages/core/dist/.tsbuildinfo +1 -1
  387. package/packages/core/dist/agents/catalog.d.ts +2 -0
  388. package/packages/core/dist/agents/catalog.d.ts.map +1 -1
  389. package/packages/core/dist/agents/catalog.js +1 -0
  390. package/packages/core/dist/agents/catalog.js.map +1 -1
  391. package/packages/core/dist/agents/edit.d.ts +2 -0
  392. package/packages/core/dist/agents/edit.d.ts.map +1 -1
  393. package/packages/core/dist/agents/edit.js +3 -1
  394. package/packages/core/dist/agents/edit.js.map +1 -1
  395. package/packages/core/dist/agents/frontmatter.d.ts +11 -0
  396. package/packages/core/dist/agents/frontmatter.d.ts.map +1 -1
  397. package/packages/core/dist/agents/frontmatter.js +7 -0
  398. package/packages/core/dist/agents/frontmatter.js.map +1 -1
  399. package/packages/core/dist/index.d.ts +1 -0
  400. package/packages/core/dist/index.d.ts.map +1 -1
  401. package/packages/core/dist/index.js +1 -0
  402. package/packages/core/dist/index.js.map +1 -1
  403. package/packages/core/dist/plugin/index.d.ts +3 -0
  404. package/packages/core/dist/plugin/index.d.ts.map +1 -1
  405. package/packages/core/dist/plugin/index.js +3 -0
  406. package/packages/core/dist/plugin/index.js.map +1 -1
  407. package/packages/core/dist/plugin/version.d.ts +1 -1
  408. package/packages/core/dist/plugin/version.js +1 -1
  409. package/packages/core/dist/questions/store.d.ts +12 -0
  410. package/packages/core/dist/questions/store.d.ts.map +1 -1
  411. package/packages/core/dist/questions/store.js +11 -1
  412. package/packages/core/dist/questions/store.js.map +1 -1
  413. package/packages/core/dist/questions/types.d.ts +8 -0
  414. package/packages/core/dist/questions/types.d.ts.map +1 -1
  415. package/packages/core/dist/questions/types.js +15 -0
  416. package/packages/core/dist/questions/types.js.map +1 -1
  417. package/packages/core/dist/queue/jobs.d.ts +8 -0
  418. package/packages/core/dist/queue/jobs.d.ts.map +1 -1
  419. package/packages/core/dist/queue/jobs.js +9 -3
  420. package/packages/core/dist/queue/jobs.js.map +1 -1
  421. package/packages/core/dist/queue/worker.d.ts +2 -0
  422. package/packages/core/dist/queue/worker.d.ts.map +1 -1
  423. package/packages/core/dist/queue/worker.js +2 -1
  424. package/packages/core/dist/queue/worker.js.map +1 -1
  425. package/packages/core/dist/registry.d.ts +7 -1
  426. package/packages/core/dist/registry.d.ts.map +1 -1
  427. package/packages/core/dist/registry.js +73 -11
  428. package/packages/core/dist/registry.js.map +1 -1
  429. package/packages/core/dist/routes.d.ts +153 -0
  430. package/packages/core/dist/routes.d.ts.map +1 -0
  431. package/packages/core/dist/routes.js +47 -0
  432. package/packages/core/dist/routes.js.map +1 -0
  433. package/packages/core/dist/scheduler/missions.d.ts +5 -3
  434. package/packages/core/dist/scheduler/missions.d.ts.map +1 -1
  435. package/packages/core/dist/scheduler/missions.js +9 -7
  436. package/packages/core/dist/scheduler/missions.js.map +1 -1
  437. package/packages/core/dist/scheduler/types.d.ts +7 -0
  438. package/packages/core/dist/scheduler/types.d.ts.map +1 -1
  439. package/packages/core/dist/scheduler/types.js +1 -0
  440. package/packages/core/dist/scheduler/types.js.map +1 -1
  441. package/packages/core/dist/tools.d.ts +59 -2
  442. package/packages/core/dist/tools.d.ts.map +1 -1
  443. package/packages/core/dist/tools.js.map +1 -1
  444. package/packages/core/migrations/075_access_providers.sql +43 -0
  445. package/packages/core/migrations/076_mission_browser.sql +7 -0
  446. package/packages/gateway/dist/.tsbuildinfo +1 -1
  447. package/packages/gateway/dist/agents/canvas.d.ts +12 -12
  448. package/packages/gateway/dist/agents/catalogue-package.d.ts +38 -20
  449. package/packages/gateway/dist/agents/catalogue-package.d.ts.map +1 -1
  450. package/packages/gateway/dist/agents/catalogue-package.js +6 -0
  451. package/packages/gateway/dist/agents/catalogue-package.js.map +1 -1
  452. package/packages/gateway/dist/agents/delegation.d.ts +10 -0
  453. package/packages/gateway/dist/agents/delegation.d.ts.map +1 -1
  454. package/packages/gateway/dist/agents/delegation.js +1 -0
  455. package/packages/gateway/dist/agents/delegation.js.map +1 -1
  456. package/packages/gateway/dist/agents/platform-catalogue.d.ts +7 -1
  457. package/packages/gateway/dist/agents/platform-catalogue.d.ts.map +1 -1
  458. package/packages/gateway/dist/agents/platform-catalogue.js +15 -6
  459. package/packages/gateway/dist/agents/platform-catalogue.js.map +1 -1
  460. package/packages/gateway/dist/bootstrap.d.ts.map +1 -1
  461. package/packages/gateway/dist/bootstrap.js +8 -0
  462. package/packages/gateway/dist/bootstrap.js.map +1 -1
  463. package/packages/gateway/dist/browser-host.d.ts +30 -1
  464. package/packages/gateway/dist/browser-host.d.ts.map +1 -1
  465. package/packages/gateway/dist/browser-host.js +56 -1
  466. package/packages/gateway/dist/browser-host.js.map +1 -1
  467. package/packages/gateway/dist/chat/session.d.ts.map +1 -1
  468. package/packages/gateway/dist/chat/session.js +9 -5
  469. package/packages/gateway/dist/chat/session.js.map +1 -1
  470. package/packages/gateway/dist/index.d.ts +2 -1
  471. package/packages/gateway/dist/index.d.ts.map +1 -1
  472. package/packages/gateway/dist/index.js +2 -1
  473. package/packages/gateway/dist/index.js.map +1 -1
  474. package/packages/gateway/dist/missions/execute.d.ts +34 -1
  475. package/packages/gateway/dist/missions/execute.d.ts.map +1 -1
  476. package/packages/gateway/dist/missions/execute.js +92 -8
  477. package/packages/gateway/dist/missions/execute.js.map +1 -1
  478. package/packages/gateway/dist/missions/parked.d.ts +133 -0
  479. package/packages/gateway/dist/missions/parked.d.ts.map +1 -0
  480. package/packages/gateway/dist/missions/parked.js +249 -0
  481. package/packages/gateway/dist/missions/parked.js.map +1 -0
  482. package/packages/gateway/dist/serve.d.ts +7 -0
  483. package/packages/gateway/dist/serve.d.ts.map +1 -1
  484. package/packages/gateway/dist/serve.js +49 -9
  485. package/packages/gateway/dist/serve.js.map +1 -1
  486. package/packages/gateway/dist/surfaces/browser-cards.d.ts +18 -0
  487. package/packages/gateway/dist/surfaces/browser-cards.d.ts.map +1 -0
  488. package/packages/gateway/dist/surfaces/browser-cards.js +42 -0
  489. package/packages/gateway/dist/surfaces/browser-cards.js.map +1 -0
  490. package/packages/gateway/dist/surfaces/browser-continuation.js +1 -1
  491. package/packages/gateway/dist/surfaces/browser-continuation.js.map +1 -1
  492. package/packages/gateway/dist/surfaces/owner-request.d.ts +6 -0
  493. package/packages/gateway/dist/surfaces/owner-request.d.ts.map +1 -1
  494. package/packages/gateway/dist/surfaces/owner-request.js +7 -1
  495. package/packages/gateway/dist/surfaces/owner-request.js.map +1 -1
  496. package/packages/gateway/dist/system-context.d.ts.map +1 -1
  497. package/packages/gateway/dist/system-context.js +6 -7
  498. package/packages/gateway/dist/system-context.js.map +1 -1
  499. package/packages/gateway/dist/telegram/browser-view.d.ts +17 -17
  500. package/packages/gateway/dist/telegram/browser-view.d.ts.map +1 -1
  501. package/packages/gateway/dist/telegram/browser-view.js +33 -37
  502. package/packages/gateway/dist/telegram/browser-view.js.map +1 -1
  503. package/packages/gateway/dist/telegram/channel.d.ts.map +1 -1
  504. package/packages/gateway/dist/telegram/channel.js +17 -1
  505. package/packages/gateway/dist/telegram/channel.js.map +1 -1
  506. package/packages/gateway/dist/telegram/main.d.ts.map +1 -1
  507. package/packages/gateway/dist/telegram/main.js +11 -3
  508. package/packages/gateway/dist/telegram/main.js.map +1 -1
  509. package/packages/gateway/dist/telegram/surface.d.ts.map +1 -1
  510. package/packages/gateway/dist/telegram/surface.js +10 -0
  511. package/packages/gateway/dist/telegram/surface.js.map +1 -1
  512. package/packages/gateway/dist/tips/facts.d.ts +8 -0
  513. package/packages/gateway/dist/tips/facts.d.ts.map +1 -1
  514. package/packages/gateway/dist/tips/facts.js +8 -2
  515. package/packages/gateway/dist/tips/facts.js.map +1 -1
  516. package/packages/gateway/dist/tips/rules.d.ts +2 -0
  517. package/packages/gateway/dist/tips/rules.d.ts.map +1 -1
  518. package/packages/gateway/dist/tips/rules.js +15 -0
  519. package/packages/gateway/dist/tips/rules.js.map +1 -1
  520. package/packages/gateway/dist/web/access/arrival.d.ts +24 -0
  521. package/packages/gateway/dist/web/access/arrival.d.ts.map +1 -0
  522. package/packages/gateway/dist/web/access/arrival.js +18 -0
  523. package/packages/gateway/dist/web/access/arrival.js.map +1 -0
  524. package/packages/gateway/dist/web/access/cloudflare-api.d.ts +124 -0
  525. package/packages/gateway/dist/web/access/cloudflare-api.d.ts.map +1 -0
  526. package/packages/gateway/dist/web/access/cloudflare-api.js +206 -0
  527. package/packages/gateway/dist/web/access/cloudflare-api.js.map +1 -0
  528. package/packages/gateway/dist/web/access/cloudflare-setup.d.ts +163 -0
  529. package/packages/gateway/dist/web/access/cloudflare-setup.d.ts.map +1 -0
  530. package/packages/gateway/dist/web/access/cloudflare-setup.js +438 -0
  531. package/packages/gateway/dist/web/access/cloudflare-setup.js.map +1 -0
  532. package/packages/gateway/dist/web/access/cloudflare-token.d.ts +31 -0
  533. package/packages/gateway/dist/web/access/cloudflare-token.d.ts.map +1 -0
  534. package/packages/gateway/dist/web/access/cloudflare-token.js +74 -0
  535. package/packages/gateway/dist/web/access/cloudflare-token.js.map +1 -0
  536. package/packages/gateway/dist/web/access/cloudflare.d.ts +145 -0
  537. package/packages/gateway/dist/web/access/cloudflare.d.ts.map +1 -0
  538. package/packages/gateway/dist/web/access/cloudflare.js +474 -0
  539. package/packages/gateway/dist/web/access/cloudflare.js.map +1 -0
  540. package/packages/gateway/dist/web/access/index.d.ts +9 -0
  541. package/packages/gateway/dist/web/access/index.d.ts.map +1 -0
  542. package/packages/gateway/dist/web/access/index.js +9 -0
  543. package/packages/gateway/dist/web/access/index.js.map +1 -0
  544. package/packages/gateway/dist/web/access/ingress.d.ts +30 -0
  545. package/packages/gateway/dist/web/access/ingress.d.ts.map +1 -0
  546. package/packages/gateway/dist/web/access/ingress.js +76 -0
  547. package/packages/gateway/dist/web/access/ingress.js.map +1 -0
  548. package/packages/gateway/dist/web/access/provider.d.ts +173 -0
  549. package/packages/gateway/dist/web/access/provider.d.ts.map +1 -0
  550. package/packages/gateway/dist/web/access/provider.js +11 -0
  551. package/packages/gateway/dist/web/access/provider.js.map +1 -0
  552. package/packages/gateway/dist/web/access/registry.d.ts +33 -0
  553. package/packages/gateway/dist/web/access/registry.d.ts.map +1 -0
  554. package/packages/gateway/dist/web/access/registry.js +32 -0
  555. package/packages/gateway/dist/web/access/registry.js.map +1 -0
  556. package/packages/gateway/dist/web/{tailscale.d.ts → access/tailscale.d.ts} +27 -0
  557. package/packages/gateway/dist/web/access/tailscale.d.ts.map +1 -0
  558. package/packages/gateway/dist/web/{tailscale.js → access/tailscale.js} +118 -3
  559. package/packages/gateway/dist/web/access/tailscale.js.map +1 -0
  560. package/packages/gateway/dist/web/agents.d.ts +2 -0
  561. package/packages/gateway/dist/web/agents.d.ts.map +1 -1
  562. package/packages/gateway/dist/web/agents.js +19 -1
  563. package/packages/gateway/dist/web/agents.js.map +1 -1
  564. package/packages/gateway/dist/web/api-routes.d.ts +4 -3
  565. package/packages/gateway/dist/web/api-routes.d.ts.map +1 -1
  566. package/packages/gateway/dist/web/api-routes.js +96 -17
  567. package/packages/gateway/dist/web/api-routes.js.map +1 -1
  568. package/packages/gateway/dist/web/attention.d.ts.map +1 -1
  569. package/packages/gateway/dist/web/attention.js +11 -3
  570. package/packages/gateway/dist/web/attention.js.map +1 -1
  571. package/packages/gateway/dist/web/chat.d.ts +23 -0
  572. package/packages/gateway/dist/web/chat.d.ts.map +1 -1
  573. package/packages/gateway/dist/web/chat.js +62 -2
  574. package/packages/gateway/dist/web/chat.js.map +1 -1
  575. package/packages/gateway/dist/web/client-key.d.ts +3 -0
  576. package/packages/gateway/dist/web/client-key.d.ts.map +1 -1
  577. package/packages/gateway/dist/web/client-key.js +8 -1
  578. package/packages/gateway/dist/web/client-key.js.map +1 -1
  579. package/packages/gateway/dist/web/extension.d.ts +9 -1
  580. package/packages/gateway/dist/web/extension.d.ts.map +1 -1
  581. package/packages/gateway/dist/web/extension.js +61 -1
  582. package/packages/gateway/dist/web/extension.js.map +1 -1
  583. package/packages/gateway/dist/web/http.d.ts +7 -0
  584. package/packages/gateway/dist/web/http.d.ts.map +1 -1
  585. package/packages/gateway/dist/web/http.js +15 -1
  586. package/packages/gateway/dist/web/http.js.map +1 -1
  587. package/packages/gateway/dist/web/index.d.ts +1 -1
  588. package/packages/gateway/dist/web/index.d.ts.map +1 -1
  589. package/packages/gateway/dist/web/index.js +1 -1
  590. package/packages/gateway/dist/web/index.js.map +1 -1
  591. package/packages/gateway/dist/web/onboarding.js +1 -1
  592. package/packages/gateway/dist/web/onboarding.js.map +1 -1
  593. package/packages/gateway/dist/web/server.d.ts +38 -2
  594. package/packages/gateway/dist/web/server.d.ts.map +1 -1
  595. package/packages/gateway/dist/web/server.js +576 -145
  596. package/packages/gateway/dist/web/server.js.map +1 -1
  597. package/packages/gateway/dist/web/sessions.d.ts +24 -14
  598. package/packages/gateway/dist/web/sessions.d.ts.map +1 -1
  599. package/packages/gateway/dist/web/sessions.js +42 -14
  600. package/packages/gateway/dist/web/sessions.js.map +1 -1
  601. package/packages/gateway/dist/web/signed-out.d.ts +10 -0
  602. package/packages/gateway/dist/web/signed-out.d.ts.map +1 -1
  603. package/packages/gateway/dist/web/signed-out.js +47 -0
  604. package/packages/gateway/dist/web/signed-out.js.map +1 -1
  605. package/packages/install/dist/.tsbuildinfo +1 -1
  606. package/packages/runtime/dist/.tsbuildinfo +1 -1
  607. package/packages/runtime/dist/delegate.d.ts +8 -0
  608. package/packages/runtime/dist/delegate.d.ts.map +1 -1
  609. package/packages/runtime/dist/delegate.js +19 -1
  610. package/packages/runtime/dist/delegate.js.map +1 -1
  611. package/packages/runtime/dist/loop.d.ts +2 -0
  612. package/packages/runtime/dist/loop.d.ts.map +1 -1
  613. package/packages/runtime/dist/loop.js +18 -4
  614. package/packages/runtime/dist/loop.js.map +1 -1
  615. package/packages/tools/artifacts/dist/.tsbuildinfo +1 -1
  616. package/packages/tools/browser/dist/.tsbuildinfo +1 -1
  617. package/packages/tools/browser/dist/availability.d.ts +2 -2
  618. package/packages/tools/browser/dist/availability.d.ts.map +1 -1
  619. package/packages/tools/browser/dist/availability.js +2 -2
  620. package/packages/tools/browser/dist/availability.js.map +1 -1
  621. package/packages/tools/browser/dist/controller.d.ts +76 -58
  622. package/packages/tools/browser/dist/controller.d.ts.map +1 -1
  623. package/packages/tools/browser/dist/controller.js +751 -219
  624. package/packages/tools/browser/dist/controller.js.map +1 -1
  625. package/packages/tools/browser/dist/extension.d.ts +12 -0
  626. package/packages/tools/browser/dist/extension.d.ts.map +1 -1
  627. package/packages/tools/browser/dist/extension.js +8 -0
  628. package/packages/tools/browser/dist/extension.js.map +1 -1
  629. package/packages/tools/browser/dist/index.d.ts +13 -5
  630. package/packages/tools/browser/dist/index.d.ts.map +1 -1
  631. package/packages/tools/browser/dist/index.js +29 -12
  632. package/packages/tools/browser/dist/index.js.map +1 -1
  633. package/packages/tools/browser/dist/manager.d.ts +39 -21
  634. package/packages/tools/browser/dist/manager.d.ts.map +1 -1
  635. package/packages/tools/browser/dist/manager.js +229 -136
  636. package/packages/tools/browser/dist/manager.js.map +1 -1
  637. package/packages/tools/browser/dist/routes.d.ts +130 -0
  638. package/packages/tools/browser/dist/routes.d.ts.map +1 -0
  639. package/packages/tools/browser/dist/routes.js +283 -0
  640. package/packages/tools/browser/dist/routes.js.map +1 -0
  641. package/packages/tools/browser/dist/service.d.ts +157 -114
  642. package/packages/tools/browser/dist/service.d.ts.map +1 -1
  643. package/packages/tools/browser/dist/service.js +379 -390
  644. package/packages/tools/browser/dist/service.js.map +1 -1
  645. package/packages/tools/browser/dist/settings.d.ts +88 -0
  646. package/packages/tools/browser/dist/settings.d.ts.map +1 -0
  647. package/packages/tools/browser/dist/settings.js +86 -0
  648. package/packages/tools/browser/dist/settings.js.map +1 -0
  649. package/packages/tools/browser/dist/telemetry.d.ts +203 -0
  650. package/packages/tools/browser/dist/telemetry.d.ts.map +1 -0
  651. package/packages/tools/browser/dist/telemetry.js +142 -0
  652. package/packages/tools/browser/dist/telemetry.js.map +1 -0
  653. package/packages/tools/browser/dist/types.d.ts +14 -3
  654. package/packages/tools/browser/dist/types.d.ts.map +1 -1
  655. package/packages/tools/browser/dist/types.js +9 -9
  656. package/packages/tools/browser/dist/types.js.map +1 -1
  657. package/packages/tools/email/dist/.tsbuildinfo +1 -1
  658. package/packages/tools/host/dist/.tsbuildinfo +1 -1
  659. package/packages/tools/mcp/dist/.tsbuildinfo +1 -1
  660. package/packages/tools/memory/dist/.tsbuildinfo +1 -1
  661. package/packages/tools/web/dist/.tsbuildinfo +1 -1
  662. package/packages/web/dist/assets/index-Bac-CdD-.css +1 -0
  663. package/packages/web/dist/assets/index-DI8bp_D7.js +146 -0
  664. package/packages/web/dist/assets/{lottie_light-CKJ88Yuk.js → lottie_light-CuiSMqnl.js} +1 -1
  665. package/packages/web/dist/build.json +1 -1
  666. package/packages/web/dist/index.html +2 -2
  667. package/packages/web/dist/precache.json +4 -4
  668. package/node_modules/@buddi/gateway/dist/web/apps.d.ts +0 -18
  669. package/node_modules/@buddi/gateway/dist/web/apps.d.ts.map +0 -1
  670. package/node_modules/@buddi/gateway/dist/web/apps.js +0 -84
  671. package/node_modules/@buddi/gateway/dist/web/apps.js.map +0 -1
  672. package/node_modules/@buddi/gateway/dist/web/tailscale.d.ts.map +0 -1
  673. package/node_modules/@buddi/gateway/dist/web/tailscale.js.map +0 -1
  674. package/node_modules/@buddi/tool-browser/dist/computer.d.ts +0 -153
  675. package/node_modules/@buddi/tool-browser/dist/computer.d.ts.map +0 -1
  676. package/node_modules/@buddi/tool-browser/dist/computer.js +0 -392
  677. package/node_modules/@buddi/tool-browser/dist/computer.js.map +0 -1
  678. package/node_modules/@buddi/tool-browser/dist/native/buddi-computer +0 -0
  679. package/node_modules/pino/test/browser-bindings.test.js +0 -114
  680. package/node_modules/pino/test/browser-redaction.test.js +0 -264
  681. package/node_modules/pino/test/browser-set-bindings.test.js +0 -99
  682. package/node_modules/pino/test/caller.test.js +0 -20
  683. package/node_modules/pino/test/fixtures/caller-loop.js +0 -6
  684. package/node_modules/pino/test/smoke.js +0 -59
  685. package/node_modules/pino/test/types/pino-import.tst.cts +0 -30
  686. package/node_modules/pino/test/types/pino-import.tst.js +0 -73
  687. package/node_modules/pino/test/types/pino-multistream.tst.ts +0 -49
  688. package/node_modules/pino/test/types/pino-top-export.tst.ts +0 -32
  689. package/node_modules/pino/test/types/pino-type-only.tst.ts +0 -77
  690. package/node_modules/pino/test/types/tsconfig.json +0 -10
  691. package/packages/gateway/dist/web/apps.d.ts +0 -18
  692. package/packages/gateway/dist/web/apps.d.ts.map +0 -1
  693. package/packages/gateway/dist/web/apps.js +0 -84
  694. package/packages/gateway/dist/web/apps.js.map +0 -1
  695. package/packages/gateway/dist/web/tailscale.d.ts.map +0 -1
  696. package/packages/gateway/dist/web/tailscale.js.map +0 -1
  697. package/packages/tools/browser/dist/computer.d.ts +0 -153
  698. package/packages/tools/browser/dist/computer.d.ts.map +0 -1
  699. package/packages/tools/browser/dist/computer.js +0 -392
  700. package/packages/tools/browser/dist/computer.js.map +0 -1
  701. package/packages/tools/browser/dist/native/buddi-computer +0 -0
  702. package/packages/web/dist/assets/index-CN1AXMI1.css +0 -1
  703. package/packages/web/dist/assets/index-CQRE9LJX.js +0 -145
@@ -1,51 +1,55 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { mkdir, readFile, writeFile, rename } from 'node:fs/promises';
3
- import path from 'node:path';
4
2
  import { FORM_KIND, NATIVE_KIND, fieldBoundTo, secretKindFor, takeDelivered } from './secrets.js';
5
3
  import { APP_BEHIND, BrowserPreconditionError, UNTRUSTED, observedLine } from './types.js';
4
+ import { ownerCard, siteOf } from './routes.js';
5
+ import { missionMark } from './telemetry.js';
6
6
  /**
7
- * "The owner stopped the browser", said where the owner can undo it.
8
- *
9
- * The *fact* is one sentence; the way back differs by surface, and the surface
10
- * is already on the tool context (`ctx.surface`), so the plugin says it rather
11
- * than leaving a relay to guess. On Telegram the way back is a command in the
12
- * same chat; everywhere else it is the dashboard's own Settings page, which is
13
- * where the Stop button lives.
7
+ * Said when the owner has stopped agents' browsing. On Telegram the way back
8
+ * is a command in the same chat; everywhere else the Resume card in the chat
9
+ * itself, or Settings.
14
10
  */
15
- /** Said when control paused: the tab or window is gone, or the page kept failing to answer. The way back depends on where the owner is. */
11
+ export function browserStoppedMessage(surface) {
12
+ return surface?.id === 'telegram'
13
+ ? 'The owner stopped agents\' browsing. Tap Resume on the card, or send /browser resume here.'
14
+ : 'The owner stopped agents\' browsing. Tap Resume on the card in this chat to let agents look again.';
15
+ }
16
+ /** Kept for the surfaces that still name it: the owner has the page in their hands. */
16
17
  export function browserPausedMessage(surface) {
17
18
  return surface?.id === 'telegram'
18
- ? 'Control is paused: the page closed or stopped answering. Send /browser resume here, then ask again for a fresh look.'
19
- : 'Control is paused. Ask the owner to inspect the selected app/window and the reported cause, then use Resume access and ask for a fresh observation.';
19
+ ? 'You have the page. Give it back from the dashboard, or send /browser resume here.'
20
+ : 'You have the page. Give it back when you are done and the agent carries on.';
20
21
  }
21
- /**
22
- * Said when an observation did not answer and control stays with the agent.
23
- * A slow page is something the model can wait out itself, so there is nothing
24
- * for the owner to do and the wording is the same on every surface.
25
- */
22
+ /** A page that did not answer after every retry: said once, never as an instruction to retry. */
26
23
  export function browserWaitMessage(_surface) {
27
- return 'The page has not answered yet. Wait a few seconds and observe again.';
24
+ return 'The page did not answer after several tries.';
28
25
  }
29
- /** An observation failure that no waiting fixes: the tab or window it was reading is gone. */
30
- const SCREEN_GONE = /\b(tab|window)\b[^.]*\b(closed|gone)\b|has been closed|target closed/i;
31
- /** A gone tab the driver can replace by itself ("observe again to continue in a new one") is not a screen lost. */
32
- const SCREEN_REPLACEABLE = /observe again to continue in a new one/i;
33
- /** The extension's refusal to act in the tab the owner is viewing (extension commands.ts, `WATCHED`). */
26
+ /** The extension's last word after waiting for the owner to leave their tab (extension commands.ts, `WATCHED`). */
34
27
  const OWNER_WATCHING = /You are looking at this tab/i;
35
- /** What the model is told instead: one ask of the owner, not a retry. */
36
- export const OWNER_WATCHING_MESSAGE = 'The owner is looking at that tab. Ask them to switch to another tab or window, then try once more.';
37
- /** Consecutive observation failures on one session before control pauses. */
38
- const MAX_OBSERVATION_FAILURES = 3;
39
- export function browserStoppedMessage(surface) {
40
- return surface?.id === 'telegram'
41
- ? 'The owner stopped the browser. Only the owner can enable it again — send /browser resume here.'
42
- : 'The owner stopped the browser. Only the owner can enable it again in the dashboard, on the Settings page.';
43
- }
44
- /** Already classified: do not retry observation or overwrite the paused state. */
45
- class ObservationFailure extends Error {
28
+ /** What the agent is told instead: no ask, no retry loop; the bar in the tab already asks the owner. */
29
+ export const OWNER_WATCHING_MESSAGE = 'The owner is looking at that tab, and the bar in it asks them whether you may carry on there. Nothing was done. Work on something else for a moment, then try again.';
30
+ /** An observation failure no waiting fixes: the tab or window it was reading is gone. */
31
+ const SCREEN_GONE = /\b(tab|window)\b[^.]*\b(closed|gone)\b|has been closed|target closed/i;
32
+ /** The waits before each re-read when the page gave no answer: 0.5, 1, 2, 4 and 8 seconds (six attempts in all). */
33
+ export const RETRY_DELAYS_MS = [500, 1_000, 2_000, 4_000, 8_000];
34
+ /** Targeting refusals in a row before the task asks the owner whether to keep going. */
35
+ export const MAX_TARGETING_FAILURES = 8;
36
+ /** The task's budget: actions and minutes, renewed by any owner touch in the conversation. */
37
+ export const DEFAULT_MAX_STEPS = 200;
38
+ export const DEFAULT_LIFETIME_MS = 60 * 60_000;
39
+ /** How long a run stays parked on its page waiting for the owner's card. */
40
+ export const PARK_MS = 60 * 60_000;
41
+ /** A route by the mode name the dashboard and Telegram already know. */
42
+ export function modeOf(route) {
43
+ return route === 'chrome' ? 'extension' : route === 'apps' ? 'computer' : 'playwright';
46
44
  }
47
- /** One host controller shared by all registry instances/surfaces in serve.
48
- * CLI processes are deliberately unavailable, not a second browser owner. */
45
+ /**
46
+ * One conversation's page on one route.
47
+ *
48
+ * Every action returns the page as it is afterwards. Refusals that used to
49
+ * stop the task are retried here (a slow page, a stale ref, a redirect) or
50
+ * become one card the owner answers (an input that may not have landed, the
51
+ * budget). Only the owner's own take-over pauses a page.
52
+ */
49
53
  export class BrowserService {
50
54
  driver;
51
55
  options;
@@ -55,81 +59,81 @@ export class BrowserService {
55
59
  #observation;
56
60
  #picture;
57
61
  #busy = false;
58
- /**
59
- * The screen this session had is gone.
60
- *
61
- * Set when a take-over had to close the driver to end the action in flight,
62
- * and cleared by resume. Belt to `handReady`'s braces: a hand offered over
63
- * nothing is a live view that never paints its first frame, and the owner
64
- * has no way to tell that from a slow link.
65
- */
66
62
  #handless = false;
67
63
  #controller;
68
64
  #expiry;
69
65
  #lastAction;
70
66
  #message;
71
- #preconditionFailures = 0;
72
- #observationFailures = 0;
73
- #needsObservation = false;
74
- #spent = new Set();
67
+ #targetingFailures = 0;
68
+ #card;
69
+ /** Where the page last was, so a closed tab or a new request re-opens it rather than stopping. */
70
+ #lastUrl;
71
+ #lastActivity = 0;
72
+ #tail = Promise.resolve();
75
73
  #controlTail = Promise.resolve();
76
- #diskTail = Promise.resolve();
77
74
  constructor(driver, options = {}) {
78
75
  this.driver = driver;
79
76
  this.options = options;
80
77
  }
81
78
  #now() { return this.options.now?.() ?? Date.now(); }
82
- /** When buddi took this observation, so the model can tell the newest from an older one. */
83
- #stamp(observation) {
84
- return { ...observation, observedAt: new Date(this.#now()).toISOString() };
79
+ get #route() { return this.options.route ?? (this.options.allowOpen ? 'apps' : 'own'); }
80
+ #sleep(ms) { return this.options.sleep ? this.options.sleep(ms) : new Promise((resolve) => setTimeout(resolve, ms)); }
81
+ #stamp(observation) { return { ...observation, observedAt: new Date(this.#now()).toISOString() }; }
82
+ #stop(cause, ctx, recovered) {
83
+ this.options.telemetry?.stop(cause, { route: this.#route, ...(ctx?.agentId ? { agent: ctx.agentId } : {}), ...(ctx?.surface?.id ? { surface: ctx.surface.id } : {}), ...missionMark(ctx),
84
+ ...(siteOf(this.#observation?.url ?? this.#lastUrl) ? { host: siteOf(this.#observation?.url ?? this.#lastUrl) } : {}), ...(recovered ? { recovered } : {}) });
85
85
  }
86
86
  async enable() {
87
87
  if (this.#enabled)
88
88
  return;
89
- if (this.options.controlFile) {
90
- try {
91
- const state = JSON.parse(await readFile(this.options.controlFile, 'utf8'));
92
- this.#state = state.stopped ? 'stopped' : 'idle';
93
- }
94
- catch (error) {
95
- if (error.code !== 'ENOENT')
96
- throw error;
97
- this.#state = 'idle';
98
- }
99
- }
100
- else
101
- this.#state = 'idle';
89
+ // Take over pressed in the page's own bar is the Canvas button.
90
+ this.driver.onOwnerTakeover?.(() => {
91
+ const id = this.#session?.id;
92
+ if (!id)
93
+ return;
94
+ if (this.options.requestTakeover)
95
+ this.options.requestTakeover(id);
96
+ else
97
+ void this.control('takeover').catch(() => undefined);
98
+ });
99
+ this.#state = 'idle';
102
100
  this.#enabled = true;
103
101
  }
104
102
  status(_scope) {
105
103
  const { tree: _tree, targets: _targets, ...page } = this.#observation ?? {};
106
- const { ownerId: _owner, ...session } = this.#session ?? {};
104
+ const session = this.#session ? (({ ownerId: _o, startedAt: _s, actions: _a, cards: _c, ...rest }) => rest)(this.#session) : undefined;
107
105
  return { state: this.#state, enabled: this.#enabled, busy: this.#busy,
108
- ...(this.#session ? { session: session } : {}),
106
+ ...(session ? { session: { ...session, route: this.#route }, route: this.#route, mode: modeOf(this.#route) } : {}),
109
107
  ...(this.#observation ? { page: page } : {}),
108
+ ...(this.#card ? { needsOwner: this.#card } : {}),
110
109
  lastAction: this.#lastAction, message: this.#message, hasScreenshot: !!this.#picture };
111
110
  }
112
111
  screenshot(_sessionId) { return this.#picture; }
112
+ /** The card this page waits on, if any. */
113
+ get card() { return this.#card; }
114
+ /** Where this page is, or was. */
115
+ get lastUrl() { return this.#observation?.url ?? this.#lastUrl; }
116
+ /** The latest page, with its tree: what the route's post-processing reads. */
117
+ get observation() { return this.#observation; }
118
+ get busy() { return this.#busy; }
119
+ /** Where this conversation's page was before it was let go, so the next action opens it again there. */
120
+ seed(url) { this.#lastUrl ??= url; }
121
+ /** No action for this long: a page a waiting conversation may take over. */
122
+ idleFor() { return this.#busy || this.#state === 'paused' || this.#card ? 0 : this.#now() - this.#lastActivity; }
113
123
  /**
114
- * The remote hand, and only while the owner holds this screen.
115
- *
116
- * Paused is the take-over state, so it is also the only state in which a
117
- * dashboard may drive: an agent mid-action and a hand on the same page would
118
- * be two drivers, and the evidence rules here assume exactly one.
124
+ * The remote hand, and only while the owner holds this screen. Paused is the
125
+ * take-over state, the only one in which a dashboard may drive.
119
126
  */
120
127
  hand(_scope) {
121
128
  if (this.driver.supportsHand === false || !this.driver.hand) {
122
- return { supported: false, message: this.driver.handMessage ?? 'Take over at the computer for this mode.' };
129
+ return { supported: false, message: this.driver.handMessage ?? 'Take over at the computer for this route.' };
123
130
  }
124
131
  if (!this.#session)
125
- return { supported: true, message: 'No agent is driving this screen.' };
132
+ return { supported: true, message: 'No agent is looking at this page.' };
126
133
  if (this.#state !== 'paused')
127
134
  return { supported: true, message: 'Take over first, then you can drive.' };
128
- // Paused is not the same as paintable. A take-over that interrupted an
129
- // action closed the screen that action was on, and a hand offered over
130
- // nothing is a live view that never draws its first frame.
131
135
  if (this.#handless || this.driver.handReady?.() === false) {
132
- return { supported: true, message: this.#message ?? 'There is no screen to drive. Resume and ask the agent to open the page again.' };
136
+ return { supported: true, message: this.#message ?? 'There is no screen to drive. Give it back and the agent opens the page again.' };
133
137
  }
134
138
  return { supported: true, hand: this.driver.hand };
135
139
  }
@@ -138,120 +142,178 @@ export class BrowserService {
138
142
  if (!session || session.ownerId !== input.ownerId || session.agentId !== input.agentId || session.conversationId !== input.previousConversationId)
139
143
  return false;
140
144
  if (!this.#enabled || this.#busy || !['running', 'paused'].includes(this.#state))
141
- throw new Error('Wait for computer/browser control to settle before continuing the conversation.');
142
- if (Date.parse(session.expiresAt) <= this.#now())
143
- return false;
144
- this.#spent.add(session.requestId);
145
+ throw new Error('Wait for the page to settle before continuing the conversation.');
145
146
  session.conversationId = input.conversationId;
146
147
  this.#observation = undefined;
147
148
  this.#picture = undefined;
148
- this.#needsObservation = true;
149
- this.#message = 'Task continued after conversation rollover. Observe the current page before acting. Human takeover, if active, still requires owner resume.';
149
+ this.#message = 'Task continued after conversation rollover. The next action returns the current page.';
150
150
  return true;
151
151
  }
152
- async execute(command, ctx) {
152
+ /**
153
+ * Put the page on a card and wait for the owner. The run stops (the tool's
154
+ * result carries the card) and the page stays open for at least an hour.
155
+ */
156
+ park(kind, facts = {}) {
157
+ const card = ownerCard(kind, { site: siteOf(this.lastUrl), ...facts });
158
+ this.#card = card;
159
+ if (this.#session)
160
+ this.#session.cards++;
161
+ this.#schedule(Math.max(Date.parse(this.#session?.expiresAt ?? '') || 0, this.#now()) + Math.max(this.options.parkMs ?? PARK_MS, PARK_MS) - this.#now());
162
+ return card;
163
+ }
164
+ #cardResult(card, dispatched, message) {
165
+ return { completed: false, dispatched, needsOwner: card, notice: UNTRUSTED,
166
+ message: message ?? `Waiting for the owner: "${card.title}" Say that in one sentence and stop; the card in the chat has the buttons. The page stays open; you continue when they answer.`,
167
+ ...(this.#observation ? { observation: this.#observation } : {}) };
168
+ }
169
+ /**
170
+ * The owner spoke or tapped in this conversation: the budget renews (200
171
+ * actions, an hour) and a waiting card is cleared. Returns the card it
172
+ * cleared, so the caller can act on the answer (take over, use Chrome).
173
+ */
174
+ renew() {
175
+ const card = this.#card;
176
+ this.#card = undefined;
177
+ this.#targetingFailures = 0;
178
+ if (this.#session) {
179
+ this.#session.steps = 0;
180
+ this.#session.maxSteps = this.options.maxSteps ?? DEFAULT_MAX_STEPS;
181
+ const expiresAt = this.#now() + (this.options.lifetimeMs ?? DEFAULT_LIFETIME_MS);
182
+ this.#session.expiresAt = new Date(expiresAt).toISOString();
183
+ this.#schedule(expiresAt - this.#now() + Math.max(this.options.parkMs ?? PARK_MS, PARK_MS));
184
+ }
185
+ return card;
186
+ }
187
+ #schedule(ms) {
188
+ clearTimeout(this.#expiry);
189
+ this.#expiry = setTimeout(() => { void this.#release('expired'); }, Math.max(1, ms));
190
+ this.#expiry.unref?.();
191
+ }
192
+ #open(request, ctx) {
193
+ const lifetime = this.options.lifetimeMs ?? DEFAULT_LIFETIME_MS;
194
+ if (!this.#session) {
195
+ const expiresAt = this.#now() + lifetime;
196
+ this.#session = { id: randomUUID(), ownerId: ctx.buddi.owner.id, agentId: ctx.agentId, conversationId: ctx.conversationId,
197
+ requestId: request?.id ?? 'unattended', task: (request?.text ?? 'An unattended task').slice(0, 4000),
198
+ expiresAt: new Date(expiresAt).toISOString(), steps: 0, maxSteps: this.options.maxSteps ?? DEFAULT_MAX_STEPS,
199
+ startedAt: this.#now(), actions: 0, cards: 0 };
200
+ this.#schedule(lifetime + Math.max(this.options.parkMs ?? PARK_MS, PARK_MS));
201
+ return;
202
+ }
203
+ // A new owner message is an owner touch: the same page, a fresh budget.
204
+ if (request && this.#session.requestId !== request.id) {
205
+ this.#session.requestId = request.id;
206
+ this.#session.task = request.text.slice(0, 4000);
207
+ this.renew();
208
+ }
209
+ }
210
+ /** One action at a time per page: a second call waits for the first rather than being refused. */
211
+ #serial(run) {
212
+ const next = this.#tail.then(run, run);
213
+ this.#tail = next.catch(() => { });
214
+ return next;
215
+ }
216
+ execute(command, ctx) {
217
+ return this.#serial(() => this.#execute(command, ctx));
218
+ }
219
+ async #execute(command, ctx) {
153
220
  ctx.signal?.throwIfAborted();
154
221
  const request = ctx.ownerRequest;
155
- if (!request || !request.id || !request.text.trim() || request.expiresAt <= this.#now() ||
156
- !ctx.agentId || !ctx.conversationId || (ctx.delegationDepth ?? 0) > 0) {
157
- throw new Error('A current authenticated owner request is required.');
158
- }
222
+ if (!ctx.agentId || !ctx.conversationId)
223
+ throw new Error('A browser action belongs to an agent and a conversation.');
159
224
  if (!this.#enabled)
160
225
  throw new Error('Browser driving is available through buddi serve (dashboard or Telegram), not a separate CLI process.');
161
226
  if (this.#state === 'stopped')
162
227
  throw new Error(browserStoppedMessage(ctx.surface));
163
- if (this.#busy)
164
- throw new Error('Browser is busy; overlapping actions are refused.');
165
228
  if (this.#session && (this.#session.ownerId !== ctx.buddi.owner.id || this.#session.agentId !== ctx.agentId || this.#session.conversationId !== ctx.conversationId)) {
166
- throw new Error('Another agent/conversation owns the browser. Ask the owner to release it from the dashboard.');
229
+ throw new Error('Another conversation owns this page.');
167
230
  }
168
- if (this.#spent.has(request.id))
169
- throw new Error('This browser request has ended. A new owner message is required.');
170
231
  if (command.action === 'close') {
171
- this.#spent.add(request.id);
172
232
  await this.#release('idle');
173
233
  return { closed: true, notice: UNTRUSTED };
174
234
  }
175
- if (this.#state === 'paused')
176
- throw new Error('Browser is under human control or needs inspection. Wait for the owner to resume in the dashboard, then observe.');
177
- // Computer mode's open only brings an app forward, then observes: nothing earlier is replayed.
178
- // navigate still waits for a fresh look, since it loads a page.
179
- const reopens = this.options.allowOpen === true && command.action === 'open';
180
- if (this.#needsObservation && command.action !== 'observe' && !reopens)
181
- throw new Error('A fresh observation is required: observe the current page before acting. Do not replay an earlier action.');
182
- if (!this.#session || this.#session.requestId !== request.id) {
183
- if (!this.#session && command.action !== 'navigate' && !(this.options.allowOpen && command.action === 'open'))
184
- throw new Error('Start with navigate, or open an allowed application in computer mode.');
185
- this.#rekey(request, ctx.agentId, ctx.conversationId, ctx.buddi.owner.id);
235
+ if (this.#state === 'paused') {
236
+ throw new Error('The owner has this page in their hands. Wait for them to give it back; you continue when they do.');
237
+ }
238
+ // Parked on a card: nothing is done until the owner answers it.
239
+ if (this.#card) {
240
+ this.#open(request, ctx);
241
+ if (this.#card)
242
+ return this.#cardResult(this.#card, false);
186
243
  }
244
+ let run = command;
245
+ let reopened = false;
246
+ if (!this.#session && command.action !== 'navigate' && command.action !== 'open') {
247
+ // No page yet, or the last one was let go: open it again where it was.
248
+ if (!this.#lastUrl || this.#route === 'apps') {
249
+ this.#stop('start-with-navigate', ctx);
250
+ return { completed: false, dispatched: false, notice: UNTRUSTED, message: 'No page is open in this conversation yet. Navigate to the website first.' };
251
+ }
252
+ this.#stop('request-ended', ctx);
253
+ run = { action: 'navigate', url: this.#lastUrl };
254
+ reopened = true;
255
+ }
256
+ this.#open(request, ctx);
187
257
  const active = this.#session;
188
- if (!active || Date.parse(active.expiresAt) <= this.#now() || active.steps >= active.maxSteps) {
189
- await this.#release('expired');
190
- throw new Error('Browser task reached its time or step limit. Ask the owner for a new request.');
258
+ if (active.steps >= active.maxSteps || Date.parse(active.expiresAt) <= this.#now()) {
259
+ this.#stop('budget', ctx);
260
+ return this.#cardResult(this.park('budget'), false);
261
+ }
262
+ // The observation is the latest one unless the agent named another.
263
+ if (['click', 'fill', 'select', 'press', 'scroll'].includes(run.action) && run.observation === undefined && this.#observation) {
264
+ run = { ...run, observation: this.#observation.id };
191
265
  }
192
266
  ++active.steps;
267
+ ++active.actions;
193
268
  this.#busy = true;
194
- this.#lastAction = command.action; // Never record form values here.
269
+ this.#lastAction = run.action; // Never record form values here.
270
+ this.#lastActivity = this.#now();
195
271
  this.#message = undefined;
196
272
  const controller = new AbortController();
197
273
  this.#controller = controller;
198
274
  const cancel = () => {
199
275
  controller.abort(ctx.signal?.reason ?? new Error('Browser action stopped.'));
200
- this.#spent.add(request.id);
201
- void this.#release('stopped');
202
- void this.#persistStop(true).catch(() => { });
276
+ void this.#release('idle');
203
277
  };
204
278
  ctx.signal?.addEventListener('abort', cancel, { once: true });
205
279
  try {
206
280
  this.#state = 'starting';
207
281
  await this.driver.start();
208
282
  controller.signal.throwIfAborted();
209
- ctx.signal?.throwIfAborted();
210
283
  this.#state = 'running';
211
- await this.driver.perform(command);
212
- if (command.action !== 'observe')
213
- this.#preconditionFailures = 0;
284
+ await this.driver.perform(run);
285
+ if (run.action !== 'observe')
286
+ this.#targetingFailures = 0;
214
287
  controller.signal.throwIfAborted();
215
- // Once input succeeds, observation loss must not invite replaying it.
216
- // For an observe-only command, however, observation IS the whole action.
217
- try {
218
- const observation = await this.driver.observe();
219
- const picture = await this.driver.screenshot();
220
- controller.signal.throwIfAborted();
221
- this.#observation = this.#stamp(observation);
222
- this.#picture = picture;
223
- this.#needsObservation = false;
224
- this.#observationFailures = 0;
288
+ const seen = await this.#look(controller, ctx);
289
+ if (!seen) {
290
+ // Six reads over fifteen seconds and nothing: one card, not a loop.
291
+ this.#stop('observation-failures', ctx, 'card');
292
+ return this.#cardResult(this.park('uncertain'), run.action !== 'observe');
225
293
  }
226
- catch (error) {
227
- controller.signal.throwIfAborted();
228
- const cause = error instanceof Error ? error.message : String(error);
229
- const paused = this.#observationFailed(cause);
230
- // The extension's final error already says to wait and observe again; do not say it twice.
231
- // The app pushed behind already says how to bring it back.
232
- const recovery = paused ? browserPausedMessage(ctx.surface) : APP_BEHIND.test(cause) || /observe again\.?$/i.test(cause.trim()) ? '' : browserWaitMessage(ctx.surface);
233
- this.#message = `${command.action === 'observe' ? 'Observation failed' : 'Action completed, but observation failed'}: ${cause.replace(/\.$/, '')}.${recovery ? ` ${recovery}` : ''}${command.action === 'observe' ? '' : ' Do not repeat the action; its effect may already have happened.'}`;
234
- const result = { completed: command.action !== 'observe', observed: false, error: cause,
235
- state: this.#state, recovery, message: this.#message, notice: UNTRUSTED };
236
- if (command.action === 'observe')
237
- throw new ObservationFailure(JSON.stringify(result));
238
- return result;
239
- }
240
- controller.signal.throwIfAborted();
241
294
  const observed = observedLine(this.#observation.observedAt);
295
+ if (reopened) {
296
+ const asked = command.action;
297
+ return { completed: false, dispatched: false, notice: UNTRUSTED, observation: this.#observation,
298
+ message: `${observed} No page was open, so I opened ${siteOf(this.#lastUrl) ?? 'the last page'} again. Nothing else was done; ${asked === 'observe' ? 'here it is' : 'act on this page now'}.` };
299
+ }
242
300
  return { completed: true, notice: UNTRUSTED, observation: this.#observation, message: this.#message ? `${observed} ${this.#message}` : observed };
243
301
  }
244
302
  catch (error) {
245
- if (error instanceof ObservationFailure)
303
+ if (controller.signal.aborted)
246
304
  throw error;
247
- if (!controller.signal.aborted && error instanceof BrowserPreconditionError) {
248
- await this.#precondition(controller, error);
249
- }
250
- if (!controller.signal.aborted) {
251
- this.#state = error instanceof BrowserPreconditionError ? 'running'
252
- : ['click', 'fill', 'select', 'press'].includes(command.action) ? 'paused' : 'error';
253
- this.#message = `${error instanceof Error ? error.message : String(error)}${this.#state === 'paused' ? ' The action may have partially completed. Inspect it before resuming; do not repeat a submission.' : ''}`;
305
+ const message = error instanceof Error ? error.message : String(error);
306
+ if (error instanceof BrowserPreconditionError)
307
+ return await this.#precondition(controller, error, ctx);
308
+ this.#state = 'running';
309
+ if (['click', 'fill', 'select', 'press'].includes(run.action)) {
310
+ // The input may have landed part-way: the owner looks, or tells the agent to judge from the page.
311
+ this.#stop('uncertain-input', ctx, 'card');
312
+ this.#observation = undefined;
313
+ this.#picture = undefined;
314
+ return this.#cardResult(this.park('uncertain'), true, `${message.replace(/\.$/, '')}. I'm not sure that went through. Say so in one sentence and stop; the card asks the owner whether to look.`);
254
315
  }
316
+ this.#message = message;
255
317
  throw error;
256
318
  }
257
319
  finally {
@@ -262,201 +324,172 @@ export class BrowserService {
262
324
  }
263
325
  }
264
326
  /**
265
- * An observation that did not come back. Usually a page still loading or
266
- * busy, which the agent can wait out and observe again, so control stays
267
- * with it and the next action must be a fresh observation. Control pauses
268
- * only when the tab or window is gone, or on the third failure in a row.
269
- * Returns whether it paused.
327
+ * Read the page, re-reading at 0.5, 1, 2, 4 and 8 seconds when it does not
328
+ * answer. A closed tab is opened again at its last address once. False when
329
+ * all six reads failed. The app pushed behind the owner's window is said
330
+ * straight away: open brings it back and no wait helps.
270
331
  */
271
- #observationFailed(cause) {
272
- this.#observation = undefined;
273
- this.#picture = undefined;
274
- this.#needsObservation = true;
275
- // The owner's window in front of the app is not a failing screen: the agent brings it back with open.
276
- if (APP_BEHIND.test(cause)) {
277
- if (this.#state !== 'paused')
278
- this.#state = 'running';
279
- return false;
332
+ async #look(controller, ctx) {
333
+ const delays = this.options.retryDelays ?? RETRY_DELAYS_MS;
334
+ let reopened = false;
335
+ let counted = false;
336
+ for (let attempt = 0; attempt <= delays.length; attempt++) {
337
+ if (attempt > 0)
338
+ await this.#sleep(delays[attempt - 1]);
339
+ controller.signal.throwIfAborted();
340
+ try {
341
+ const observation = await this.driver.observe();
342
+ const picture = await this.driver.screenshot();
343
+ controller.signal.throwIfAborted();
344
+ this.#observation = this.#stamp(observation);
345
+ this.#picture = picture;
346
+ if (observation.url)
347
+ this.#lastUrl = observation.url;
348
+ return true;
349
+ }
350
+ catch (error) {
351
+ controller.signal.throwIfAborted();
352
+ const cause = error instanceof Error ? error.message : String(error);
353
+ this.#observation = undefined;
354
+ this.#picture = undefined;
355
+ if (APP_BEHIND.test(cause)) {
356
+ this.#stop('app-behind', ctx);
357
+ throw new BrowserPreconditionError(cause);
358
+ }
359
+ if (SCREEN_GONE.test(cause) && !reopened && this.#lastUrl && this.#route !== 'apps') {
360
+ reopened = true;
361
+ this.#stop('screen-gone', ctx);
362
+ try {
363
+ await this.driver.perform({ action: 'navigate', url: this.#lastUrl });
364
+ }
365
+ catch { /* the next read says */ }
366
+ continue;
367
+ }
368
+ if (!counted) {
369
+ counted = true;
370
+ this.#stop('page-not-answered', ctx);
371
+ }
372
+ }
280
373
  }
281
- const paused = ++this.#observationFailures >= MAX_OBSERVATION_FAILURES || (SCREEN_GONE.test(cause) && !SCREEN_REPLACEABLE.test(cause));
282
- this.#state = paused ? 'paused' : 'running';
283
- return paused;
284
- }
285
- /**
286
- * A new owner message continues the session under that message's request:
287
- * the old one is spent, the step budget and the failure count reset, and the
288
- * expiry runs from now. The session id survives, so the conversation still
289
- * owns the same screen it always did.
290
- */
291
- #rekey(request, agentId, conversationId, ownerId) {
292
- const expiresAt = Math.min(request.expiresAt, this.#now() + (this.options.lifetimeMs ?? 20 * 60_000));
293
- if (this.#session)
294
- this.#spent.add(this.#session.requestId);
295
- this.#preconditionFailures = 0;
296
- this.#session = { id: this.#session?.id ?? randomUUID(), ownerId, agentId,
297
- conversationId, requestId: request.id, task: request.text.slice(0, 4000),
298
- expiresAt: new Date(expiresAt).toISOString(), steps: 0, maxSteps: this.options.maxSteps ?? 80 };
299
- clearTimeout(this.#expiry);
300
- this.#expiry = setTimeout(() => { void this.#release('expired'); }, Math.max(1, expiresAt - this.#now()));
301
- this.#expiry.unref?.();
374
+ return false;
302
375
  }
303
376
  /**
304
- * The precondition path every refused action takes, `browser.act`'s and the
305
- * secret tools' alike: count the failure, pause on the third, and recover
306
- * fresh evidence so the next call acts on what the page now shows rather
307
- * than on the stale arguments. Nothing was dispatched for any of these.
377
+ * Refused before anything was dispatched: a stale observation, a ref that
378
+ * no longer matches, a page that moved. The tool looks again and answers
379
+ * with the fresh page; nothing pauses. Eight in a row asks the owner
380
+ * whether to keep going. The owner looking at the tab and the app behind
381
+ * their window are said as what they are.
308
382
  */
309
- async #precondition(controller, error) {
383
+ async #precondition(controller, error, ctx) {
384
+ this.#state = 'running';
310
385
  if (OWNER_WATCHING.test(error.message)) {
311
- // Not a targeting failure and nothing waiting fixes: only the owner
312
- // moving to another tab does. No pause and no count; the next action
313
- // must observe first, so the model asks once instead of retrying.
386
+ this.#stop('owner-watching', ctx);
314
387
  this.#message = OWNER_WATCHING_MESSAGE;
315
- this.#state = 'running';
316
- this.#needsObservation = true;
317
- throw new BrowserPreconditionError(JSON.stringify({ error: OWNER_WATCHING_MESSAGE, dispatched: false,
318
- recovery: 'Ask the owner now and wait for their answer. Do not retry by yourself.' }));
388
+ throw new BrowserPreconditionError(JSON.stringify({ error: OWNER_WATCHING_MESSAGE, dispatched: false }));
319
389
  }
320
390
  if (APP_BEHIND.test(error.message)) {
321
- // The owner's own window came forward (typing in the dashboard does it).
322
- // Not a targeting failure and nothing for the owner to do: the agent
323
- // calls open for the same app. No count, no pause, and no recovery
324
- // observation, which would only be refused the same way.
325
391
  this.#message = error.message;
326
- this.#state = 'running';
327
392
  this.#observation = undefined;
328
393
  this.#picture = undefined;
329
- this.#needsObservation = true;
330
394
  throw new BrowserPreconditionError(JSON.stringify({ error: error.message, dispatched: false,
331
- recovery: 'Call browser.act open with the same app now; it needs no approval. Then observe and continue.' }));
395
+ recovery: 'Call browser.act open with the same app now; it needs no approval. It returns the app as it is.' }));
332
396
  }
397
+ const cause = /stale|latest observation/i.test(error.message) ? 'stale-observation'
398
+ : /changed since|moved|redirect|different page/i.test(error.message) ? 'redirect' : 'stale-ref';
399
+ this.#stop(cause, ctx);
333
400
  this.#message = error.message;
334
- this.#state = ++this.#preconditionFailures >= 3 ? 'paused' : 'running';
335
- if (this.#state === 'paused')
336
- this.#message += ' Repeated targeting failures: ask the owner to inspect and resume. No input was dispatched.';
337
- // Recover evidence, never replay input. Keep this a failed tool result
338
- // so the runtime skips any remaining sequential calls in this batch.
339
- try {
340
- const observation = await this.driver.observe();
341
- const picture = await this.driver.screenshot();
342
- controller.signal.throwIfAborted();
343
- this.#observation = this.#stamp(observation);
344
- this.#picture = picture;
345
- this.#observationFailures = 0;
346
- }
347
- catch (observationError) {
348
- controller.signal.throwIfAborted();
349
- const cause = observationError instanceof Error ? observationError.message : String(observationError);
350
- const targeting = this.#state === 'paused';
351
- const paused = this.#observationFailed(cause) || targeting;
352
- if (paused)
353
- this.#state = 'paused';
354
- this.#message += ` Recovery observation failed: ${cause.replace(/\.$/, '')}.${paused ? ' Inspect the selected app/window and this error, then resume and observe. Do not retry while paused.' : APP_BEHIND.test(cause) ? '' : ` ${browserWaitMessage()}`}`;
401
+ if (++this.#targetingFailures >= MAX_TARGETING_FAILURES) {
402
+ this.#stop('targeting-cap', ctx, 'card');
403
+ return this.#cardResult(this.park('budget'), false);
355
404
  }
356
- throw new BrowserPreconditionError(JSON.stringify({ error: this.#message, dispatched: false,
357
- ...(this.#observation?.observedAt ? { message: observedLine(this.#observation.observedAt) } : {}),
358
- recovery: this.#state === 'paused' ? 'Wait for owner resume. Do not retry.' : this.#needsObservation ? (APP_BEHIND.test(this.#message) ? 'Call browser.act open with the same app; it needs no approval. Then observe.' : browserWaitMessage()) : 'Re-evaluate using the fresh observation below. Prefer target:{ref:"..."} and this observation.id. Do not guess an index or reuse the previous observation.',
359
- observation: this.#observation }));
405
+ const seen = await this.#look(controller, ctx).catch(() => false);
406
+ throw new BrowserPreconditionError(JSON.stringify({ error: error.message, dispatched: false,
407
+ ...(seen && this.#observation?.observedAt ? { message: `${observedLine(this.#observation.observedAt)} The page changed; here it is now.` } : {}),
408
+ recovery: seen ? 'Nothing was done. Re-evaluate from the page below and act on it; prefer target:{ref:"..."} from it.' : browserWaitMessage(),
409
+ ...(seen ? { observation: this.#observation } : {}) }));
360
410
  }
361
411
  /**
362
- * The authority shell the secret tools run under: exactly `execute`'s gates —
363
- * the same authenticated owner request, the same single-owner lock, the same
364
- * stopped/busy/paused/fresh-evidence refusals, the same step and expiry
365
- * budget — and its start sequence and precondition path. A secret fill is a
366
- * browser action like any other; only the value's route differs.
412
+ * The authority shell the secret tools run under: the same page, budget and
413
+ * card rules as `execute`. A secret fill is a browser action like any other;
414
+ * only the value's route differs.
367
415
  */
368
- async #under(ctx, action, run) {
369
- ctx.signal?.throwIfAborted();
370
- const request = ctx.ownerRequest;
371
- if (!request || !request.id || !request.text.trim() || request.expiresAt <= this.#now() ||
372
- !ctx.agentId || !ctx.conversationId || (ctx.delegationDepth ?? 0) > 0) {
373
- throw new Error('A current authenticated owner request is required.');
374
- }
375
- if (!this.#enabled)
376
- throw new Error('Browser driving is available through buddi serve (dashboard or Telegram), not a separate CLI process.');
377
- if (this.#state === 'stopped')
378
- throw new Error(browserStoppedMessage(ctx.surface));
379
- if (this.#busy)
380
- throw new Error('Browser is busy; overlapping actions are refused.');
381
- if (this.#session && (this.#session.ownerId !== ctx.buddi.owner.id || this.#session.agentId !== ctx.agentId || this.#session.conversationId !== ctx.conversationId)) {
382
- throw new Error('Another agent/conversation owns the browser. Ask the owner to release it from the dashboard.');
383
- }
384
- if (this.#spent.has(request.id))
385
- throw new Error('This browser request has ended. A new owner message is required.');
386
- if (this.#state === 'paused')
387
- throw new Error('Browser is under human control or needs inspection. Wait for the owner to resume in the dashboard, then observe.');
388
- if (this.#needsObservation)
389
- throw new Error('A fresh observation is required: observe the current page before acting. Do not replay an earlier action.');
390
- if (!this.#session)
391
- throw new Error('Start with navigate, or open an allowed application, and observe before using a secret here.');
392
- if (this.#session.requestId !== request.id)
393
- this.#rekey(request, ctx.agentId, ctx.conversationId, ctx.buddi.owner.id);
394
- const active = this.#session;
395
- if (!active || Date.parse(active.expiresAt) <= this.#now() || active.steps >= active.maxSteps) {
396
- await this.#release('expired');
397
- throw new Error('Browser task reached its time or step limit. Ask the owner for a new request.');
398
- }
399
- ++active.steps;
400
- this.#busy = true;
401
- this.#lastAction = action;
402
- this.#message = undefined;
403
- const controller = new AbortController();
404
- this.#controller = controller;
405
- const cancel = () => {
406
- controller.abort(ctx.signal?.reason ?? new Error('Browser action stopped.'));
407
- this.#spent.add(request.id);
408
- void this.#release('stopped');
409
- void this.#persistStop(true).catch(() => { });
410
- };
411
- ctx.signal?.addEventListener('abort', cancel, { once: true });
412
- try {
413
- this.#state = 'starting';
414
- await this.driver.start();
415
- controller.signal.throwIfAborted();
416
+ #under(ctx, action, run) {
417
+ return this.#serial(async () => {
416
418
  ctx.signal?.throwIfAborted();
417
- this.#state = 'running';
418
- return await run(controller);
419
- }
420
- catch (error) {
421
- if (!controller.signal.aborted && error instanceof BrowserPreconditionError) {
422
- await this.#precondition(controller, error);
419
+ if (!ctx.agentId || !ctx.conversationId)
420
+ throw new Error('A browser action belongs to an agent and a conversation.');
421
+ if (!this.#enabled)
422
+ throw new Error('Browser driving is available through buddi serve (dashboard or Telegram), not a separate CLI process.');
423
+ if (this.#state === 'stopped')
424
+ throw new Error(browserStoppedMessage(ctx.surface));
425
+ if (this.#session && (this.#session.ownerId !== ctx.buddi.owner.id || this.#session.agentId !== ctx.agentId || this.#session.conversationId !== ctx.conversationId)) {
426
+ throw new Error('Another conversation owns this page.');
423
427
  }
424
- if (!controller.signal.aborted) {
425
- // A failed fill or a failed typing is an uncertain input: the value may
426
- // be part-way into the field, so the session pauses rather than invites
427
- // a repeat, exactly as a fill or a click does.
428
- this.#state = 'paused';
429
- this.#message = `${error instanceof Error ? error.message : String(error)} The action may have partially completed. Inspect it before resuming; do not repeat a submission.`;
428
+ if (this.#state === 'paused')
429
+ throw new Error('The owner has this page in their hands. Wait for them to give it back.');
430
+ if (!this.#session)
431
+ throw new Error('Open the page with browser.act navigate before using a secret here.');
432
+ this.#open(ctx.ownerRequest, ctx);
433
+ if (this.#card)
434
+ return this.#cardResult(this.#card, false);
435
+ const active = this.#session;
436
+ if (active.steps >= active.maxSteps || Date.parse(active.expiresAt) <= this.#now()) {
437
+ this.#stop('budget', ctx);
438
+ return this.#cardResult(this.park('budget'), false);
430
439
  }
431
- throw error;
432
- }
433
- finally {
434
- ctx.signal?.removeEventListener('abort', cancel);
435
- if (this.#controller === controller)
436
- this.#controller = undefined;
437
- this.#busy = false;
438
- }
440
+ ++active.steps;
441
+ ++active.actions;
442
+ this.#busy = true;
443
+ this.#lastAction = action;
444
+ this.#lastActivity = this.#now();
445
+ this.#message = undefined;
446
+ const controller = new AbortController();
447
+ this.#controller = controller;
448
+ const cancel = () => { controller.abort(ctx.signal?.reason ?? new Error('Browser action stopped.')); void this.#release('idle'); };
449
+ ctx.signal?.addEventListener('abort', cancel, { once: true });
450
+ try {
451
+ this.#state = 'starting';
452
+ await this.driver.start();
453
+ controller.signal.throwIfAborted();
454
+ this.#state = 'running';
455
+ return await run(controller);
456
+ }
457
+ catch (error) {
458
+ if (controller.signal.aborted)
459
+ throw error;
460
+ if (error instanceof BrowserPreconditionError)
461
+ return await this.#precondition(controller, error, ctx);
462
+ // The value may be part-way into the field: the owner looks.
463
+ this.#state = 'running';
464
+ this.#stop('uncertain-input', ctx, 'card');
465
+ return this.#cardResult(this.park('uncertain'), true, `${error instanceof Error ? error.message.replace(/\.$/, '') : String(error)}. I'm not sure that went through.`);
466
+ }
467
+ finally {
468
+ ctx.signal?.removeEventListener('abort', cancel);
469
+ if (this.#controller === controller)
470
+ this.#controller = undefined;
471
+ this.#busy = false;
472
+ }
473
+ });
474
+ }
475
+ /** After a fill or typing the page changed: answer with it, as every action does. */
476
+ async #after(controller, ctx, result) {
477
+ const seen = await this.#look(controller, ctx).catch(() => false);
478
+ return seen ? { ...result, observation: this.#observation, message: observedLine(this.#observation.observedAt) } : result;
439
479
  }
440
480
  /**
441
481
  * One owner secret into one field of the page this conversation drives
442
- * (docs/owner-secrets.md §3, §4).
443
- *
444
- * The order is the security argument. The driver reads the field's frame
445
- * origin, its password mark and its accessible name from the live page — the
446
- * backend reports, the agent never claims (§8) — then core finds the binding,
447
- * the destination checks that target against it, the rule is applied and the
448
- * vault read, and the destination's `deliver` parks the value against the use
449
- * id. Only then does the driver fill, re-checking the origin once more
450
- * against what the use was delivered for. The result is `{ filled: true }`
451
- * or a pending card; a refusal is the refusal's own sentence, and a value
452
- * appears in none of them.
482
+ * (docs/owner-secrets.md §3, §4). The driver reads the field's frame origin,
483
+ * its password mark and its name from the live page; core finds the binding
484
+ * and the destination checks it; the value crosses only into the fill.
453
485
  */
454
486
  async secretFill(input, ctx) {
455
- return this.#under(ctx, 'secret.fill', async () => {
487
+ return this.#under(ctx, 'secret.fill', async (controller) => {
456
488
  if (typeof this.driver.secretFieldInfo !== 'function' || typeof this.driver.secretFillField !== 'function') {
457
- throw new BrowserPreconditionError('secret.fill works in Playwright browser automation or in the buddi extension mode; this mode has no page fields to fill. Switch modes on the dashboard Settings page.');
489
+ throw new BrowserPreconditionError('secret.fill works on web pages (buddi\'s own browser or your Chrome); an app window has no page fields to fill.');
458
490
  }
459
- const facts = await this.driver.secretFieldInfo(input.observation, input.ref);
491
+ const observation = input.observation ?? this.#observation?.id ?? '';
492
+ const facts = await this.driver.secretFieldInfo(observation, input.ref);
460
493
  const secrets = ctx.buddi?.secrets;
461
494
  if (secrets === undefined)
462
495
  throw new Error('This plugin has no secrets area; the owner updates the browser plugin to one that declares it.');
@@ -464,12 +497,10 @@ export class BrowserService {
464
497
  if (secret === undefined) {
465
498
  throw new BrowserPreconditionError(`There is no secret named "${input.name}" bound to this browser's destinations. The owner keeps one in Settings, under Keys and secrets.`);
466
499
  }
467
- // A visible field on an origin the owner bound as browser.field takes
468
- // that binding; the card then names the field (§3).
469
500
  const visibleField = !secret.totp && !facts.password && fieldBoundTo(secret.bindings, facts.origin);
470
501
  const kind = secretKindFor(secret.totp, facts.password, visibleField);
471
502
  if (kind === FORM_KIND && facts.name.trim() === '') {
472
- throw new BrowserPreconditionError('That field has no name the page gives it, so it cannot be a form-field destination. Observe again, or ask the owner to bind the secret to the page instead.');
503
+ throw new BrowserPreconditionError('That field has no name the page gives it, so it cannot be a form-field destination. Pick another ref, or ask the owner to bind the secret to the page instead.');
473
504
  }
474
505
  const named = { origin: facts.origin, field: facts.name };
475
506
  const target = kind === FORM_KIND || (visibleField && facts.name.trim() !== '') ? named : facts.origin;
@@ -482,26 +513,15 @@ export class BrowserService {
482
513
  const value = takeDelivered(outcome.use);
483
514
  if (value === undefined)
484
515
  throw new Error('The use delivered nothing to fill with. Ask for the secret again.');
485
- await this.driver.secretFillField(input.observation, input.ref, value, facts.origin);
486
- this.#needsObservation = true; // The field just changed; the next action observes first.
487
- return { filled: true };
516
+ await this.driver.secretFillField(observation, input.ref, value, facts.origin);
517
+ return this.#after(controller, ctx, { filled: true });
488
518
  });
489
519
  }
490
- /**
491
- * One owner secret typed into the focused field of the focused app
492
- * (owner-secrets.md §3, native typing).
493
- *
494
- * The bundle id is the backend's answer about whatever app is in front right
495
- * now, and the helper re-checks it before the first keystroke, so an app
496
- * switch between the owner's approval and the typing refuses with nothing
497
- * typed. There is no observed target here — the field is whatever the owner
498
- * left focused — which is why the destination's loosest rule is a card every
499
- * time.
500
- */
520
+ /** One owner secret typed into the focused field of the focused app (owner-secrets.md §3, native typing). */
501
521
  async secretType(input, ctx) {
502
- return this.#under(ctx, 'secret.type', async () => {
522
+ return this.#under(ctx, 'secret.type', async (controller) => {
503
523
  if (typeof this.driver.focusedBundleId !== 'function' || typeof this.driver.nativeType !== 'function') {
504
- throw new BrowserPreconditionError('secret.type works in Computer mode, which types into the focused app on this machine through macOS accessibility; this mode has no native typing. Switch modes on the dashboard Settings page.');
524
+ throw new BrowserPreconditionError('secret.type types into an app on this machine; a web page takes secret.fill instead.');
505
525
  }
506
526
  const bundleId = await this.driver.focusedBundleId();
507
527
  if (!bundleId)
@@ -519,32 +539,10 @@ export class BrowserService {
519
539
  if (value === undefined)
520
540
  throw new Error('The use delivered nothing to type. Ask for the secret again.');
521
541
  await this.driver.nativeType(value);
522
- this.#needsObservation = true; // The screen just changed; the next action observes first.
523
- return { typed: true };
542
+ return this.#after(controller, ctx, { typed: true });
524
543
  });
525
544
  }
526
- async #persistStop(stopped) {
527
- if (!this.options.controlFile)
528
- return;
529
- const file = this.options.controlFile;
530
- const write = async () => {
531
- await mkdir(path.dirname(file), { recursive: true, mode: 0o700 });
532
- const temp = `${file}.${randomUUID()}.tmp`;
533
- await writeFile(temp, JSON.stringify({ stopped }), { mode: 0o600 });
534
- await rename(temp, file);
535
- };
536
- const next = this.#diskTail.then(write, write);
537
- this.#diskTail = next.catch(() => { });
538
- await next;
539
- }
540
- /**
541
- * Stop the action, keep the screen if the driver can.
542
- *
543
- * True when there is still something to drive afterwards. A driver with no
544
- * `interrupt` — or one whose page really did go — has its screen closed
545
- * instead, which is the old behaviour and still the honest answer when there
546
- * is nothing left to paint.
547
- */
545
+ /** Stop the action, keep the screen if the driver can. True when there is still something to drive. */
548
546
  async #interrupt() {
549
547
  if (!this.driver.interrupt) {
550
548
  await this.driver.close().catch(() => { });
@@ -560,11 +558,15 @@ export class BrowserService {
560
558
  return this.driver.handReady?.() !== false;
561
559
  }
562
560
  async #release(state) {
563
- this.#needsObservation = false;
561
+ const session = this.#session;
562
+ if (session && this.options.telemetry) {
563
+ this.options.telemetry.record({ type: 'browser.task', outcome: this.#card ? (this.#card.kind === 'budget' ? 'budget' : 'needs-owner') : state === 'stopped' ? 'stopped' : 'done',
564
+ actions: session.actions, seconds: Math.round((this.#now() - session.startedAt) / 1000), cards: session.cards, agent: session.agentId, route: this.#route, ...(session.requestId === 'unattended' ? { mission: true } : {}) });
565
+ }
566
+ if (this.#observation?.url)
567
+ this.#lastUrl = this.#observation.url;
564
568
  this.#handless = false;
565
569
  this.#state = state;
566
- if (this.#session)
567
- this.#spent.add(this.#session.requestId);
568
570
  this.#controller?.abort(new Error(`Browser ${state}. An in-flight submission may have completed; inspect before retrying.`));
569
571
  clearTimeout(this.#expiry);
570
572
  this.#session = undefined;
@@ -572,8 +574,8 @@ export class BrowserService {
572
574
  this.#picture = undefined;
573
575
  this.#lastAction = undefined;
574
576
  this.#message = undefined;
575
- this.#preconditionFailures = 0;
576
- this.#observationFailures = 0;
577
+ this.#card = undefined;
578
+ this.#targetingFailures = 0;
577
579
  await this.driver.close();
578
580
  }
579
581
  /** Only authenticated owner UI handlers call this; it is not an agent tool. */
@@ -582,59 +584,46 @@ export class BrowserService {
582
584
  if (!this.#enabled)
583
585
  throw new Error('The host browser service is unavailable.');
584
586
  if (expectedSessionId !== undefined && this.#session?.id !== expectedSessionId) {
585
- throw new Error('The browser session changed. Refresh before controlling it.');
587
+ throw new Error('The page changed. Refresh before controlling it.');
586
588
  }
587
589
  if (action === 'stop') {
588
- // Revoke in memory before disk IO, so a pending call cannot race it.
589
- const closing = this.#release('stopped');
590
- await this.#persistStop(true);
591
- await closing;
590
+ await this.#release('stopped');
592
591
  }
593
592
  else if (action === 'takeover') {
594
593
  this.#state = 'paused';
595
594
  this.#message = undefined;
595
+ this.#card = undefined;
596
596
  if (this.#busy) {
597
- // The owner presses Take over *because* the agent is working: it
598
- // reached a login, an MFA prompt or a consent banner and is still
599
- // going round on it. That page is the whole point of the button, so
600
- // the action is abandoned and the page is kept. Every branch of
601
- // `execute` that would otherwise decide what this failure means is
602
- // guarded by `controller.signal.aborted`, so aborting here is also
603
- // what stops the interrupted command from overwriting `paused`.
597
+ // Take over is pressed most often *while* the agent works on a login:
598
+ // the action is abandoned and the page kept, when the driver can.
604
599
  this.#controller?.abort(new Error('Owner took control during an action. Inspect the site before retrying.'));
605
600
  this.#picture = undefined;
606
601
  this.#observation = undefined;
607
- this.#needsObservation = !!this.#session;
608
602
  const kept = await this.#interrupt();
609
603
  this.#handless = !kept;
610
604
  this.#message = kept
611
- ? 'The in-flight action was interrupted; the page is still open and yours to use. Resume here when ready, then ask the agent to observe.'
612
- : this.driver.preservesWindows ? 'Computer input was interrupted. Your apps remain open. Inspect the result, resume, then ask the agent to observe.' : 'The in-flight action was interrupted and the window closed. Resume and ask the agent to navigate again.';
605
+ ? 'The action in flight was stopped; the page is yours. Give it back when you are done.'
606
+ : this.driver.preservesWindows ? 'Computer input was interrupted. Your apps remain open. Give it back when you are done.' : 'The action in flight was stopped and the window closed. Give it back and the agent opens the page again.';
613
607
  }
614
608
  else {
615
609
  await this.driver.takeover?.();
616
- this.#message = this.driver.preservesWindows ? 'Computer control is paused. Use the selected app, then resume here and ask the agent to observe.' : 'Use this conversation’s host tab for login or manual work. Resume here when ready, then ask the agent to observe.';
610
+ this.#message = this.driver.preservesWindows ? 'The app is yours. Give it back when you are done.' : 'The page is yours. Give it back when you are done.';
617
611
  }
618
612
  }
619
613
  else if (action === 'resume') {
620
614
  if (this.#busy)
621
- throw new Error('Wait for the interrupted action to settle before resuming.');
622
- await this.#persistStop(false);
615
+ throw new Error('Wait for the interrupted action to settle before giving it back.');
623
616
  this.driver.resume?.();
624
617
  this.#handless = false;
625
- this.#preconditionFailures = 0;
626
- this.#observationFailures = 0;
627
618
  this.#observation = undefined;
628
619
  this.#picture = undefined;
629
- this.#needsObservation = !!this.#session;
630
- if (this.#session && Date.parse(this.#session.expiresAt) <= this.#now())
631
- await this.#release('idle');
620
+ // The owner acted: a fresh budget, and the agent's next action returns the page as the owner left it.
621
+ this.renew();
632
622
  this.#state = this.#session ? 'running' : 'idle';
633
- this.#message = 'Ready. Send a new message to the agent to continue.';
623
+ this.#message = 'Given back. The agent carries on from the page as you left it.';
634
624
  }
635
625
  else {
636
- const stopped = this.#state === 'stopped';
637
- await this.#release(stopped ? 'stopped' : 'idle');
626
+ await this.#release(this.#state === 'stopped' ? 'stopped' : 'idle');
638
627
  }
639
628
  return this.status();
640
629
  };