agents 0.26.0 → 0.28.0

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 (301) hide show
  1. package/README.md +8 -9
  2. package/dist/abortable-C1SpfVoi.js +21 -0
  3. package/dist/abortable-C1SpfVoi.js.map +1 -0
  4. package/dist/{agent-routing-0DR0Tk2v.d.ts → agent-routing-QDcchcQP.d.ts} +16 -16
  5. package/dist/agent-routing.d.ts +1 -1
  6. package/dist/agent-tool-types.d.ts +1 -1
  7. package/dist/{agent-tools-YrATZJu2.d.ts → agent-tools-DHL2XI7u.d.ts} +2 -2
  8. package/dist/agent-tools.d.ts +1 -1
  9. package/dist/ai-ahruGw7e.d.ts +239 -0
  10. package/dist/ai-sdk-Bdsf6mSA.js +2444 -0
  11. package/dist/ai-sdk-Bdsf6mSA.js.map +1 -0
  12. package/dist/apply-chunks-1FheRb9W.js +99 -0
  13. package/dist/apply-chunks-1FheRb9W.js.map +1 -0
  14. package/dist/broadcast-state-CEyI4uAK.js +69 -0
  15. package/dist/broadcast-state-CEyI4uAK.js.map +1 -0
  16. package/dist/browser/ai.d.ts +8 -227
  17. package/dist/browser/ai.js +259 -1
  18. package/dist/browser/ai.js.map +1 -0
  19. package/dist/browser/index.d.ts +56 -46
  20. package/dist/browser/index.js +4 -361
  21. package/dist/browser/{ai-sdk.d.ts → tools/ai-sdk.d.ts} +7 -7
  22. package/dist/browser/{ai-sdk.js → tools/ai-sdk.js} +6 -5
  23. package/dist/browser/tools/ai-sdk.js.map +1 -0
  24. package/dist/browser/tools/pi.d.ts +111 -0
  25. package/dist/browser/tools/pi.js +119 -0
  26. package/dist/browser/tools/pi.js.map +1 -0
  27. package/dist/browser/{tanstack-ai.d.ts → tools/tanstack-ai.d.ts} +39 -37
  28. package/dist/browser/{tanstack-ai.js → tools/tanstack-ai.js} +73 -59
  29. package/dist/browser/tools/tanstack-ai.js.map +1 -0
  30. package/dist/browser-CEdNlsaD.js +481 -0
  31. package/dist/browser-CEdNlsaD.js.map +1 -0
  32. package/dist/{browser-DE3d-RLk.d.ts → browser-D30VlpcA.d.ts} +63 -37
  33. package/dist/{browser-tool-CQ10e6Kj.js → browser-tool-4iomavs_.js} +198 -62
  34. package/dist/browser-tool-4iomavs_.js.map +1 -0
  35. package/dist/{browser-tool-DuNdlwZ9.d.ts → browser-tool-vtrPOV8e.d.ts} +25 -6
  36. package/dist/{capability-B4WbF81e.js → capability-DBAKc6UZ.js} +1 -3
  37. package/dist/capability-DBAKc6UZ.js.map +1 -0
  38. package/dist/{capability-runner-DBAnGr6L.d.ts → capability-runner-BiVUtjqC.d.ts} +9 -7
  39. package/dist/channel-Bak_6zDP.d.ts +333 -0
  40. package/dist/chat/index.d.ts +11 -9
  41. package/dist/chat/index.js +5 -194
  42. package/dist/chat/index.js.map +1 -1
  43. package/dist/chat/react.d.ts +2 -4
  44. package/dist/chat/react.js +3 -1
  45. package/dist/chat/react.js.map +1 -1
  46. package/dist/chat-sdk/index.d.ts +1 -1
  47. package/dist/chat-sdk/index.js +1 -1
  48. package/dist/cli.js +144 -0
  49. package/dist/{client-je3koD9Z.d.ts → client-BGIQKJhX.d.ts} +2 -2
  50. package/dist/{client-fyQrLGkD.js → client-BnYbNT3z.js} +29 -5
  51. package/dist/client-BnYbNT3z.js.map +1 -0
  52. package/dist/client-tools-aIBO0Fk7.d.ts +53 -0
  53. package/dist/client.d.ts +1 -1
  54. package/dist/{connector-58XDGvc3.js → connector-CtZylXdk.js} +3 -603
  55. package/dist/connector-CtZylXdk.js.map +1 -0
  56. package/dist/{connector-Cl-VqPmA.d.ts → connector-DEXzVoaY.d.ts} +9 -374
  57. package/dist/conversations-FjHDRZyD.d.ts +192 -0
  58. package/dist/{current-agent-vAk_5JMt.d.ts → current-agent-CKgT5d1O.d.ts} +3 -5
  59. package/dist/current-agent-DhoDkSnH.js.map +1 -1
  60. package/dist/daemon-core-Buubj-y1.js +481 -0
  61. package/dist/daemon-core-Buubj-y1.js.map +1 -0
  62. package/dist/daemon-core-CbohVPAu.d.ts +132 -0
  63. package/dist/{do-oauth-client-provider-Tmf1vgKz.d.ts → do-oauth-client-provider-DfsUcpc3.d.ts} +7 -1
  64. package/dist/{durable-object-lifecycle-HhgOMWq9.d.ts → durable-object-lifecycle-DOI_bzCH.d.ts} +2 -2
  65. package/dist/{channels/email.d.ts → experimental/channels/email/index.d.ts} +25 -12
  66. package/dist/{channels/email.js → experimental/channels/email/index.js} +13 -35
  67. package/dist/experimental/channels/email/index.js.map +1 -0
  68. package/dist/experimental/channels/index.d.ts +270 -0
  69. package/dist/experimental/channels/index.js +1186 -0
  70. package/dist/experimental/channels/index.js.map +1 -0
  71. package/dist/{channels/slack.d.ts → experimental/channels/slack/index.d.ts} +19 -9
  72. package/dist/experimental/channels/slack/index.js +267 -0
  73. package/dist/experimental/channels/slack/index.js.map +1 -0
  74. package/dist/{channels/telegram.d.ts → experimental/channels/telegram/index.d.ts} +19 -9
  75. package/dist/experimental/channels/telegram/index.js +198 -0
  76. package/dist/experimental/channels/telegram/index.js.map +1 -0
  77. package/dist/experimental/channels/web/ai-sdk.d.ts +55 -0
  78. package/dist/experimental/channels/web/ai-sdk.js +266 -0
  79. package/dist/experimental/channels/web/ai-sdk.js.map +1 -0
  80. package/dist/experimental/channels/web/client.d.ts +97 -0
  81. package/dist/experimental/channels/web/client.js +349 -0
  82. package/dist/experimental/channels/web/client.js.map +1 -0
  83. package/dist/experimental/channels/web/index.d.ts +189 -0
  84. package/dist/experimental/channels/web/index.js +332 -0
  85. package/dist/experimental/channels/web/index.js.map +1 -0
  86. package/dist/gateway-BFO6vRDn.d.ts +100 -0
  87. package/dist/handle-zAzh0UW2.d.ts +460 -0
  88. package/dist/harness/ai-sdk/index.d.ts +175 -0
  89. package/dist/harness/ai-sdk/index.js +605 -0
  90. package/dist/harness/ai-sdk/index.js.map +1 -0
  91. package/dist/harness/container/daemon/index.d.ts +76 -0
  92. package/dist/harness/container/daemon/index.js +3 -0
  93. package/dist/harness/container/index.d.ts +740 -0
  94. package/dist/harness/container/index.js +2152 -0
  95. package/dist/harness/container/index.js.map +1 -0
  96. package/dist/harness/container/runtime/index.d.ts +144 -0
  97. package/dist/harness/container/runtime/index.js +1082 -0
  98. package/dist/harness/container/runtime/index.js.map +1 -0
  99. package/dist/harness/opencode/index.d.ts +369 -0
  100. package/dist/harness/opencode/index.js +1072 -0
  101. package/dist/harness/opencode/index.js.map +1 -0
  102. package/dist/harness/pi/index.d.ts +3 -2
  103. package/dist/harness/pi/index.js +3 -3
  104. package/dist/harness/store/index.d.ts +24 -0
  105. package/dist/harness/store/index.js +2 -0
  106. package/dist/harness/think/index.d.ts +821 -0
  107. package/dist/harness/think/index.js +2721 -0
  108. package/dist/harness/think/index.js.map +1 -0
  109. package/dist/harness-B6B9S3rb.d.ts +203 -0
  110. package/dist/{images-iiTDSyRu.js → images-Ce9SCu3X.js} +2 -248
  111. package/dist/images-Ce9SCu3X.js.map +1 -0
  112. package/dist/{index-BreL0YrQ.d.ts → index-BEL3ZV-s.d.ts} +2 -6
  113. package/dist/index-CBt8oRJt.d.ts +198 -0
  114. package/dist/index.d.ts +5 -5
  115. package/dist/index.js +2 -2
  116. package/dist/ingress-EFbrS547.js +9 -0
  117. package/dist/ingress-EFbrS547.js.map +1 -0
  118. package/dist/input-schema-BQykTEp_.js +20 -0
  119. package/dist/input-schema-BQykTEp_.js.map +1 -0
  120. package/dist/input-schema-D2QAtHZH.js +23 -0
  121. package/dist/input-schema-D2QAtHZH.js.map +1 -0
  122. package/dist/internal-kmw70xwR.js +46 -0
  123. package/dist/internal-kmw70xwR.js.map +1 -0
  124. package/dist/internal_context.d.ts +1 -1
  125. package/dist/lifecycle/index.d.ts +3 -3
  126. package/dist/lifecycle/index.js +2 -2
  127. package/dist/{lifecycle-CFu6OV03.js → lifecycle-DGorpAmA.js} +2 -4
  128. package/dist/lifecycle-DGorpAmA.js.map +1 -0
  129. package/dist/mcp/client/do-oauth-client-provider.d.ts +1 -1
  130. package/dist/mcp/client/do-oauth-client-provider.js +9 -0
  131. package/dist/mcp/client/do-oauth-client-provider.js.map +1 -1
  132. package/dist/mcp/client/index.d.ts +1 -1
  133. package/dist/mcp/client/index.js +1 -1
  134. package/dist/mcp/client/x402.d.ts +35 -4
  135. package/dist/mcp/client/x402.js +24 -3
  136. package/dist/mcp/client/x402.js.map +1 -1
  137. package/dist/mcp/index.d.ts +1 -1
  138. package/dist/mcp/index.js +2 -2
  139. package/dist/models/ai-sdk/index.d.ts +16 -14
  140. package/dist/models/ai-sdk/index.js +1 -2442
  141. package/dist/models/opencode/index.d.ts +65 -0
  142. package/dist/models/opencode/index.js +285 -0
  143. package/dist/models/opencode/index.js.map +1 -0
  144. package/dist/models/pi-ai/index.d.ts +9 -7
  145. package/dist/models/pi-ai/index.js +2 -1
  146. package/dist/models/pi-ai/index.js.map +1 -1
  147. package/dist/options-CiIsJHXR.d.ts +130 -0
  148. package/dist/protocol-BEgrJYC5.d.ts +331 -0
  149. package/dist/protocol-CukuI73M.d.ts +386 -0
  150. package/dist/protocol-cOklVBBD.js +227 -0
  151. package/dist/protocol-cOklVBBD.js.map +1 -0
  152. package/dist/{protocol-kHsr-f0X.js → protocol-eXeJxhgu.js} +2 -67
  153. package/dist/protocol-eXeJxhgu.js.map +1 -0
  154. package/dist/protocol-y2sSY584.js +148 -0
  155. package/dist/protocol-y2sSY584.js.map +1 -0
  156. package/dist/queue/index.d.ts +1 -1
  157. package/dist/queue/index.js +1 -1
  158. package/dist/{queue-BB-zfIYF.js → queue-CcIjVYTE.js} +2 -2
  159. package/dist/{queue-BB-zfIYF.js.map → queue-CcIjVYTE.js.map} +1 -1
  160. package/dist/react.d.ts +2 -2
  161. package/dist/routing/index.d.ts +2 -2
  162. package/dist/routing/index.js +1 -1
  163. package/dist/{scheduler-RdACNXDP.d.ts → scheduler-BCLESHSC.d.ts} +2 -12
  164. package/dist/{scheduler-DZ3xQfeK.js → scheduler-FIHv2-kJ.js} +2 -4
  165. package/dist/scheduler-FIHv2-kJ.js.map +1 -0
  166. package/dist/schedules/index.d.ts +1 -1
  167. package/dist/schedules/index.js +1 -1
  168. package/dist/serializable.d.ts +1 -1
  169. package/dist/session-store-Do4xkDcf.js +606 -0
  170. package/dist/session-store-Do4xkDcf.js.map +1 -0
  171. package/dist/session-store-DoPY12xM.d.ts +383 -0
  172. package/dist/sessions/index.d.ts +11 -434
  173. package/dist/sessions/index.js +1 -2271
  174. package/dist/sessions-_vN5BEZX.js +2272 -0
  175. package/dist/sessions-_vN5BEZX.js.map +1 -0
  176. package/dist/settings-C45hDliX.js +253 -0
  177. package/dist/settings-C45hDliX.js.map +1 -0
  178. package/dist/{transport-PfFnt-Ld.d.ts → settings-NgGwF7Qt.d.ts} +14 -208
  179. package/dist/{src-BZeu-SCD.js → src-CQxJFv4l.js} +8 -8
  180. package/dist/src-CQxJFv4l.js.map +1 -0
  181. package/dist/stall-watchdog-BpRF2uwG.js +195 -0
  182. package/dist/stall-watchdog-BpRF2uwG.js.map +1 -0
  183. package/dist/state/index.d.ts +1 -1
  184. package/dist/state/index.js +1 -3
  185. package/dist/state/index.js.map +1 -1
  186. package/dist/store-BKM4Xm9M.d.ts +332 -0
  187. package/dist/store-CslVzfN7.js +458 -0
  188. package/dist/store-CslVzfN7.js.map +1 -0
  189. package/dist/streams/index.d.ts +1 -1
  190. package/dist/streams/index.js +1 -1
  191. package/dist/{streams-DW-UCOUc.js → streams-lsHMJhRW.js} +17 -4
  192. package/dist/streams-lsHMJhRW.js.map +1 -0
  193. package/dist/{streams-Cmkj9QfW.d.ts → streams-vrCtbUIn.d.ts} +2 -2
  194. package/dist/sub-routing.d.ts +1 -1
  195. package/dist/tasks/index.d.ts +1 -1
  196. package/dist/tasks/index.js +1 -1
  197. package/dist/{tasks-68DESxf0.js → tasks-BN_5AWqI.js} +3 -2
  198. package/dist/tasks-BN_5AWqI.js.map +1 -0
  199. package/dist/{tasks-9YxYtByh.d.ts → tasks-E89KdwkS.d.ts} +2 -2
  200. package/dist/tool-CTp72Jb_.d.ts +278 -0
  201. package/dist/tool-CxKsvxjm.js +1126 -0
  202. package/dist/tool-CxKsvxjm.js.map +1 -0
  203. package/dist/tool-DoVberpN.d.ts +301 -0
  204. package/dist/tool-cQRkwSZZ.js +410 -0
  205. package/dist/tool-cQRkwSZZ.js.map +1 -0
  206. package/dist/tool-helpers-O5BDVEAY.js +58 -0
  207. package/dist/tool-helpers-O5BDVEAY.js.map +1 -0
  208. package/dist/transport-k2mFrtL8.d.ts +200 -0
  209. package/dist/turns-DCV3ycDl.js +317 -0
  210. package/dist/turns-DCV3ycDl.js.map +1 -0
  211. package/dist/voice/client.js +1 -1
  212. package/dist/voice/index.d.ts +2 -2
  213. package/dist/voice/index.js +1 -1
  214. package/dist/web/fetch/index.d.ts +89 -0
  215. package/dist/web/fetch/index.js +20 -0
  216. package/dist/web/fetch/index.js.map +1 -0
  217. package/dist/web/fetch/tools/ai-sdk.d.ts +80 -0
  218. package/dist/web/fetch/tools/ai-sdk.js +47 -0
  219. package/dist/web/fetch/tools/ai-sdk.js.map +1 -0
  220. package/dist/web/fetch/tools/pi.d.ts +84 -0
  221. package/dist/web/fetch/tools/pi.js +88 -0
  222. package/dist/web/fetch/tools/pi.js.map +1 -0
  223. package/dist/web/fetch/tools/tanstack-ai.d.ts +78 -0
  224. package/dist/web/fetch/tools/tanstack-ai.js +45 -0
  225. package/dist/web/fetch/tools/tanstack-ai.js.map +1 -0
  226. package/dist/web/search/index.d.ts +58 -0
  227. package/dist/web/search/index.js +2 -0
  228. package/dist/web/search/tools/ai-sdk.d.ts +77 -0
  229. package/dist/web/search/tools/ai-sdk.js +46 -0
  230. package/dist/web/search/tools/ai-sdk.js.map +1 -0
  231. package/dist/web/search/tools/pi.d.ts +82 -0
  232. package/dist/web/search/tools/pi.js +89 -0
  233. package/dist/web/search/tools/pi.js.map +1 -0
  234. package/dist/web/search/tools/tanstack-ai.d.ts +71 -0
  235. package/dist/web/search/tools/tanstack-ai.js +46 -0
  236. package/dist/web/search/tools/tanstack-ai.js.map +1 -0
  237. package/dist/websockets/index.d.ts +12 -296
  238. package/dist/websockets/index.js +1 -1
  239. package/dist/{websockets-Ci-LZFHH.js → websockets-C3zy8YR0.js} +20 -8
  240. package/dist/websockets-C3zy8YR0.js.map +1 -0
  241. package/dist/{wire-types-CrjKvDyi.d.ts → wire-types-Cv0iwjk5.d.ts} +3 -51
  242. package/dist/workflow-types.d.ts +1 -1
  243. package/dist/workflows.d.ts +1 -1
  244. package/dist/workflows.js +1 -1
  245. package/docs/browse-the-web.md +29 -1
  246. package/docs/fetch-the-web.md +276 -0
  247. package/docs/harnesses/pi.md +25 -0
  248. package/docs/harnesses/think.md +215 -0
  249. package/docs/index.md +99 -75
  250. package/docs/lifecycle.md +42 -3
  251. package/docs/queue.md +2 -3
  252. package/docs/scheduling.md +2 -6
  253. package/docs/search-the-web.md +135 -0
  254. package/package.json +148 -44
  255. package/dist/ai-fm7xx1BK.js +0 -312
  256. package/dist/ai-fm7xx1BK.js.map +0 -1
  257. package/dist/browser/ai-sdk.js.map +0 -1
  258. package/dist/browser/index.js.map +0 -1
  259. package/dist/browser/tanstack-ai.js.map +0 -1
  260. package/dist/browser-tool-CQ10e6Kj.js.map +0 -1
  261. package/dist/capability-B4WbF81e.js.map +0 -1
  262. package/dist/channel-Bnm4S7T2.d.ts +0 -491
  263. package/dist/channels/ai-sdk.d.ts +0 -46
  264. package/dist/channels/ai-sdk.js +0 -120
  265. package/dist/channels/ai-sdk.js.map +0 -1
  266. package/dist/channels/email.js.map +0 -1
  267. package/dist/channels/index.d.ts +0 -233
  268. package/dist/channels/index.js +0 -608
  269. package/dist/channels/index.js.map +0 -1
  270. package/dist/channels/slack.js +0 -614
  271. package/dist/channels/slack.js.map +0 -1
  272. package/dist/channels/tanstack-ai.d.ts +0 -39
  273. package/dist/channels/tanstack-ai.js +0 -17
  274. package/dist/channels/tanstack-ai.js.map +0 -1
  275. package/dist/channels/telegram.js +0 -427
  276. package/dist/channels/telegram.js.map +0 -1
  277. package/dist/channels/voice.d.ts +0 -45
  278. package/dist/channels/voice.js +0 -122
  279. package/dist/channels/voice.js.map +0 -1
  280. package/dist/client-fyQrLGkD.js.map +0 -1
  281. package/dist/connector-58XDGvc3.js.map +0 -1
  282. package/dist/images-iiTDSyRu.js.map +0 -1
  283. package/dist/index-BB0kqhIz.d.ts +0 -101
  284. package/dist/ingress-BfetZbMO.js +0 -83
  285. package/dist/ingress-BfetZbMO.js.map +0 -1
  286. package/dist/internal-CYlgHl1l.js +0 -59
  287. package/dist/internal-CYlgHl1l.js.map +0 -1
  288. package/dist/lifecycle-CFu6OV03.js.map +0 -1
  289. package/dist/models/ai-sdk/index.js.map +0 -1
  290. package/dist/protocol-kHsr-f0X.js.map +0 -1
  291. package/dist/scheduler-DZ3xQfeK.js.map +0 -1
  292. package/dist/sessions/index.js.map +0 -1
  293. package/dist/src-BZeu-SCD.js.map +0 -1
  294. package/dist/streams-DW-UCOUc.js.map +0 -1
  295. package/dist/surface-bZZJqBka.js +0 -17
  296. package/dist/surface-bZZJqBka.js.map +0 -1
  297. package/dist/tasks-68DESxf0.js.map +0 -1
  298. package/dist/tool-schema-CBjGPrsQ.js +0 -31
  299. package/dist/tool-schema-CBjGPrsQ.js.map +0 -1
  300. package/dist/websockets-Ci-LZFHH.js.map +0 -1
  301. package/docs/channels.md +0 -323
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-tool-4iomavs_.js","names":[],"sources":["../src/browser/session-connector.ts","../src/browser/browser-tool.ts"],"sourcesContent":["import {\n CodemodeConnector,\n MAX_DURABLE_VALUE_BYTES,\n type ConnectorTool,\n type ConnectorTools,\n type ToolExecuteContext\n} from \"@cloudflare/codemode\";\nimport { validateConnectorArgs } from \"./connector-validation\";\nimport {\n CDP_METHOD_NOT_FOUND,\n CdpProtocolError,\n type CdpConnection\n} from \"./cdp-connection\";\nimport type { BrowserConnection, BrowserConnectOptions } from \"./browser\";\nimport type { SearchableCdpSpec } from \"./spec\";\n\n/**\n * Where a {@link BrowserSessionConnector} gets its browser. Usually a\n * `Browser` installed on the host's Lifecycle.\n */\nexport interface BrowserSource {\n /** The browser's name, for log messages. */\n readonly name: string;\n /**\n * Reattach to the browser (or replace it) and open a CDP connection for\n * a scope. A source that ignores `scope` shares one active tab between\n * every caller.\n */\n connect(options?: BrowserConnectOptions): Promise<BrowserConnection>;\n}\n\nexport interface BrowserSessionConnectorOptions {\n /** The persistent browser this connector drives. */\n browser: BrowserSource;\n /**\n * The scope this connector's executions work in: they share one active\n * tab, kept apart from other scopes'. Defaults to the browser's default\n * scope.\n */\n scope?: string;\n}\n\n/** A tab a page opened on its own during an execution. */\nexport interface BrowserNewTab {\n targetId: string;\n url?: string;\n title?: string;\n}\n\n/**\n * What happened to the browser during one execution, beyond the code's own\n * result — read by the tool after the run via\n * {@link BrowserSessionConnector.takeReport}.\n */\nexport interface BrowserExecutionReport {\n /** The browser was replaced before this run; earlier page state is gone. */\n restarted: boolean;\n /** Tabs the page opened itself (popups, `target=_blank`). */\n newTabs: BrowserNewTab[];\n /**\n * The tab this scope was working in was closed by someone else (another\n * scope, or a person in Live View), so `\"active\"` will be a new blank tab.\n */\n tabClosed: boolean;\n /** Another scope is working in this scope's active tab too. */\n tabShared: boolean;\n}\n\n/** `sessionId` value that addresses the tab the agent is working in. */\nexport const ACTIVE_PAGE_SESSION = \"active\";\n\n/**\n * `cdp.attachToTarget` returns `{ sessionId: \"target:<targetId>\" }` — a\n * stable handle rather than a connection-scoped CDP session id, so replayed\n * code computes identical arguments. `send` resolves it on the live socket.\n */\nconst ATTACH_HANDLE_PREFIX = \"target:\";\n\n/** Chrome's JSON-RPC code for a CDP session id it doesn't know. */\nconst CDP_SESSION_NOT_FOUND = -32001;\n\n/**\n * Codemode records every `send` result for replay and fails the run when one\n * is over {@link MAX_DURABLE_VALUE_BYTES}, telling the model to write to a\n * file, which this sandbox can't. A full-page screenshot is the usual\n * culprit, so say how to take a smaller one instead.\n */\nfunction assertScreenshotFits(result: unknown): void {\n // Measure the result as codemode stores it (JSON), not just the data, so a\n // screenshot just under the limit can't slip past with its JSON framing.\n const size = JSON.stringify(result ?? null).length;\n if (size <= MAX_DURABLE_VALUE_BYTES) return;\n const megabytes = (size / 1_000_000).toFixed(1);\n throw new Error(\n `The screenshot result is ${megabytes} MB, over the 1 MB limit on a ` +\n `cdp.send result. Capture just the viewport (no captureBeyondViewport ` +\n `or clip larger than the window), or pass format: \"jpeg\" with ` +\n `quality: 60.`\n );\n}\n\n/** {@link BrowserSessionConnector} `#liveParams`: nothing to detach. */\nconst DETACHED = Symbol(\"detached\");\n\n/** Reports awaiting their tool call; bounded in case a caller never reads. */\nconst MAX_PENDING_REPORTS = 100;\n\n/**\n * Commands that would end the browser. The host owns its lifetime, so the\n * model can't close it out from under the agent (and lose its logins).\n */\nconst BROWSER_LIFETIME_COMMANDS = new Set([\n \"Browser.close\",\n \"Browser.crash\",\n \"Browser.crashGpuProcess\"\n]);\n\n/** A CDP target id — for this connector, a tab. */\ntype TargetId = string & { readonly __brand: \"TargetId\" };\n\n/** A CDP session id from `Target.attachToTarget`, valid on one socket only. */\ntype LiveSessionId = string & { readonly __brand: \"LiveSessionId\" };\n\n/** The stable `sessionId` handle `cdp.attachToTarget` gives the model. */\ntype AttachHandle = `${typeof ATTACH_HANDLE_PREFIX}${string}`;\n\ninterface TargetInfo {\n targetId: TargetId;\n type: string;\n url?: string;\n title?: string;\n /** The tab that opened this one (popups, `target=_blank` links). */\n openerId?: TargetId;\n}\n\n/** Per-execution state for one pass. Dropped when the pass ends. */\ninterface ExecutionState {\n executionId: string;\n connected: BrowserConnection;\n /** Live CDP session per target, valid on this socket only. */\n attached: Map<TargetId, LiveSessionId>;\n /**\n * Tabs this pass attached to, through the connector or a raw\n * `Target.attachToTarget`. Their popups are this pass's new tabs.\n */\n workedIn: Set<TargetId>;\n /** Page targets open when the pass connected. */\n initialPages: Set<TargetId>;\n /** The tab `\"active\"` resolves to — decided lazily on first use. */\n activeTargetId?: TargetId;\n /** Whether {@link activeTargetId} was decided (vs. never needed). */\n activeResolved: boolean;\n /** Tabs this pass closed with `Target.closeTarget`. */\n closed: Set<TargetId>;\n}\n\n/**\n * How to use the `cdp` connector, one rule per line. `codemode.describe(\"cdp\")`\n * returns these, and `browserTool` puts them in its description. Each rule\n * fixes a mistake models make with CDP, or states something about this\n * browser they can't know; leave out what a model knows already.\n */\nexport const BROWSER_INSTRUCTIONS = [\n \"The browser persists between runs: tabs, cookies, and logins are still there next time. You never start or close it.\",\n \"If the browser was replaced (idle timeout, crash), the result says restarted: true and earlier tabs and logins are gone. Before an action that matters (submitting a form, a purchase), check you're on the page you expect.\",\n 'Page-scoped commands (Page.*, Runtime.*, DOM.*, Input.*, Network.*, Emulation.*) need sessionId: \"active\", your tab, which is remembered between runs. Browser.* and Target.* commands take no sessionId.',\n \"Other open tabs (Target.getTargets) may belong to other conversations using this browser: don't close, navigate, or attach to a tab you didn't open unless the user asks.\",\n \"Target.createTarget opens a tab and makes it active. To switch to another open tab, call cdp.attachToTarget({ targetId }); the sessionId it returns keeps working in later runs, while one from a raw Target.attachToTarget only works in the current run.\",\n \"Tabs a page opens itself (popups, target=_blank links) don't become active; the result lists them as newTabs.\",\n \"Runtime.evaluate: pass returnByValue: true, or objects come back as a remote reference with no value, and awaitPromise: true for async expressions. The value is at result.value. A thrown error doesn't reject: check exceptionDetails.\",\n \"Page.navigate returns before the page loads and doesn't throw when it fails: check errorText, then poll document.readyState with Runtime.evaluate until it is 'complete'.\",\n \"Pick out what you need inside Runtime.evaluate and return only that. Results over about 24,000 characters are cut short, and a single cdp.send result over 1 MB (a full-page screenshot, say) fails the run.\"\n].join(\"\\n\");\n\n/**\n * Codemode connector exposing one host-named, persistent browser over the\n * Chrome DevTools Protocol as the `cdp` global.\n *\n * The model never manages sessions: every execution reattaches to the\n * browser (or gets a replacement, reported as `restarted`), and\n * `sessionId: \"active\"` addresses the tab it last worked in. The active tab\n * is stored per scope (see {@link BrowserSessionConnectorOptions.scope}), so\n * it survives between executions for as long as the tab does, and one\n * scope's executions never land in another scope's tab unless the model\n * attaches to it.\n *\n * The CDP socket is per pass: opened on the first call, closed when the pass\n * ends. The browser itself outlives the execution.\n */\nexport class BrowserSessionConnector extends CodemodeConnector {\n readonly #browser: BrowserSource;\n readonly #scope: string | undefined;\n #states = new Map<string, ExecutionState>();\n #connecting = new Map<string, Promise<ExecutionState>>();\n /**\n * In memory, on this instance. An execution resumed after an approval\n * pause may run on a fresh connector, whose report starts over. Nothing\n * pauses today — the browser tool wires no approval tools — so reporting\n * across a resume is left for when approvals are added.\n *\n * The same goes for raw CDP session ids from `Target.attachToTarget` sent\n * through `send`: they belong to one pass's socket, so a replay after a\n * pause would reuse a dead id. The stable handles from `attachToTarget`\n * are the replay-safe path.\n */\n #reports = new Map<string, BrowserExecutionReport>();\n\n constructor(\n ctx: DurableObjectState | ExecutionContext,\n options: BrowserSessionConnectorOptions\n ) {\n super(ctx, {});\n this.#browser = options.browser;\n this.#scope = options.scope;\n }\n\n name(): string {\n return \"cdp\";\n }\n\n protected instructions(): string {\n return BROWSER_INSTRUCTIONS;\n }\n\n protected override tool(name: string, tool: ConnectorTool): ConnectorTool {\n return validateConnectorArgs(this.name(), name, tool);\n }\n\n protected tools(): ConnectorTools {\n return {\n send: {\n description:\n 'Send a CDP command and return its method result directly. Pass sessionId: \"active\" for page-scoped commands; omit it for Browser/Target commands.',\n inputSchema: {\n type: \"object\",\n properties: {\n method: {\n type: \"string\",\n description: 'CDP method, e.g. \"Page.navigate\"'\n },\n params: {\n type: \"object\",\n description: \"CDP command parameters\"\n },\n sessionId: {\n type: \"string\",\n description:\n '\"active\" for the current tab, or a handle from attachToTarget. Omit for Browser/Target commands.'\n },\n timeoutMs: {\n type: \"number\",\n description: \"Per-command timeout override in milliseconds\"\n }\n },\n required: [\"method\"]\n },\n execute: async (args, ctx) => {\n const { method, params, sessionId, timeoutMs } = args as {\n method: string;\n params?: Record<string, unknown>;\n sessionId?: string;\n timeoutMs?: number;\n };\n if (BROWSER_LIFETIME_COMMANDS.has(method)) {\n throw new Error(\n `${method} is not available: this browser is managed for you ` +\n `and persists between runs. To close a tab, send ` +\n `Target.closeTarget with its targetId.`\n );\n }\n const state = await this.#state(this.#executionId(ctx));\n const live = await this.#resolveSessionId(state, sessionId);\n const liveParams = this.#liveParams(state, method, params);\n if (liveParams === DETACHED) return {};\n let result: unknown;\n try {\n result = await state.connected.cdp.send(method, liveParams, {\n sessionId: live,\n timeoutMs\n });\n } catch (error) {\n throw await this.#teach(state, error, method, sessionId);\n }\n this.#observe(state, method, liveParams, result);\n if (method === \"Page.captureScreenshot\") {\n assertScreenshotFits(result);\n }\n return result;\n }\n },\n\n attachToTarget: {\n description:\n \"Switch to an open tab: make it the active tab and return { sessionId } — a handle you can pass to page-scoped send calls for that tab.\",\n inputSchema: {\n type: \"object\",\n properties: {\n targetId: {\n type: \"string\",\n description: \"Target id from Target.getTargets/createTarget\"\n },\n timeoutMs: { type: \"number\" }\n },\n required: [\"targetId\"]\n },\n outputSchema: {\n type: \"object\",\n properties: {\n sessionId: {\n type: \"string\",\n description: \"Session handle for page-scoped send calls\"\n }\n },\n required: [\"sessionId\"]\n },\n execute: async (args, ctx) => {\n const { targetId, timeoutMs } = args as {\n targetId: TargetId;\n timeoutMs?: number;\n };\n const state = await this.#state(this.#executionId(ctx));\n await this.#attach(state, targetId, timeoutMs);\n this.#setActive(state, targetId);\n return { sessionId: attachHandle(targetId) };\n }\n },\n\n spec: {\n description:\n \"Return the searchable Chrome DevTools Protocol spec: domains with their commands, events, and types.\",\n replay: \"reexecute\",\n inputSchema: { type: \"object\", properties: {} },\n execute: async (_args, ctx): Promise<SearchableCdpSpec> => {\n const state = await this.#state(this.#executionId(ctx));\n return state.connected.spec();\n }\n },\n\n getDebugLog: {\n description:\n \"Return recent CDP protocol traffic (sends, receives, warnings) for this execution — useful to diagnose failures and timeouts.\",\n replay: \"reexecute\",\n inputSchema: {\n type: \"object\",\n properties: {\n limit: {\n type: \"number\",\n minimum: 1,\n description:\n \"Max entries to return, newest last (default 50; only the last 400 are kept)\"\n }\n }\n },\n execute: async (args, ctx) => {\n const { limit } = (args ?? {}) as { limit?: number };\n const state = await this.#state(this.#executionId(ctx));\n return state.connected.cdp.getDebugLog(limit);\n }\n },\n\n clearDebugLog: {\n description: \"Clear the CDP debug log for this execution.\",\n inputSchema: { type: \"object\", properties: {} },\n execute: async (_args, ctx) => {\n const state = await this.#state(this.#executionId(ctx));\n state.connected.cdp.clearDebugLog();\n return null;\n }\n }\n };\n }\n\n // ── Codemode execution hooks ─────────────────────────────────────────────\n\n /**\n * The pass is over: note tabs the page opened, save the scope's active\n * tab, note whether another scope shares it, and drop the socket. The\n * browser stays alive.\n */\n override async onPassEnd(executionId: string): Promise<void> {\n const state = this.#states.get(executionId);\n if (!state) return;\n this.#states.delete(executionId);\n try {\n const open = await this.#recordNewTabs(executionId, state);\n const active = await this.#saveActiveTarget(state, open);\n if (active && state.activeResolved) {\n await this.#recordSharedTab(state, active);\n }\n } finally {\n state.connected.cdp.disconnect();\n }\n }\n\n /** Nothing per execution outlives the pass; the named browser persists. */\n override async disposeExecution(executionId: string): Promise<void> {\n const state = this.#states.get(executionId);\n if (!state) return;\n this.#states.delete(executionId);\n state.connected.cdp.disconnect();\n }\n\n /**\n * Take (and forget) what happened to the browser during an execution.\n * `undefined` when the execution never touched the browser. Covers the\n * passes this instance ran; see the note on `#reports`.\n */\n takeReport(executionId: string): BrowserExecutionReport | undefined {\n const report = this.#reports.get(executionId);\n this.#reports.delete(executionId);\n return report;\n }\n\n // ── Internals ────────────────────────────────────────────────────────────\n\n #executionId(ctx: ToolExecuteContext | undefined): string {\n if (!ctx?.executionId) {\n throw new Error(\"Browser tools must run inside a codemode execution\");\n }\n return ctx.executionId;\n }\n\n /**\n * Connect once per pass. Concurrent first calls (model code that uses\n * Promise.all despite the instructions) share one connect.\n */\n #state(executionId: string): Promise<ExecutionState> {\n const existing = this.#states.get(executionId);\n if (existing) return Promise.resolve(existing);\n const inFlight = this.#connecting.get(executionId);\n if (inFlight) return inFlight;\n const promise = this.#connect(executionId).finally(() => {\n this.#connecting.delete(executionId);\n });\n this.#connecting.set(executionId, promise);\n return promise;\n }\n\n async #connect(executionId: string): Promise<ExecutionState> {\n const connected = await this.#browser.connect(\n this.#scope === undefined ? undefined : { scope: this.#scope }\n );\n let initialPages: TargetInfo[];\n try {\n initialPages = await this.#pages(connected.cdp);\n } catch (error) {\n connected.cdp.disconnect();\n throw error;\n }\n const state: ExecutionState = {\n executionId,\n connected,\n attached: new Map(),\n workedIn: new Set(),\n initialPages: new Set(initialPages.map((page) => page.targetId)),\n activeResolved: false,\n closed: new Set()\n };\n this.#states.set(executionId, state);\n this.#report(executionId, connected.restarted);\n return state;\n }\n\n #report(executionId: string, restarted: boolean): BrowserExecutionReport {\n let report = this.#reports.get(executionId);\n if (!report) {\n report = { restarted, newTabs: [], tabClosed: false, tabShared: false };\n this.#reports.set(executionId, report);\n if (this.#reports.size > MAX_PENDING_REPORTS) {\n const oldest = this.#reports.keys().next().value;\n if (oldest !== undefined) this.#reports.delete(oldest);\n }\n }\n // A replacement on any pass means earlier page state is gone.\n report.restarted ||= restarted;\n return report;\n }\n\n /**\n * Add tabs the page opened this pass to the execution's report, and drop\n * earlier ones that have since closed: `newTabs` lists page-opened tabs\n * still open when the execution ends, across every pass. Returns the open\n * tabs, or `undefined` when the browser couldn't be asked.\n */\n async #recordNewTabs(\n executionId: string,\n state: ExecutionState\n ): Promise<Set<TargetId> | undefined> {\n let pages: TargetInfo[];\n try {\n pages = await this.#pages(state.connected.cdp);\n } catch (error) {\n this.#warn(\"list the open tabs\", error);\n return undefined;\n }\n const report = this.#report(executionId, state.connected.restarted);\n const opened = new Set<string>(report.newTabs.map((tab) => tab.targetId));\n // A new tab is this execution's when its opener is a tab this pass\n // worked in, or another of its new tabs (a popup's popup). Chrome sets\n // openerId only on tabs a page opened, never on Target.createTarget\n // tabs, and a popup another scope's page opened meanwhile has that\n // scope's tab as its opener.\n let grew = true;\n while (grew) {\n grew = false;\n for (const page of pages) {\n const opener = page.openerId;\n if (\n !opener ||\n opened.has(page.targetId) ||\n state.initialPages.has(page.targetId)\n ) {\n continue;\n }\n if (state.workedIn.has(opener) || opened.has(opener)) {\n opened.add(page.targetId);\n grew = true;\n }\n }\n }\n report.newTabs = pages\n .filter((page) => opened.has(page.targetId))\n .map(({ targetId, url, title }) => ({ targetId, url, title }));\n return new Set(pages.map((page) => page.targetId));\n }\n\n /**\n * Save the tab this pass settled on, forgetting one that has since closed,\n * and return it. Without the list of open tabs, save the choice\n * unchecked: the next execution checks the stored tab is still open\n * before using it.\n */\n async #saveActiveTarget(\n state: ExecutionState,\n open: Set<TargetId> | undefined\n ): Promise<TargetId | undefined> {\n const stored = state.connected.activeTargetId as TargetId | undefined;\n // A pass that never used \"active\" still sees the stored tab is gone;\n // say so now, since the next pass won't know there was one.\n if (\n !state.activeResolved &&\n stored &&\n open &&\n !open.has(stored) &&\n !state.closed.has(stored)\n ) {\n this.#report(state.executionId, state.connected.restarted).tabClosed =\n true;\n }\n const candidate = state.activeResolved ? state.activeTargetId : stored;\n const active =\n candidate && (!open || open.has(candidate)) ? candidate : undefined;\n if (active === stored) return active;\n try {\n await state.connected.setActiveTarget(active);\n } catch (error) {\n this.#warn(\"save the active tab\", error);\n }\n return active;\n }\n\n /** Report when another scope is working in this pass's tab too. */\n async #recordSharedTab(\n state: ExecutionState,\n active: TargetId\n ): Promise<void> {\n try {\n const others = await state.connected.targetsInOtherScopes();\n if (others.has(active)) {\n this.#report(state.executionId, state.connected.restarted).tabShared =\n true;\n }\n } catch (error) {\n this.#warn(\"check whether the active tab is shared\", error);\n }\n }\n\n #warn(action: string, error: unknown): void {\n console.warn(\n `[agents/browser] Failed to ${action} for browser \"${this.#browser.name}\"`,\n error\n );\n }\n\n async #pages(cdp: CdpConnection): Promise<TargetInfo[]> {\n const result = (await cdp.send(\"Target.getTargets\")) as {\n targetInfos?: TargetInfo[];\n };\n return (result?.targetInfos ?? []).filter((info) => info.type === \"page\");\n }\n\n async #resolveSessionId(\n state: ExecutionState,\n sessionId: string | undefined\n ): Promise<LiveSessionId | undefined> {\n if (sessionId === ACTIVE_PAGE_SESSION) {\n return this.#attach(state, await this.#activeTarget(state));\n }\n if (isAttachHandle(sessionId)) {\n return this.#attach(state, targetOfHandle(sessionId));\n }\n // Omitted, or a raw CDP session id the model got from send().\n return sessionId as LiveSessionId | undefined;\n }\n\n /**\n * Decide which tab `\"active\"` means, once per pass: the scope's stored tab\n * if it is still open, else a new blank tab. Never a tab the scope didn't\n * open, even a blank one: it may be another scope's, or a popup.\n */\n async #activeTarget(state: ExecutionState): Promise<TargetId> {\n if (state.activeTargetId) return state.activeTargetId;\n const { connected } = state;\n const pages = await this.#pages(connected.cdp);\n const stored = connected.activeTargetId as TargetId | undefined;\n let targetId = pages.find((page) => page.targetId === stored)?.targetId;\n if (!targetId && stored && !state.closed.has(stored)) {\n this.#report(state.executionId, connected.restarted).tabClosed = true;\n }\n if (!targetId) {\n const created = (await connected.cdp.send(\"Target.createTarget\", {\n url: \"about:blank\"\n })) as { targetId: TargetId };\n targetId = created.targetId;\n }\n this.#setActive(state, targetId);\n return targetId;\n }\n\n #setActive(state: ExecutionState, targetId: TargetId | undefined): void {\n state.activeTargetId = targetId;\n state.activeResolved = true;\n }\n\n async #attach(\n state: ExecutionState,\n targetId: TargetId,\n timeoutMs?: number\n ): Promise<LiveSessionId> {\n const existing = state.attached.get(targetId);\n if (existing) return existing;\n const live = (await state.connected.cdp.attachToTarget(targetId, {\n timeoutMs\n })) as LiveSessionId;\n state.attached.set(targetId, live);\n state.workedIn.add(targetId);\n return live;\n }\n\n /** Track tab changes the model makes through raw Target commands. */\n #observe(\n state: ExecutionState,\n method: string,\n params: Record<string, unknown> | undefined,\n result: unknown\n ): void {\n const targetId =\n typeof params?.targetId === \"string\"\n ? (params.targetId as TargetId)\n : undefined;\n if (method === \"Target.createTarget\") {\n const created = (result as { targetId?: unknown } | undefined)?.targetId;\n if (typeof created === \"string\") {\n this.#setActive(state, created as TargetId);\n }\n } else if (method === \"Target.attachToTarget\" && targetId) {\n this.#setActive(state, targetId);\n state.workedIn.add(targetId);\n } else if (method === \"Target.closeTarget\" && targetId) {\n state.attached.delete(targetId);\n state.closed.add(targetId);\n // The next \"active\" use picks a tab afresh.\n if (state.activeTargetId === targetId) state.activeTargetId = undefined;\n } else if (method === \"Target.detachFromTarget\") {\n // Forget a session the model detached, so the next use reattaches.\n for (const [target, live] of state.attached) {\n if (target === targetId || live === params?.sessionId) {\n state.attached.delete(target);\n }\n }\n }\n }\n\n /**\n * Swap a handle in `Target.detachFromTarget`'s `sessionId` param for the\n * live CDP session id. Returns {@link DETACHED} when the handle's tab isn't\n * attached on this socket, so there is nothing to detach.\n */\n #liveParams(\n state: ExecutionState,\n method: string,\n params: Record<string, unknown> | undefined\n ): Record<string, unknown> | undefined | typeof DETACHED {\n const handle = params?.sessionId;\n if (method !== \"Target.detachFromTarget\" || typeof handle !== \"string\") {\n return params;\n }\n if (!isAttachHandle(handle)) return params;\n const live = state.attached.get(targetOfHandle(handle));\n return live ? { ...params, sessionId: live } : DETACHED;\n }\n\n /**\n * Turn the common protocol mistakes into instructions: sending an\n * event as a command, and a page-scoped command without a session.\n */\n async #teach(\n state: ExecutionState,\n error: unknown,\n method: string,\n sessionId: string | undefined\n ): Promise<unknown> {\n if (!(error instanceof CdpProtocolError)) return error;\n if (\n error.code === CDP_SESSION_NOT_FOUND &&\n sessionId &&\n sessionId !== ACTIVE_PAGE_SESSION &&\n !isAttachHandle(sessionId)\n ) {\n return new Error(\n `${error.message}. CDP session ids don't carry over between runs. ` +\n `Use sessionId: \"active\" for the current tab, or the handle from ` +\n `cdp.attachToTarget({ targetId }) for another tab.`\n );\n }\n if (error.code !== CDP_METHOD_NOT_FOUND) return error;\n if (await this.#isEvent(state, method)) {\n return new Error(\n `${error.message}. '${method}' is a CDP *event*, not a command — it ` +\n `cannot be sent. To wait for page state, poll instead (e.g. ` +\n `Runtime.evaluate of document.readyState until \"complete\").`\n );\n }\n if (!sessionId) {\n return new Error(\n `${error.message}. '${method}' is page-scoped: pass sessionId: ` +\n `\"active\" to run it in the current tab — ` +\n `cdp.send({ method: \"${method}\", params, sessionId: \"active\" }).`\n );\n }\n return error;\n }\n\n async #isEvent(state: ExecutionState, method: string): Promise<boolean> {\n try {\n const spec = await state.connected.spec();\n const domain = method.split(\".\")[0];\n return spec.domains.some(\n (d) => d.name === domain && d.events.some((e) => e.event === method)\n );\n } catch {\n return false;\n }\n }\n}\n\nfunction attachHandle(targetId: TargetId): AttachHandle {\n return `${ATTACH_HANDLE_PREFIX}${targetId}`;\n}\n\nfunction isAttachHandle(\n sessionId: string | undefined\n): sessionId is AttachHandle {\n return sessionId?.startsWith(ATTACH_HANDLE_PREFIX) ?? false;\n}\n\nfunction targetOfHandle(handle: AttachHandle): TargetId {\n return handle.slice(ATTACH_HANDLE_PREFIX.length) as TargetId;\n}\n","/**\n * The harness-neutral core of `browserTool`, shared by the adapters in\n * `tools/` (`agents/browser/ai-sdk`, `agents/browser/tanstack-ai`,\n * `agents/browser/pi`).\n * Internal — not an entry point.\n */\nimport {\n createCodemodeRuntime,\n DynamicWorkerExecutor,\n type ProxyToolOutput\n} from \"@cloudflare/codemode\";\nimport { DEFAULT_BROWSER_SCOPE } from \"./browser\";\nimport {\n BROWSER_INSTRUCTIONS,\n BrowserSessionConnector,\n type BrowserExecutionReport,\n type BrowserNewTab,\n type BrowserSource\n} from \"./session-connector\";\nimport { resolveCtx, transformBrowserResult } from \"./tool-helpers\";\n\nexport interface BrowserToolOptions {\n /**\n * The browser the tool drives — usually a `Browser` installed on the\n * host's Lifecycle. Tools built from the same `Browser` share it.\n */\n browser: BrowserSource;\n\n /**\n * WorkerLoader binding for sandboxed code execution.\n *\n * Requires `\"worker_loaders\": [{ \"binding\": \"LOADER\" }]` in wrangler.jsonc.\n */\n loader: WorkerLoader;\n\n /** Sandbox execution timeout in milliseconds. Defaults to 60000 (60s). */\n timeoutMs?: number;\n\n /**\n * Who is driving, when several chats or users share one `Browser`: runs\n * with the same scope share an active tab, and each scope keeps its own.\n * Cookies and logins are shared by every scope. Defaults to `\"shared\"`,\n * one active tab for every tool that leaves it out.\n */\n scope?: string;\n\n /**\n * Durable Object state for the codemode runtime facet. Optional inside an\n * Agent (resolved via `getCurrentAgent()`); pass it explicitly elsewhere.\n *\n * The worker must export the `CodemodeRuntime` class (the\n * `@cloudflare/codemode/vite` plugin does this automatically, or add\n * `export { CodemodeRuntime } from \"@cloudflare/codemode\"` to your entry).\n */\n ctx?: DurableObjectState;\n}\n\n/** The model's input to `browserTool`: JavaScript to run. */\nexport interface BrowserToolInput {\n code: string;\n}\n\n/**\n * The result of one `browserTool` run: the codemode execution result,\n * plus what happened to the browser.\n */\nexport type BrowserToolOutput = ProxyToolOutput & {\n /** The browser was replaced before this run; earlier tabs are gone. */\n restarted?: true;\n /**\n * Sentences telling the model what happened to its browser: it was\n * restarted, its tab was closed by someone else, or another scope is\n * working in its tab too.\n */\n notice?: string;\n /** Tabs the page opened itself (popups, `target=_blank` links). */\n newTabs?: BrowserNewTab[];\n};\n\nconst DEFAULT_TIMEOUT_MS = 60_000;\n\nconst RESTARTED_NOTICE =\n \"The browser was restarted before this run (it expired or was closed): earlier tabs, logins, and page state are gone. Your code ran in a fresh browser — navigate again before relying on page state.\";\n\nconst TAB_CLOSED_NOTICE =\n 'The tab you were working in was closed (by another conversation using this browser, or a person). `sessionId: \"active\"` now opens a blank tab — navigate again before relying on page state.';\n\nconst TAB_SHARED_NOTICE =\n \"Another conversation using this browser is also working in your tab, so its page may change between your runs. Open a tab of your own with Target.createTarget if you need one.\";\n\n/** Scopes whose runtime and connector stay built; older ones are rebuilt. */\nconst MAX_CACHED_SCOPES = 32;\n\n/**\n * A codemode runtime name per browser. Browser names are host-chosen and\n * unrestricted; runtime names allow only `[a-zA-Z0-9_.-]`, so anything else\n * (including `.`, the escape) is hex-escaped.\n */\nfunction browserRuntimeName(name: string): string {\n const escaped = name.replace(\n /[^a-zA-Z0-9_-]/g,\n (char) => `.${char.codePointAt(0)?.toString(16)}.`\n );\n return `browser-tool_${escaped}`;\n}\n\n/**\n * The latest run queued per browser and scope, so runs in one scope go one\n * at a time, even from tools built separately (one per turn, say). Per\n * isolate, which is per Durable Object.\n */\nconst runQueues = new WeakMap<BrowserSource, Map<string, Promise<unknown>>>();\n\nfunction queued<T>(\n browser: BrowserSource,\n scope: string,\n run: () => Promise<T>\n): Promise<T> {\n let queues = runQueues.get(browser);\n if (!queues) runQueues.set(browser, (queues = new Map()));\n const previous = queues.get(scope) ?? Promise.resolve();\n const next = previous.then(run, run);\n const settled = next.catch(() => undefined);\n queues.set(scope, settled);\n void settled.then(() => {\n if (queues.get(scope) === settled) queues.delete(scope);\n });\n return next;\n}\n\n/** Add what happened to the browser to the codemode result. */\nfunction withBrowserReport(\n output: ProxyToolOutput,\n report: BrowserExecutionReport | undefined\n): BrowserToolOutput {\n if (!report) return output;\n const notices = [\n report.restarted && RESTARTED_NOTICE,\n report.tabClosed && !report.restarted && TAB_CLOSED_NOTICE,\n report.tabShared && TAB_SHARED_NOTICE\n ].filter((notice) => typeof notice === \"string\");\n return {\n ...output,\n ...(report.restarted ? { restarted: true as const } : {}),\n ...(notices.length > 0 ? { notice: notices.join(\" \") } : {}),\n ...(report.newTabs.length > 0 ? { newTabs: report.newTabs } : {})\n };\n}\n\n/** Report sentences that must survive a screenshot's text summary. */\nexport function browserReportNotes(output: BrowserToolOutput): string[] {\n const notes: string[] = [];\n if (output.notice) notes.push(output.notice);\n if (output.newTabs?.length) {\n notes.push(\n `New tabs opened by the page: ${JSON.stringify(output.newTabs)}`\n );\n }\n return notes;\n}\n\n/**\n * Build the codemode runtime and connector for one `browserTool`, and wrap\n * `execute` so each result carries the browser report.\n *\n * Each scope gets its own connector (which knows its scope) on the same\n * codemode runtime, built on first use. Runs in one scope wait for each\n * other, since they drive one tab; runs in different scopes go in parallel.\n */\nexport function createBrowserToolCore(\n options: BrowserToolOptions,\n adapter: {\n /** What the adapter does with screenshots, told to the model. */\n screenshotHint: string;\n }\n) {\n const ctx = resolveCtx(options);\n if (!ctx) {\n throw new Error(\n \"browserTool requires a Durable Object 'ctx' — pass it explicitly, or call from within an Agent so it can be resolved via getCurrentAgent()\"\n );\n }\n\n const timeout = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const executor = new DynamicWorkerExecutor({\n loader: options.loader,\n timeout\n });\n\n // Our own description, not codemode's generic one: that one tells the\n // model to search before every new connector (search doesn't cover CDP\n // commands), and describes approvals, snippets, and replay, which this\n // tool doesn't use.\n const rules = [\n BROWSER_INSTRUCTIONS,\n `Each run times out after ${Math.round(timeout / 1000)}s, so split long jobs (crawling a site, say) across runs.`,\n adapter.screenshotHint\n ]\n .join(\"\\n\")\n .split(\"\\n\")\n .map((rule) => `- ${rule}`)\n .join(\"\\n\");\n const description = [\n \"Run JavaScript that drives a persistent Chrome browser over the Chrome DevTools Protocol (CDP).\",\n \"\",\n \"Write an async arrow function, `async () => { ... }`, and return a small JSON value. Use the `cdp` global to reach the browser. `fetch` is blocked and there is no file system or Node.js API.\",\n \"\",\n \"## cdp\",\n \"\",\n \"- `cdp.send({ method, params?, sessionId?, timeoutMs? })` sends a CDP command and returns its result without the JSON-RPC envelope: `Page.navigate` returns `{ frameId, errorText? }`, `Runtime.evaluate` returns `{ result: { value }, exceptionDetails? }`.\",\n \"- `cdp.attachToTarget({ targetId })` makes an open tab active and returns `{ sessionId }`.\",\n '- `cdp.spec()` returns the whole protocol (about 650 KB) as `{ domains: [{ name, commands, events, types }] }`. Filter it in code, for example `spec.domains.find((d) => d.name === \"Page\").commands.find((c) => c.name === \"navigate\")`.',\n \"- `cdp.getDebugLog()` returns recent protocol traffic, for when a command fails or times out.\",\n \"\",\n \"## Rules\",\n \"\",\n rules,\n '- A `SyntaxError` from \"Failed to start Worker\" means your code didn\\'t parse; its line number points into wrapper code, not yours. Check regex literals and escapes.'\n ].join(\"\\n\");\n type CodemodeTool = ReturnType<\n ReturnType<typeof createCodemodeRuntime>[\"tool\"]\n >;\n interface ScopedTool {\n connector: BrowserSessionConnector;\n tool: CodemodeTool;\n }\n const durableCtx: DurableObjectState = ctx;\n const scopes = new Map<string, ScopedTool>();\n function scoped(scope: string): ScopedTool {\n const cached = scopes.get(scope);\n if (cached) {\n // Most recently used last, so the first entry is the one to drop.\n scopes.delete(scope);\n scopes.set(scope, cached);\n return cached;\n }\n const connector = new BrowserSessionConnector(durableCtx, {\n browser: options.browser,\n scope\n });\n const runtime = createCodemodeRuntime({\n ctx: durableCtx,\n executor,\n connectors: [connector],\n name: browserRuntimeName(options.browser.name),\n transformResult: transformBrowserResult\n });\n const built = { connector, tool: runtime.tool({ description }) };\n scopes.set(scope, built);\n if (scopes.size > MAX_CACHED_SCOPES) {\n const oldest = scopes.keys().next().value;\n if (oldest !== undefined) scopes.delete(oldest);\n }\n return built;\n }\n\n const defaultScope = options.scope ?? DEFAULT_BROWSER_SCOPE;\n const { inputSchema } = scoped(defaultScope).tool;\n\n return {\n description,\n inputSchema,\n /** Run `input` in `scope`, which defaults to the tool's `scope`. */\n execute: (\n input: BrowserToolInput,\n scope: string = defaultScope\n ): Promise<BrowserToolOutput> =>\n queued(options.browser, scope, async () => {\n const { connector, tool } = scoped(scope);\n const output = await tool.execute(input, undefined);\n return withBrowserReport(\n output,\n connector.takeReport(output.executionId)\n );\n })\n };\n}\n"],"mappings":"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"}
@@ -1,4 +1,7 @@
1
- import { n as BrowserConnection } from "./browser-DE3d-RLk.js";
1
+ import {
2
+ n as BrowserConnectOptions,
3
+ r as BrowserConnection
4
+ } from "./browser-D30VlpcA.js";
2
5
  import {
3
6
  CodemodeConnector,
4
7
  ConnectorTool,
@@ -14,8 +17,12 @@ import {
14
17
  interface BrowserSource {
15
18
  /** The browser's name, for log messages. */
16
19
  readonly name: string;
17
- /** Reattach to the browser (or replace it) and open a CDP connection. */
18
- connect(): Promise<BrowserConnection>;
20
+ /**
21
+ * Reattach to the browser (or replace it) and open a CDP connection for
22
+ * a scope. A source that ignores `scope` shares one active tab between
23
+ * every caller.
24
+ */
25
+ connect(options?: BrowserConnectOptions): Promise<BrowserConnection>;
19
26
  }
20
27
  /** A tab a page opened on its own during an execution. */
21
28
  interface BrowserNewTab {
@@ -37,8 +44,15 @@ interface BrowserToolOptions {
37
44
  * Requires `"worker_loaders": [{ "binding": "LOADER" }]` in wrangler.jsonc.
38
45
  */
39
46
  loader: WorkerLoader;
40
- /** Sandbox execution timeout in milliseconds. Defaults to 30000 (30s). */
47
+ /** Sandbox execution timeout in milliseconds. Defaults to 60000 (60s). */
41
48
  timeoutMs?: number;
49
+ /**
50
+ * Who is driving, when several chats or users share one `Browser`: runs
51
+ * with the same scope share an active tab, and each scope keeps its own.
52
+ * Cookies and logins are shared by every scope. Defaults to `"shared"`,
53
+ * one active tab for every tool that leaves it out.
54
+ */
55
+ scope?: string;
42
56
  /**
43
57
  * Durable Object state for the codemode runtime facet. Optional inside an
44
58
  * Agent (resolved via `getCurrentAgent()`); pass it explicitly elsewhere.
@@ -58,7 +72,12 @@ interface BrowserToolInput {
58
72
  * plus what happened to the browser.
59
73
  */
60
74
  type BrowserToolOutput = ProxyToolOutput & {
61
- /** The browser was replaced before this run; earlier tabs are gone. */ restarted?: true /** A sentence telling the model what `restarted` means for it. */;
75
+ /** The browser was replaced before this run; earlier tabs are gone. */ restarted?: true;
76
+ /**
77
+ * Sentences telling the model what happened to its browser: it was
78
+ * restarted, its tab was closed by someone else, or another scope is
79
+ * working in its tab too.
80
+ */
62
81
  notice?: string /** Tabs the page opened itself (popups, `target=_blank` links). */;
63
82
  newTabs?: BrowserNewTab[];
64
83
  };
@@ -70,4 +89,4 @@ export {
70
89
  BrowserToolOutput as r,
71
90
  BrowserToolInput as t
72
91
  };
73
- //# sourceMappingURL=browser-tool-DuNdlwZ9.d.ts.map
92
+ //# sourceMappingURL=browser-tool-vtrPOV8e.d.ts.map
@@ -2,8 +2,6 @@
2
2
  const installedServices = /* @__PURE__ */ new WeakMap();
3
3
  /**
4
4
  * Base class for capabilities that consume standard Lifecycle services.
5
- *
6
- * @experimental The API surface may change before stabilizing.
7
5
  */
8
6
  var LifecycleCapability = class {
9
7
  constructor(capabilityId) {
@@ -40,4 +38,4 @@ function lifecycleCapabilityId(capability) {
40
38
  //#endregion
41
39
  export { bindLifecycleCapability as n, lifecycleCapabilityId as r, LifecycleCapability as t };
42
40
 
43
- //# sourceMappingURL=capability-B4WbF81e.js.map
41
+ //# sourceMappingURL=capability-DBAKc6UZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-DBAKc6UZ.js","names":[],"sources":["../src/lifecycle/capability.ts"],"sourcesContent":["import type {\n CapabilityStartContext,\n DurableObjectCapability\n} from \"./capability-runner\";\nimport type { Connection } from \"./types\";\nimport type { LifecycleJobs } from \"./job-queue\";\n\n/** Opaque address understood by a Lifecycle routing transport. */\nexport type LifecycleRouteAddress = {\n /** Stable equality and storage key. */\n readonly key: string;\n /** Transport-owned serialized address. */\n readonly data: string;\n};\n\n/** Context supplied with a routed capability message. */\nexport type LifecycleRouteContext = {\n /** Address of the sending Lifecycle, or undefined for an unrouted root. */\n readonly source: LifecycleRouteAddress | undefined;\n /** Capability-owned message payload. */\n readonly payload: unknown;\n};\n\n/** Startup state of a Lifecycle. */\nexport type LifecycleStatus = \"zero\" | \"starting\" | \"started\";\n\n/** Best-effort telemetry available to every Lifecycle capability. */\nexport type LifecycleEvents = {\n /** Publish an event under this capability's stable identity. */\n readonly emit: (type: string, payload: unknown) => void;\n};\n\n/** Routing available to every Lifecycle capability. */\nexport type LifecycleRoutes = {\n /** This Lifecycle's transport address, or undefined at the route root. */\n readonly source: LifecycleRouteAddress | undefined;\n /** Route a capability-owned message to the root Lifecycle. */\n readonly toRoot: (payload: unknown) => Promise<unknown>;\n /** Route a capability-owned message to another Lifecycle. */\n readonly to: (\n target: LifecycleRouteAddress,\n payload: unknown\n ) => Promise<unknown>;\n};\n\n/**\n * Ambient scope a capability supplies when entering host context on\n * behalf of a live connection or request.\n */\nexport type LifecycleHostContextScope = {\n /** The connection the callback runs on behalf of, when there is one. */\n readonly connection?: Connection;\n /** The request the callback runs on behalf of, when there is one. */\n readonly request?: Request;\n};\n\n/**\n * The platform's hibernatable-socket surface, exposed narrowly so a\n * capability that owns connections (e.g. WebSockets) can accept and\n * enumerate them without holding the whole `DurableObjectState`.\n * These are workerd API names, not Lifecycle modeling sockets.\n */\nexport type LifecycleSockets = {\n /** Accept a socket into hibernation under the given tags. */\n readonly accept: (ws: WebSocket, tags: string[]) => void;\n /** Every hibernated socket on the object, optionally by tag. */\n readonly get: (tag?: string) => WebSocket[];\n};\n\n/**\n * Standard services granted to every installed Lifecycle capability.\n */\nexport type LifecycleServices = {\n /** The host's Durable Object name; see `Lifecycle.name`. */\n readonly name: string;\n /** The host class name, as exported from the Worker. */\n readonly className: string;\n readonly storage: DurableObjectStorage;\n readonly sockets: LifecycleSockets;\n /**\n * Resolve once Lifecycle startup has finished, starting it if needed, and\n * reject if that startup fails. Calls made from inside startup resolve\n * immediately.\n *\n * Await it first in any operation that can run before startup and starts\n * work `onStart` also awaits, such as lazily opening a store. Native RPC\n * bypasses the automatic startup on fetch, alarm and WebSocket events, so\n * such an operation can begin that work outside startup. `onStart` then\n * awaits it while startup holds the input gate (`blockConcurrencyWhile`),\n * which holds back the work's timers and I/O, and startup times out after\n * 30 seconds and resets the object.\n */\n readonly ready: () => Promise<void>;\n /**\n * Startup state: `\"zero\"` before startup, `\"starting\"` while capability\n * and host startup hooks run, `\"started\"` once `ready()` resolves without\n * waiting.\n */\n readonly status: () => LifecycleStatus;\n /**\n * This capability's scoped access to the Lifecycle-owned work queue.\n * Pushed items are dispatched to `onJob` when due; every queue mutation\n * re-arms the physical alarm automatically.\n */\n readonly jobs: LifecycleJobs;\n /**\n * Keep work this capability hands off at a bounded `onJob` return inside\n * the current alarm's memory-limit breaker domain (#1825). Returns false,\n * tracking nothing, outside an alarm invocation.\n */\n readonly trackAlarmWork: (work: Promise<unknown>) => boolean;\n /**\n * Run a capability-held user callback inside the host invocation context.\n * Capability hooks run outside host context; this is the one boundary for\n * entering it, and a host composition root may substitute its own wrapper\n * (Agent adds tracing span scope). Pass `scope` to make a live\n * connection or request ambient for the callback.\n */\n readonly runInHostContext: (\n fn: () => unknown,\n scope?: LifecycleHostContextScope\n ) => Promise<unknown>;\n readonly events: LifecycleEvents;\n readonly routes: LifecycleRoutes;\n};\n\nconst installedServices = new WeakMap<object, LifecycleServices>();\n\n/**\n * Base class for capabilities that consume standard Lifecycle services.\n */\nexport abstract class LifecycleCapability<Props extends object = object> {\n readonly capabilityId: string;\n\n /** How this capability claims traffic; see {@link DurableObjectCapability.claims}. */\n readonly claims: \"selective\" | \"catch-all\" = \"selective\";\n\n protected constructor(capabilityId: string) {\n if (capabilityId.trim() === \"\") {\n throw new Error(\"Lifecycle capability IDs must be non-empty\");\n }\n this.capabilityId = capabilityId;\n }\n\n /** Default startup hook; capabilities override when they own startup work. */\n onStart(_context: CapabilityStartContext<Props>): void {}\n\n /** Standard services when installed, or undefined in isolated unit tests. */\n protected get lifecycleServices(): LifecycleServices | undefined {\n return installedServices.get(this);\n }\n\n /** Standard services supplied when Lifecycle installs this capability. */\n protected get lifecycle(): LifecycleServices {\n const services = this.lifecycleServices;\n if (!services) {\n throw new Error(\n `${this.constructor.name} must be installed with Lifecycle.use() before use`\n );\n }\n return services;\n }\n}\n\n/**\n * @internal Bind the standard service surface to one capability instance.\n * `Lifecycle.use()` calls this during installation. Test a capability by\n * installing it on a minimal Durable Object with a real Lifecycle rather\n * than binding fake services.\n */\nexport function bindLifecycleCapability(\n capability: LifecycleCapability,\n services: LifecycleServices\n): void {\n installedServices.set(capability, services);\n}\n\n/** @internal Read a capability ID without exposing installation internals. */\nexport function lifecycleCapabilityId(\n capability: DurableObjectCapability\n): string | undefined {\n return capability instanceof LifecycleCapability\n ? capability.capabilityId\n : undefined;\n}\n"],"mappings":";AA8HA,MAAM,oCAAoB,IAAI,QAAmC;;;;AAKjE,IAAsB,sBAAtB,MAAyE;CAMvE,YAAsB,cAAsB;EAF5C,KAAS,SAAoC;EAG3C,IAAI,aAAa,KAAK,MAAM,IAC1B,MAAM,IAAI,MAAM,4CAA4C;EAE9D,KAAK,eAAe;CACtB;;CAGA,QAAQ,UAA+C,CAAC;;CAGxD,IAAc,oBAAmD;EAC/D,OAAO,kBAAkB,IAAI,IAAI;CACnC;;CAGA,IAAc,YAA+B;EAC3C,MAAM,WAAW,KAAK;EACtB,IAAI,CAAC,UACH,MAAM,IAAI,MACR,GAAG,KAAK,YAAY,KAAK,mDAC3B;EAEF,OAAO;CACT;AACF;;;;;;;AAQA,SAAgB,wBACd,YACA,UACM;CACN,kBAAkB,IAAI,YAAY,QAAQ;AAC5C;;AAGA,SAAgB,sBACd,YACoB;CACpB,OAAO,sBAAsB,sBACzB,WAAW,eACX,KAAA;AACN"}
@@ -219,8 +219,6 @@ type LifecycleSockets = {
219
219
  };
220
220
  /**
221
221
  * Standard services granted to every installed Lifecycle capability.
222
- *
223
- * @experimental The API surface may change before stabilizing.
224
222
  */
225
223
  type LifecycleServices = {
226
224
  /** The host's Durable Object name; see `Lifecycle.name`. */ readonly name: string /** The host class name, as exported from the Worker. */;
@@ -231,6 +229,14 @@ type LifecycleServices = {
231
229
  * Resolve once Lifecycle startup has finished, starting it if needed, and
232
230
  * reject if that startup fails. Calls made from inside startup resolve
233
231
  * immediately.
232
+ *
233
+ * Await it first in any operation that can run before startup and starts
234
+ * work `onStart` also awaits, such as lazily opening a store. Native RPC
235
+ * bypasses the automatic startup on fetch, alarm and WebSocket events, so
236
+ * such an operation can begin that work outside startup. `onStart` then
237
+ * awaits it while startup holds the input gate (`blockConcurrencyWhile`),
238
+ * which holds back the work's timers and I/O, and startup times out after
239
+ * 30 seconds and resets the object.
234
240
  */
235
241
  readonly ready: () => Promise<void>;
236
242
  /**
@@ -267,8 +273,6 @@ type LifecycleServices = {
267
273
  };
268
274
  /**
269
275
  * Base class for capabilities that consume standard Lifecycle services.
270
- *
271
- * @experimental The API surface may change before stabilizing.
272
276
  */
273
277
  declare abstract class LifecycleCapability<Props extends object = object> {
274
278
  readonly capabilityId: string;
@@ -361,8 +365,6 @@ type MemoryLimitContext = {
361
365
  * - `onRoute` is addressed to one capability by its id; `onJob` is
362
366
  * addressed by the due job's owning capability, with Lifecycle owning
363
367
  * the queue and the one physical alarm.
364
- *
365
- * @experimental The API surface may change before stabilizing.
366
368
  */
367
369
  interface DurableObjectCapability<Props extends object = object> {
368
370
  /**
@@ -486,4 +488,4 @@ export {
486
488
  Connection as x,
487
489
  LifecycleJobPushOptions as y
488
490
  };
489
- //# sourceMappingURL=capability-runner-DBAnGr6L.d.ts.map
491
+ //# sourceMappingURL=capability-runner-BiVUtjqC.d.ts.map
@@ -0,0 +1,333 @@
1
+ import {
2
+ b as ChannelMessageSurface,
3
+ m as ResponseChunk,
4
+ p as Participant,
5
+ x as ChannelMessageSurfaceInput
6
+ } from "./protocol-CukuI73M.js";
7
+
8
+ //#region src/experimental/channels/identity.d.ts
9
+ type ChannelIdentity = Readonly<{
10
+ /** Configured Channel that observed this identity. */ channelKey: string /** Stable Channel namespace in which `subject` is unique. @default "default" */;
11
+ scope?: string /** Stable Channel subject within `scope`. */;
12
+ subject: string;
13
+ }>;
14
+ /** A Channel-produced identity before its Host stamps the configured key. */
15
+ type ChannelIdentityInput = Readonly<{
16
+ scope?: string;
17
+ subject: string;
18
+ }>;
19
+ /** Build a stable key for comparing or indexing a Channel identity. */
20
+ declare function identityKey(identity: ChannelIdentity): string;
21
+ //#endregion
22
+ //#region src/experimental/channels/ingress.d.ts
23
+ /** Serializable provider attachment facts available after ingress returns. */
24
+ type ChannelAttachment = {
25
+ id?: string;
26
+ mediaType?: string;
27
+ name?: string;
28
+ size?: number;
29
+ text?: string;
30
+ url?: string;
31
+ };
32
+ type ChannelActor = {
33
+ readonly id: string /** Stable Channel identity suitable for explicit application linking. */;
34
+ readonly identity?: ChannelIdentity;
35
+ readonly username?: string;
36
+ readonly fullName?: string;
37
+ readonly isBot?: boolean | "unknown";
38
+ readonly isSelf?: boolean;
39
+ };
40
+ /** An actor before the Host stamps its configured Channel key. */
41
+ type ChannelActorInput = Omit<ChannelActor, "identity"> & {
42
+ readonly identity?: ChannelIdentityInput;
43
+ };
44
+ type ChannelEventContext = {
45
+ /** Immutable Channel-scoped identity, independent of application routing. */ readonly eventId: string;
46
+ readonly thread: {
47
+ readonly id: string;
48
+ readonly isDirectMessage: boolean | "unknown";
49
+ } /** Exact provider destination for responding to this inbound event. */;
50
+ readonly replySurface?: ChannelMessageSurface;
51
+ readonly actor?: ChannelActor;
52
+ };
53
+ /** A normalized inbound message from a Channel. */
54
+ type ChannelInboundMessage = ChannelEventContext & {
55
+ readonly type: "message";
56
+ readonly message: {
57
+ readonly id: string;
58
+ readonly text: string;
59
+ readonly title?: string;
60
+ readonly markdown?: string;
61
+ readonly attachments?: readonly ChannelAttachment[];
62
+ readonly isMention?: boolean;
63
+ readonly reply?: {
64
+ readonly id: string;
65
+ readonly text?: string;
66
+ };
67
+ readonly metadata?: {
68
+ /** ISO 8601 timestamp supplied by the provider. */ readonly sentAt?: string;
69
+ readonly edited?: boolean /** ISO 8601 timestamp supplied by the provider. */;
70
+ readonly editedAt?: string;
71
+ readonly autoReply?: boolean;
72
+ };
73
+ };
74
+ };
75
+ /** A provider-normalized response to an external approval request. */
76
+ type ChannelApprovalResponse = ChannelEventContext & {
77
+ readonly type: "approval-response";
78
+ readonly approvalId: string;
79
+ readonly decision:
80
+ | "approve"
81
+ | "reject" /** Provider reference for this inbound response. */;
82
+ readonly reference: string;
83
+ };
84
+ type ChannelIngressEvent = ChannelInboundMessage | ChannelApprovalResponse;
85
+ /** A normalized message before the Host stamps its configured Channel key. */
86
+ type ChannelEventContextInput = Omit<
87
+ ChannelEventContext,
88
+ "replySurface" | "actor"
89
+ > & {
90
+ readonly replySurface?: ChannelMessageSurfaceInput;
91
+ readonly actor?: ChannelActorInput;
92
+ };
93
+ type ChannelInboundMessageInput = Omit<
94
+ ChannelInboundMessage,
95
+ "replySurface" | "actor"
96
+ > & {
97
+ readonly replySurface?: ChannelMessageSurfaceInput;
98
+ readonly actor?: ChannelActorInput;
99
+ };
100
+ /** A normalized approval before the Host stamps its configured Channel key. */
101
+ type ChannelApprovalResponseInput = Omit<
102
+ ChannelApprovalResponse,
103
+ "replySurface" | "actor"
104
+ > & {
105
+ readonly replySurface?: ChannelMessageSurfaceInput;
106
+ readonly actor?: ChannelActorInput;
107
+ };
108
+ /** Authenticated event produced by a Channel before Host dispatch. */
109
+ type ChannelIngressEventInput =
110
+ | ChannelInboundMessageInput
111
+ | ChannelApprovalResponseInput;
112
+ /** Authenticated Channel output retained only until Host routing completes. */
113
+ type ChannelIngressEnvelope<TRaw = unknown> = {
114
+ event: ChannelIngressEventInput;
115
+ raw: TRaw;
116
+ };
117
+ /** The normalized envelopes and provider acknowledgement produced by ingress. */
118
+ type ChannelIngressResult<TRaw = unknown> = {
119
+ events: readonly ChannelIngressEnvelope<TRaw>[];
120
+ response: Response;
121
+ };
122
+ /** Match an HTTP request to one exact URL pathname. */
123
+ declare function matchesPath(request: Request, path: string): boolean;
124
+ /** Webhook-shaped inbound support owned by a Channel. */
125
+ interface ChannelIngress<TRaw = unknown> {
126
+ /** Return null when this Channel does not own the request. */
127
+ receive(request: Request): Promise<ChannelIngressResult<TRaw> | null>;
128
+ }
129
+ /** Structural input supported by Workers Email and Agent email handlers. */
130
+ type ChannelEmailInput = {
131
+ from: string;
132
+ to: string;
133
+ headers: Headers;
134
+ raw?: ReadableStream<Uint8Array>;
135
+ getRaw?: () => Promise<Uint8Array>;
136
+ };
137
+ type ChannelEmailIngressResult<TRaw = unknown> = {
138
+ events: readonly ChannelIngressEnvelope<TRaw>[];
139
+ };
140
+ /** Non-HTTP ingress for a Workers Email event. */
141
+ interface ChannelEmailIngress<TRaw = unknown> {
142
+ /** Return null when this Channel does not own the email. */
143
+ receive(
144
+ email: ChannelEmailInput
145
+ ): Promise<ChannelEmailIngressResult<TRaw> | null>;
146
+ }
147
+ //#endregion
148
+ //#region src/experimental/channels/channel.d.ts
149
+ type Awaitable<T> = T | Promise<T>;
150
+ /** A transport-neutral outbound message whose canonical content is Markdown. */
151
+ type ChannelMessage = {
152
+ /** Optional topic. Each transport decides how to represent it. */ title?: string /** Canonical Markdown content. */;
153
+ markdown: string;
154
+ };
155
+ /** A transport failure safe to expose to an AI model. */
156
+ type DeliveryFailure = {
157
+ code: string;
158
+ message: string;
159
+ };
160
+ /**
161
+ * The result of a direct delivery attempt, defined by what reached the reader.
162
+ *
163
+ * `delivered` means the whole message reached the reader, not that a person
164
+ * read it. `failed` means none of it did; its `retryable` field says whether
165
+ * the same route can be attempted again. `uncertain` means an unknown amount
166
+ * of the message reached the reader, so another attempt or route could
167
+ * duplicate content. A stream that ends before its answer is complete is
168
+ * `uncertain`, and carries a `reference` when the Channel created something
169
+ * the caller can point at.
170
+ */
171
+ type DeliveryResult =
172
+ | {
173
+ status: "delivered";
174
+ reference?: string;
175
+ }
176
+ | {
177
+ status: "failed";
178
+ retryable: boolean;
179
+ error: DeliveryFailure;
180
+ }
181
+ | {
182
+ status: "uncertain";
183
+ reference?: string;
184
+ error: DeliveryFailure;
185
+ };
186
+ /** A response's chunks, as `ChannelGateway.stream` takes them. */
187
+ type ChannelChunkSource = ReadableStream<ResponseChunk>;
188
+ /** Caller options for one finished delivery. */
189
+ type ChannelDeliveryOptions = {
190
+ /** Caller-owned correlation an Adapter may use where the provider supports it. */ delivery?: ChannelDeliveryContext;
191
+ };
192
+ /** Caller options for one streamed answer. */
193
+ type ChannelStreamOptions = {
194
+ /**
195
+ * Optional topic. It is an option rather than a chunk because it is known
196
+ * before the first token, and a Channel usually needs it in its opening
197
+ * provider call.
198
+ */
199
+ title?: string /** Caller-owned correlation an Adapter may use where the provider supports it. */;
200
+ delivery?: ChannelDeliveryContext;
201
+ };
202
+ /**
203
+ * Caller-owned correlation supplied to one provider delivery attempt.
204
+ *
205
+ * This is not an idempotency guarantee. An Adapter may map it to a provider
206
+ * idempotency primitive when one exists, or otherwise use it for observability.
207
+ */
208
+ type ChannelDeliveryContext = {
209
+ deliveryId: string;
210
+ };
211
+ /**
212
+ * Who a sender is, as the application decides it. A string is shorthand
213
+ * for `{ id }`; `null` refuses the sender. Participants that share an id
214
+ * are the same participant.
215
+ */
216
+ type ParticipantResult = Participant | string | null;
217
+ /**
218
+ * Resolve who sent an authenticated event. Channels has no opinion on
219
+ * identity: this is the only place a webhook sender becomes a participant.
220
+ */
221
+ type ChannelParticipant<TRaw = unknown> = (
222
+ event: ChannelIngressEvent,
223
+ raw: TRaw
224
+ ) => Awaitable<ParticipantResult>;
225
+ /**
226
+ * Pick the agent object an event reaches, or return null to ignore it.
227
+ *
228
+ * The agent object is the authorization boundary: anyone who reaches one
229
+ * may use every conversation in it. Default: an agent object of the
230
+ * participant's own (`routes.perParticipant`).
231
+ */
232
+ type ChannelRoute<TRaw = unknown> = (
233
+ event: ChannelIngressEvent,
234
+ raw: TRaw,
235
+ participant: Participant
236
+ ) => Awaitable<string | null>;
237
+ /** A WebSocket upgrade's conversation, once it is known to be for Channels. */
238
+ type ChannelUpgradeMatch = {
239
+ /** The conversation to follow. Default: the agent's default conversation. */ conversationId?: string;
240
+ };
241
+ /** How a Channel takes WebSocket upgrades in the gateway. */
242
+ interface ChannelUpgrade {
243
+ /** Return undefined for an upgrade that is not for this Channel. */
244
+ match(request: Request): ChannelUpgradeMatch | undefined;
245
+ /** Who is connecting. Return null to refuse the upgrade. */
246
+ participant(request: Request): Awaitable<ParticipantResult>;
247
+ /** The agent object the upgrade reaches, or null to refuse it. */
248
+ route(request: Request, participant: Participant): Awaitable<string | null>;
249
+ }
250
+ /** A configured delivery route with optional ingress support. */
251
+ interface Channel<TRaw = unknown> {
252
+ /**
253
+ * Who sent an ingress event. Required when the Channel has `ingress` or
254
+ * `emailIngress`; the gateway refuses to start without it.
255
+ */
256
+ participant?(
257
+ event: ChannelIngressEvent,
258
+ raw: TRaw
259
+ ): Awaitable<ParticipantResult>;
260
+ /** Pick the agent object an event reaches. See `ChannelRoute`. */
261
+ route?(
262
+ event: ChannelIngressEvent,
263
+ raw: TRaw,
264
+ participant: Participant
265
+ ): Awaitable<string | null>;
266
+ /** Derive a direct destination from this configured Channel's identity. */
267
+ contactSurface?(identity: ChannelIdentity): ChannelMessageSurfaceInput | null;
268
+ /**
269
+ * Deliver one finished message. Only for Channels that cannot stream:
270
+ * the gateway delivers to a Channel that can by streaming the message.
271
+ */
272
+ deliver?(
273
+ surface: ChannelMessageSurface,
274
+ message: ChannelMessage,
275
+ options?: ChannelDeliveryOptions
276
+ ): Promise<DeliveryResult>;
277
+ /**
278
+ * Deliver one progressively generated answer. Absent for Channels that
279
+ * cannot stream, which the Host serves by collecting and calling `deliver`.
280
+ *
281
+ * The Channel owns the consumption loop. It must finalize whether the
282
+ * stream closed or errored, because a model can fail mid-generation, and it
283
+ * must not abandon a terminal provider call on error.
284
+ */
285
+ stream?(
286
+ surface: ChannelMessageSurface,
287
+ chunks: ChannelChunkSource,
288
+ options: ChannelStreamOptions
289
+ ): Promise<DeliveryResult>;
290
+ readonly ingress?: ChannelIngress<TRaw>;
291
+ readonly emailIngress?: ChannelEmailIngress<TRaw>;
292
+ /** WebSocket upgrades this Channel takes, such as the Web Channel's. */
293
+ readonly upgrade?: ChannelUpgrade;
294
+ }
295
+ //#endregion
296
+ export {
297
+ ChannelIngressEventInput as A,
298
+ ChannelEventContext as C,
299
+ ChannelIngress as D,
300
+ ChannelInboundMessageInput as E,
301
+ identityKey as F,
302
+ matchesPath as M,
303
+ ChannelIdentity as N,
304
+ ChannelIngressEnvelope as O,
305
+ ChannelIdentityInput as P,
306
+ ChannelEmailInput as S,
307
+ ChannelInboundMessage as T,
308
+ ChannelApprovalResponse as _,
309
+ ChannelDeliveryOptions as a,
310
+ ChannelEmailIngress as b,
311
+ ChannelRoute as c,
312
+ ChannelUpgradeMatch as d,
313
+ DeliveryFailure as f,
314
+ ChannelActorInput as g,
315
+ ChannelActor as h,
316
+ ChannelDeliveryContext as i,
317
+ ChannelIngressResult as j,
318
+ ChannelIngressEvent as k,
319
+ ChannelStreamOptions as l,
320
+ ParticipantResult as m,
321
+ Channel as n,
322
+ ChannelMessage as o,
323
+ DeliveryResult as p,
324
+ ChannelChunkSource as r,
325
+ ChannelParticipant as s,
326
+ Awaitable as t,
327
+ ChannelUpgrade as u,
328
+ ChannelApprovalResponseInput as v,
329
+ ChannelEventContextInput as w,
330
+ ChannelEmailIngressResult as x,
331
+ ChannelAttachment as y
332
+ };
333
+ //# sourceMappingURL=channel-Bak_6zDP.d.ts.map
@@ -9,21 +9,23 @@ import {
9
9
  _ as FiberRecoveryContext$1,
10
10
  at as isPositionlessAgentToolChunk,
11
11
  z as AgentToolEventState
12
- } from "../agent-routing-0DR0Tk2v.js";
13
- import { _ as TaskStep, m as TaskRunOptions } from "../tasks-9YxYtByh.js";
12
+ } from "../agent-routing-QDcchcQP.js";
13
+ import { _ as TaskStep, m as TaskRunOptions } from "../tasks-E89KdwkS.js";
14
+ import {
15
+ n as ClientToolSchema,
16
+ r as createToolsFromClientSchemas,
17
+ t as ClientToolExecutor
18
+ } from "../client-tools-aIBO0Fk7.js";
19
+ import { n as Streams } from "../streams-vrCtbUIn.js";
14
20
  import {
15
21
  a as CHAT_MESSAGE_TYPES,
16
- c as ClientToolExecutor,
17
22
  i as OutgoingMessage,
18
- l as ClientToolSchema,
19
23
  n as IncomingMessage,
20
24
  o as STREAM_RESUME_NONE_REASONS,
21
25
  r as MessageType,
22
26
  s as StreamResumeNoneReason,
23
- t as ChatTurnOutcome,
24
- u as createToolsFromClientSchemas
25
- } from "../wire-types-CrjKvDyi.js";
26
- import { n as Streams } from "../streams-Cmkj9QfW.js";
27
+ t as ChatTurnOutcome
28
+ } from "../wire-types-Cv0iwjk5.js";
27
29
  import {
28
30
  a as applyAgentToolEvent,
29
31
  i as AgentToolProgressEmitter,
@@ -32,7 +34,7 @@ import {
32
34
  r as AgentToolProgressEmitResult,
33
35
  s as interceptAgentToolBroadcast,
34
36
  t as AgentToolBroadcastHooks
35
- } from "../agent-tools-YrATZJu2.js";
37
+ } from "../agent-tools-DHL2XI7u.js";
36
38
  import { l as SessionMessage } from "../types-B7LojTe4.js";
37
39
  import { ModelMessage, UIMessage } from "ai";
38
40
  import { Connection, FiberRecoveryContext } from "agents";