@agent-relay/sdk 7.1.1 → 8.0.2

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 (581) hide show
  1. package/README.md +177 -143
  2. package/bin/agent-relay-broker-darwin-arm64 +0 -0
  3. package/bin/agent-relay-broker-darwin-x64 +0 -0
  4. package/bin/agent-relay-broker-linux-arm64 +0 -0
  5. package/bin/agent-relay-broker-linux-x64 +0 -0
  6. package/bin/agent-relay-broker-win32-x64.exe +0 -0
  7. package/dist/actions/errors.d.ts +18 -0
  8. package/dist/actions/errors.d.ts.map +1 -0
  9. package/dist/actions/errors.js +39 -0
  10. package/dist/actions/errors.js.map +1 -0
  11. package/dist/actions/index.d.ts +5 -0
  12. package/dist/actions/index.d.ts.map +1 -0
  13. package/dist/actions/index.js +5 -0
  14. package/dist/actions/index.js.map +1 -0
  15. package/dist/actions/json-schema-lite.d.ts +13 -0
  16. package/dist/actions/json-schema-lite.d.ts.map +1 -0
  17. package/dist/actions/json-schema-lite.js +322 -0
  18. package/dist/actions/json-schema-lite.js.map +1 -0
  19. package/dist/actions/registry.d.ts +20 -0
  20. package/dist/actions/registry.d.ts.map +1 -0
  21. package/dist/actions/registry.js +267 -0
  22. package/dist/actions/registry.js.map +1 -0
  23. package/dist/actions/types.d.ts +177 -0
  24. package/dist/actions/types.d.ts.map +1 -0
  25. package/dist/{provisioner → actions}/types.js.map +1 -1
  26. package/dist/agent-relay.d.ts +86 -0
  27. package/dist/agent-relay.d.ts.map +1 -0
  28. package/dist/agent-relay.js +197 -0
  29. package/dist/agent-relay.js.map +1 -0
  30. package/dist/capabilities.d.ts +6 -0
  31. package/dist/capabilities.d.ts.map +1 -0
  32. package/dist/capabilities.js +9 -0
  33. package/dist/capabilities.js.map +1 -0
  34. package/dist/delivery/index.d.ts +4 -0
  35. package/dist/delivery/index.d.ts.map +1 -0
  36. package/dist/delivery/index.js +4 -0
  37. package/dist/delivery/index.js.map +1 -0
  38. package/dist/delivery/runner.d.ts +26 -0
  39. package/dist/delivery/runner.d.ts.map +1 -0
  40. package/dist/delivery/runner.js +177 -0
  41. package/dist/delivery/runner.js.map +1 -0
  42. package/dist/delivery/types.d.ts +45 -0
  43. package/dist/delivery/types.d.ts.map +1 -0
  44. package/dist/delivery/types.js +2 -0
  45. package/dist/delivery/types.js.map +1 -0
  46. package/dist/facade.d.ts +151 -0
  47. package/dist/facade.d.ts.map +1 -0
  48. package/dist/facade.js +280 -0
  49. package/dist/facade.js.map +1 -0
  50. package/dist/index.d.ts +9 -25
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +9 -23
  53. package/dist/index.js.map +1 -1
  54. package/dist/listeners.d.ts +162 -0
  55. package/dist/listeners.d.ts.map +1 -0
  56. package/dist/listeners.js +297 -0
  57. package/dist/listeners.js.map +1 -0
  58. package/dist/messaging/index.d.ts +4 -0
  59. package/dist/messaging/index.d.ts.map +1 -0
  60. package/dist/messaging/index.js +4 -0
  61. package/dist/messaging/index.js.map +1 -0
  62. package/dist/messaging/normalize.d.ts +29 -0
  63. package/dist/messaging/normalize.d.ts.map +1 -0
  64. package/dist/messaging/normalize.js +602 -0
  65. package/dist/messaging/normalize.js.map +1 -0
  66. package/dist/messaging/relaycast.d.ts +270 -0
  67. package/dist/messaging/relaycast.d.ts.map +1 -0
  68. package/dist/messaging/relaycast.js +559 -0
  69. package/dist/messaging/relaycast.js.map +1 -0
  70. package/dist/messaging/types.d.ts +672 -0
  71. package/dist/messaging/types.d.ts.map +1 -0
  72. package/dist/messaging/types.js +2 -0
  73. package/dist/messaging/types.js.map +1 -0
  74. package/dist/relaycast-errors.d.ts +39 -0
  75. package/dist/relaycast-errors.d.ts.map +1 -0
  76. package/dist/relaycast-errors.js +111 -0
  77. package/dist/relaycast-errors.js.map +1 -0
  78. package/dist/session/index.d.ts +58 -0
  79. package/dist/session/index.d.ts.map +1 -0
  80. package/dist/session/index.js +54 -0
  81. package/dist/session/index.js.map +1 -0
  82. package/dist/session/types.d.ts +258 -0
  83. package/dist/session/types.d.ts.map +1 -0
  84. package/dist/session/types.js +7 -0
  85. package/dist/session/types.js.map +1 -0
  86. package/package.json +31 -199
  87. package/dist/broker-logs.d.ts +0 -80
  88. package/dist/broker-logs.d.ts.map +0 -1
  89. package/dist/broker-logs.js +0 -189
  90. package/dist/broker-logs.js.map +0 -1
  91. package/dist/broker-path.d.ts +0 -34
  92. package/dist/broker-path.d.ts.map +0 -1
  93. package/dist/broker-path.js +0 -267
  94. package/dist/broker-path.js.map +0 -1
  95. package/dist/browser.d.ts +0 -16
  96. package/dist/browser.d.ts.map +0 -1
  97. package/dist/browser.js +0 -19
  98. package/dist/browser.js.map +0 -1
  99. package/dist/cli-registry.d.ts +0 -44
  100. package/dist/cli-registry.d.ts.map +0 -1
  101. package/dist/cli-registry.js +0 -104
  102. package/dist/cli-registry.js.map +0 -1
  103. package/dist/cli-resolver.d.ts +0 -30
  104. package/dist/cli-resolver.d.ts.map +0 -1
  105. package/dist/cli-resolver.js +0 -132
  106. package/dist/cli-resolver.js.map +0 -1
  107. package/dist/client.d.ts +0 -278
  108. package/dist/client.d.ts.map +0 -1
  109. package/dist/client.js +0 -838
  110. package/dist/client.js.map +0 -1
  111. package/dist/communicate/a2a-bridge.d.ts +0 -25
  112. package/dist/communicate/a2a-bridge.d.ts.map +0 -1
  113. package/dist/communicate/a2a-bridge.js +0 -89
  114. package/dist/communicate/a2a-bridge.js.map +0 -1
  115. package/dist/communicate/a2a-server.d.ts +0 -31
  116. package/dist/communicate/a2a-server.d.ts.map +0 -1
  117. package/dist/communicate/a2a-server.js +0 -220
  118. package/dist/communicate/a2a-server.js.map +0 -1
  119. package/dist/communicate/a2a-transport.d.ts +0 -48
  120. package/dist/communicate/a2a-transport.d.ts.map +0 -1
  121. package/dist/communicate/a2a-transport.js +0 -305
  122. package/dist/communicate/a2a-transport.js.map +0 -1
  123. package/dist/communicate/a2a-types.d.ts +0 -107
  124. package/dist/communicate/a2a-types.d.ts.map +0 -1
  125. package/dist/communicate/a2a-types.js +0 -209
  126. package/dist/communicate/a2a-types.js.map +0 -1
  127. package/dist/communicate/adapters/ai-sdk.d.ts +0 -63
  128. package/dist/communicate/adapters/ai-sdk.d.ts.map +0 -1
  129. package/dist/communicate/adapters/ai-sdk.js +0 -114
  130. package/dist/communicate/adapters/ai-sdk.js.map +0 -1
  131. package/dist/communicate/adapters/claude-sdk.d.ts +0 -28
  132. package/dist/communicate/adapters/claude-sdk.d.ts.map +0 -1
  133. package/dist/communicate/adapters/claude-sdk.js +0 -47
  134. package/dist/communicate/adapters/claude-sdk.js.map +0 -1
  135. package/dist/communicate/adapters/crewai.d.ts +0 -42
  136. package/dist/communicate/adapters/crewai.d.ts.map +0 -1
  137. package/dist/communicate/adapters/crewai.js +0 -95
  138. package/dist/communicate/adapters/crewai.js.map +0 -1
  139. package/dist/communicate/adapters/google-adk.d.ts +0 -53
  140. package/dist/communicate/adapters/google-adk.d.ts.map +0 -1
  141. package/dist/communicate/adapters/google-adk.js +0 -77
  142. package/dist/communicate/adapters/google-adk.js.map +0 -1
  143. package/dist/communicate/adapters/index.d.ts +0 -3
  144. package/dist/communicate/adapters/index.d.ts.map +0 -1
  145. package/dist/communicate/adapters/index.js +0 -3
  146. package/dist/communicate/adapters/index.js.map +0 -1
  147. package/dist/communicate/adapters/langgraph.d.ts +0 -40
  148. package/dist/communicate/adapters/langgraph.d.ts.map +0 -1
  149. package/dist/communicate/adapters/langgraph.js +0 -77
  150. package/dist/communicate/adapters/langgraph.js.map +0 -1
  151. package/dist/communicate/adapters/openai-agents.d.ts +0 -25
  152. package/dist/communicate/adapters/openai-agents.d.ts.map +0 -1
  153. package/dist/communicate/adapters/openai-agents.js +0 -70
  154. package/dist/communicate/adapters/openai-agents.js.map +0 -1
  155. package/dist/communicate/adapters/pi.d.ts +0 -44
  156. package/dist/communicate/adapters/pi.d.ts.map +0 -1
  157. package/dist/communicate/adapters/pi.js +0 -55
  158. package/dist/communicate/adapters/pi.js.map +0 -1
  159. package/dist/communicate/core.d.ts +0 -58
  160. package/dist/communicate/core.d.ts.map +0 -1
  161. package/dist/communicate/core.js +0 -127
  162. package/dist/communicate/core.js.map +0 -1
  163. package/dist/communicate/index.d.ts +0 -20
  164. package/dist/communicate/index.d.ts.map +0 -1
  165. package/dist/communicate/index.js +0 -43
  166. package/dist/communicate/index.js.map +0 -1
  167. package/dist/communicate/transport.d.ts +0 -35
  168. package/dist/communicate/transport.d.ts.map +0 -1
  169. package/dist/communicate/transport.js +0 -279
  170. package/dist/communicate/transport.js.map +0 -1
  171. package/dist/communicate/types.d.ts +0 -58
  172. package/dist/communicate/types.d.ts.map +0 -1
  173. package/dist/communicate/types.js +0 -66
  174. package/dist/communicate/types.js.map +0 -1
  175. package/dist/consensus-helpers.d.ts +0 -103
  176. package/dist/consensus-helpers.d.ts.map +0 -1
  177. package/dist/consensus-helpers.js +0 -147
  178. package/dist/consensus-helpers.js.map +0 -1
  179. package/dist/consensus.d.ts +0 -72
  180. package/dist/consensus.d.ts.map +0 -1
  181. package/dist/consensus.js +0 -378
  182. package/dist/consensus.js.map +0 -1
  183. package/dist/event-bus.d.ts +0 -57
  184. package/dist/event-bus.d.ts.map +0 -1
  185. package/dist/event-bus.js +0 -76
  186. package/dist/event-bus.js.map +0 -1
  187. package/dist/examples/demo.d.ts +0 -2
  188. package/dist/examples/demo.d.ts.map +0 -1
  189. package/dist/examples/demo.js +0 -63
  190. package/dist/examples/demo.js.map +0 -1
  191. package/dist/examples/example.d.ts +0 -2
  192. package/dist/examples/example.d.ts.map +0 -1
  193. package/dist/examples/example.js +0 -77
  194. package/dist/examples/example.js.map +0 -1
  195. package/dist/examples/persona-spawn.d.ts +0 -2
  196. package/dist/examples/persona-spawn.d.ts.map +0 -1
  197. package/dist/examples/persona-spawn.js +0 -43
  198. package/dist/examples/persona-spawn.js.map +0 -1
  199. package/dist/examples/quickstart.d.ts +0 -2
  200. package/dist/examples/quickstart.d.ts.map +0 -1
  201. package/dist/examples/quickstart.js +0 -56
  202. package/dist/examples/quickstart.js.map +0 -1
  203. package/dist/examples/ralph-loop.d.ts +0 -2
  204. package/dist/examples/ralph-loop.d.ts.map +0 -1
  205. package/dist/examples/ralph-loop.js +0 -281
  206. package/dist/examples/ralph-loop.js.map +0 -1
  207. package/dist/examples/workflow-superiority.d.ts +0 -32
  208. package/dist/examples/workflow-superiority.d.ts.map +0 -1
  209. package/dist/examples/workflow-superiority.js +0 -1421
  210. package/dist/examples/workflow-superiority.js.map +0 -1
  211. package/dist/github.d.ts +0 -24
  212. package/dist/github.d.ts.map +0 -1
  213. package/dist/github.js +0 -24
  214. package/dist/github.js.map +0 -1
  215. package/dist/http.d.ts +0 -38
  216. package/dist/http.d.ts.map +0 -1
  217. package/dist/http.js +0 -60
  218. package/dist/http.js.map +0 -1
  219. package/dist/lifecycle-hooks.d.ts +0 -141
  220. package/dist/lifecycle-hooks.d.ts.map +0 -1
  221. package/dist/lifecycle-hooks.js +0 -29
  222. package/dist/lifecycle-hooks.js.map +0 -1
  223. package/dist/logs.d.ts +0 -106
  224. package/dist/logs.d.ts.map +0 -1
  225. package/dist/logs.js +0 -291
  226. package/dist/logs.js.map +0 -1
  227. package/dist/models.d.ts +0 -9
  228. package/dist/models.d.ts.map +0 -1
  229. package/dist/models.js +0 -17
  230. package/dist/models.js.map +0 -1
  231. package/dist/personas.d.ts +0 -160
  232. package/dist/personas.d.ts.map +0 -1
  233. package/dist/personas.js +0 -401
  234. package/dist/personas.js.map +0 -1
  235. package/dist/protocol.d.ts +0 -521
  236. package/dist/protocol.d.ts.map +0 -1
  237. package/dist/protocol.js +0 -2
  238. package/dist/protocol.js.map +0 -1
  239. package/dist/provisioner/__tests__/audit.test.d.ts +0 -2
  240. package/dist/provisioner/__tests__/audit.test.d.ts.map +0 -1
  241. package/dist/provisioner/__tests__/audit.test.js +0 -45
  242. package/dist/provisioner/__tests__/audit.test.js.map +0 -1
  243. package/dist/provisioner/__tests__/compiler.test.d.ts +0 -2
  244. package/dist/provisioner/__tests__/compiler.test.d.ts.map +0 -1
  245. package/dist/provisioner/__tests__/compiler.test.js +0 -345
  246. package/dist/provisioner/__tests__/compiler.test.js.map +0 -1
  247. package/dist/provisioner/__tests__/presets.test.d.ts +0 -2
  248. package/dist/provisioner/__tests__/presets.test.d.ts.map +0 -1
  249. package/dist/provisioner/__tests__/presets.test.js +0 -23
  250. package/dist/provisioner/__tests__/presets.test.js.map +0 -1
  251. package/dist/provisioner/__tests__/seeder.test.d.ts +0 -2
  252. package/dist/provisioner/__tests__/seeder.test.d.ts.map +0 -1
  253. package/dist/provisioner/__tests__/seeder.test.js +0 -224
  254. package/dist/provisioner/__tests__/seeder.test.js.map +0 -1
  255. package/dist/provisioner/__tests__/tar-seeder.test.d.ts +0 -2
  256. package/dist/provisioner/__tests__/tar-seeder.test.d.ts.map +0 -1
  257. package/dist/provisioner/__tests__/tar-seeder.test.js +0 -191
  258. package/dist/provisioner/__tests__/tar-seeder.test.js.map +0 -1
  259. package/dist/provisioner/__tests__/token-factory.test.d.ts +0 -2
  260. package/dist/provisioner/__tests__/token-factory.test.d.ts.map +0 -1
  261. package/dist/provisioner/__tests__/token-factory.test.js +0 -139
  262. package/dist/provisioner/__tests__/token-factory.test.js.map +0 -1
  263. package/dist/provisioner/__tests__/token.test.d.ts +0 -2
  264. package/dist/provisioner/__tests__/token.test.d.ts.map +0 -1
  265. package/dist/provisioner/__tests__/token.test.js +0 -49
  266. package/dist/provisioner/__tests__/token.test.js.map +0 -1
  267. package/dist/provisioner/audit.d.ts +0 -19
  268. package/dist/provisioner/audit.d.ts.map +0 -1
  269. package/dist/provisioner/audit.js +0 -74
  270. package/dist/provisioner/audit.js.map +0 -1
  271. package/dist/provisioner/compiler.d.ts +0 -23
  272. package/dist/provisioner/compiler.d.ts.map +0 -1
  273. package/dist/provisioner/compiler.js +0 -355
  274. package/dist/provisioner/compiler.js.map +0 -1
  275. package/dist/provisioner/index.d.ts +0 -10
  276. package/dist/provisioner/index.d.ts.map +0 -1
  277. package/dist/provisioner/index.js +0 -269
  278. package/dist/provisioner/index.js.map +0 -1
  279. package/dist/provisioner/local-jwks.d.ts +0 -25
  280. package/dist/provisioner/local-jwks.d.ts.map +0 -1
  281. package/dist/provisioner/local-jwks.js +0 -70
  282. package/dist/provisioner/local-jwks.js.map +0 -1
  283. package/dist/provisioner/mount.d.ts +0 -14
  284. package/dist/provisioner/mount.d.ts.map +0 -1
  285. package/dist/provisioner/mount.js +0 -329
  286. package/dist/provisioner/mount.js.map +0 -1
  287. package/dist/provisioner/seeder.d.ts +0 -17
  288. package/dist/provisioner/seeder.d.ts.map +0 -1
  289. package/dist/provisioner/seeder.js +0 -419
  290. package/dist/provisioner/seeder.js.map +0 -1
  291. package/dist/provisioner/token.d.ts +0 -41
  292. package/dist/provisioner/token.d.ts.map +0 -1
  293. package/dist/provisioner/token.js +0 -77
  294. package/dist/provisioner/token.js.map +0 -1
  295. package/dist/provisioner/types.d.ts +0 -134
  296. package/dist/provisioner/types.d.ts.map +0 -1
  297. package/dist/pty.d.ts +0 -8
  298. package/dist/pty.d.ts.map +0 -1
  299. package/dist/pty.js +0 -26
  300. package/dist/pty.js.map +0 -1
  301. package/dist/relay-adapter.d.ts +0 -124
  302. package/dist/relay-adapter.d.ts.map +0 -1
  303. package/dist/relay-adapter.js +0 -242
  304. package/dist/relay-adapter.js.map +0 -1
  305. package/dist/relay.d.ts +0 -550
  306. package/dist/relay.d.ts.map +0 -1
  307. package/dist/relay.js +0 -1682
  308. package/dist/relay.js.map +0 -1
  309. package/dist/shadow.d.ts +0 -101
  310. package/dist/shadow.d.ts.map +0 -1
  311. package/dist/shadow.js +0 -174
  312. package/dist/shadow.js.map +0 -1
  313. package/dist/slack.d.ts +0 -24
  314. package/dist/slack.d.ts.map +0 -1
  315. package/dist/slack.js +0 -24
  316. package/dist/slack.js.map +0 -1
  317. package/dist/spawn-from-env.d.ts +0 -78
  318. package/dist/spawn-from-env.d.ts.map +0 -1
  319. package/dist/spawn-from-env.js +0 -172
  320. package/dist/spawn-from-env.js.map +0 -1
  321. package/dist/transport.d.ts +0 -104
  322. package/dist/transport.d.ts.map +0 -1
  323. package/dist/transport.js +0 -520
  324. package/dist/transport.js.map +0 -1
  325. package/dist/types.d.ts +0 -101
  326. package/dist/types.d.ts.map +0 -1
  327. package/dist/types.js +0 -5
  328. package/dist/types.js.map +0 -1
  329. package/dist/workers.d.ts +0 -39
  330. package/dist/workers.d.ts.map +0 -1
  331. package/dist/workers.js +0 -39
  332. package/dist/workers.js.map +0 -1
  333. package/dist/workflows/__tests__/budget-enforcement.test.d.ts +0 -2
  334. package/dist/workflows/__tests__/budget-enforcement.test.d.ts.map +0 -1
  335. package/dist/workflows/__tests__/budget-enforcement.test.js +0 -411
  336. package/dist/workflows/__tests__/budget-enforcement.test.js.map +0 -1
  337. package/dist/workflows/__tests__/budget-tracker.test.d.ts +0 -2
  338. package/dist/workflows/__tests__/budget-tracker.test.d.ts.map +0 -1
  339. package/dist/workflows/__tests__/budget-tracker.test.js +0 -99
  340. package/dist/workflows/__tests__/budget-tracker.test.js.map +0 -1
  341. package/dist/workflows/__tests__/builder-paths.test.d.ts +0 -2
  342. package/dist/workflows/__tests__/builder-paths.test.d.ts.map +0 -1
  343. package/dist/workflows/__tests__/builder-paths.test.js +0 -63
  344. package/dist/workflows/__tests__/builder-paths.test.js.map +0 -1
  345. package/dist/workflows/__tests__/channel-messenger.test.d.ts +0 -2
  346. package/dist/workflows/__tests__/channel-messenger.test.d.ts.map +0 -1
  347. package/dist/workflows/__tests__/channel-messenger.test.js +0 -123
  348. package/dist/workflows/__tests__/channel-messenger.test.js.map +0 -1
  349. package/dist/workflows/__tests__/cli-session-collector.test.d.ts +0 -2
  350. package/dist/workflows/__tests__/cli-session-collector.test.d.ts.map +0 -1
  351. package/dist/workflows/__tests__/cli-session-collector.test.js +0 -54
  352. package/dist/workflows/__tests__/cli-session-collector.test.js.map +0 -1
  353. package/dist/workflows/__tests__/collectors/claude.test.d.ts +0 -2
  354. package/dist/workflows/__tests__/collectors/claude.test.d.ts.map +0 -1
  355. package/dist/workflows/__tests__/collectors/claude.test.js +0 -85
  356. package/dist/workflows/__tests__/collectors/claude.test.js.map +0 -1
  357. package/dist/workflows/__tests__/collectors/codex.test.d.ts +0 -2
  358. package/dist/workflows/__tests__/collectors/codex.test.d.ts.map +0 -1
  359. package/dist/workflows/__tests__/collectors/codex.test.js +0 -67
  360. package/dist/workflows/__tests__/collectors/codex.test.js.map +0 -1
  361. package/dist/workflows/__tests__/collectors/opencode.test.d.ts +0 -2
  362. package/dist/workflows/__tests__/collectors/opencode.test.d.ts.map +0 -1
  363. package/dist/workflows/__tests__/collectors/opencode.test.js +0 -119
  364. package/dist/workflows/__tests__/collectors/opencode.test.js.map +0 -1
  365. package/dist/workflows/__tests__/e2big-and-verify.test.d.ts +0 -2
  366. package/dist/workflows/__tests__/e2big-and-verify.test.d.ts.map +0 -1
  367. package/dist/workflows/__tests__/e2big-and-verify.test.js +0 -62
  368. package/dist/workflows/__tests__/e2big-and-verify.test.js.map +0 -1
  369. package/dist/workflows/__tests__/e2e-permissions.test.d.ts +0 -2
  370. package/dist/workflows/__tests__/e2e-permissions.test.d.ts.map +0 -1
  371. package/dist/workflows/__tests__/e2e-permissions.test.js +0 -338
  372. package/dist/workflows/__tests__/e2e-permissions.test.js.map +0 -1
  373. package/dist/workflows/__tests__/permission-types.test.d.ts +0 -2
  374. package/dist/workflows/__tests__/permission-types.test.d.ts.map +0 -1
  375. package/dist/workflows/__tests__/permission-types.test.js +0 -124
  376. package/dist/workflows/__tests__/permission-types.test.js.map +0 -1
  377. package/dist/workflows/__tests__/permissions-integration.test.d.ts +0 -2
  378. package/dist/workflows/__tests__/permissions-integration.test.d.ts.map +0 -1
  379. package/dist/workflows/__tests__/permissions-integration.test.js +0 -577
  380. package/dist/workflows/__tests__/permissions-integration.test.js.map +0 -1
  381. package/dist/workflows/__tests__/process-backend-executor.test.d.ts +0 -2
  382. package/dist/workflows/__tests__/process-backend-executor.test.d.ts.map +0 -1
  383. package/dist/workflows/__tests__/process-backend-executor.test.js +0 -83
  384. package/dist/workflows/__tests__/process-backend-executor.test.js.map +0 -1
  385. package/dist/workflows/__tests__/proxy-env.test.d.ts +0 -2
  386. package/dist/workflows/__tests__/proxy-env.test.d.ts.map +0 -1
  387. package/dist/workflows/__tests__/proxy-env.test.js +0 -135
  388. package/dist/workflows/__tests__/proxy-env.test.js.map +0 -1
  389. package/dist/workflows/__tests__/run-script.test.d.ts +0 -2
  390. package/dist/workflows/__tests__/run-script.test.d.ts.map +0 -1
  391. package/dist/workflows/__tests__/run-script.test.js +0 -426
  392. package/dist/workflows/__tests__/run-script.test.js.map +0 -1
  393. package/dist/workflows/__tests__/run-summary-table.test.d.ts +0 -2
  394. package/dist/workflows/__tests__/run-summary-table.test.d.ts.map +0 -1
  395. package/dist/workflows/__tests__/run-summary-table.test.js +0 -131
  396. package/dist/workflows/__tests__/run-summary-table.test.js.map +0 -1
  397. package/dist/workflows/__tests__/scrub-pty-chrome.test.d.ts +0 -2
  398. package/dist/workflows/__tests__/scrub-pty-chrome.test.d.ts.map +0 -1
  399. package/dist/workflows/__tests__/scrub-pty-chrome.test.js +0 -113
  400. package/dist/workflows/__tests__/scrub-pty-chrome.test.js.map +0 -1
  401. package/dist/workflows/__tests__/sibling-links.test.d.ts +0 -2
  402. package/dist/workflows/__tests__/sibling-links.test.d.ts.map +0 -1
  403. package/dist/workflows/__tests__/sibling-links.test.js +0 -166
  404. package/dist/workflows/__tests__/sibling-links.test.js.map +0 -1
  405. package/dist/workflows/__tests__/step-cwd.test.d.ts +0 -2
  406. package/dist/workflows/__tests__/step-cwd.test.d.ts.map +0 -1
  407. package/dist/workflows/__tests__/step-cwd.test.js +0 -42
  408. package/dist/workflows/__tests__/step-cwd.test.js.map +0 -1
  409. package/dist/workflows/__tests__/step-executor.test.d.ts +0 -2
  410. package/dist/workflows/__tests__/step-executor.test.d.ts.map +0 -1
  411. package/dist/workflows/__tests__/step-executor.test.js +0 -378
  412. package/dist/workflows/__tests__/step-executor.test.js.map +0 -1
  413. package/dist/workflows/__tests__/template-resolver.test.d.ts +0 -2
  414. package/dist/workflows/__tests__/template-resolver.test.d.ts.map +0 -1
  415. package/dist/workflows/__tests__/template-resolver.test.js +0 -145
  416. package/dist/workflows/__tests__/template-resolver.test.js.map +0 -1
  417. package/dist/workflows/__tests__/verification-custom.test.d.ts +0 -2
  418. package/dist/workflows/__tests__/verification-custom.test.d.ts.map +0 -1
  419. package/dist/workflows/__tests__/verification-custom.test.js +0 -230
  420. package/dist/workflows/__tests__/verification-custom.test.js.map +0 -1
  421. package/dist/workflows/__tests__/verification-traceback.test.d.ts +0 -2
  422. package/dist/workflows/__tests__/verification-traceback.test.d.ts.map +0 -1
  423. package/dist/workflows/__tests__/verification-traceback.test.js +0 -442
  424. package/dist/workflows/__tests__/verification-traceback.test.js.map +0 -1
  425. package/dist/workflows/__tests__/verification.test.d.ts +0 -2
  426. package/dist/workflows/__tests__/verification.test.d.ts.map +0 -1
  427. package/dist/workflows/__tests__/verification.test.js +0 -272
  428. package/dist/workflows/__tests__/verification.test.js.map +0 -1
  429. package/dist/workflows/__tests__/workflow-reliability-contract.test.d.ts +0 -2
  430. package/dist/workflows/__tests__/workflow-reliability-contract.test.d.ts.map +0 -1
  431. package/dist/workflows/__tests__/workflow-reliability-contract.test.js +0 -536
  432. package/dist/workflows/__tests__/workflow-reliability-contract.test.js.map +0 -1
  433. package/dist/workflows/__tests__/workflow-reliability-e2e.test.d.ts +0 -2
  434. package/dist/workflows/__tests__/workflow-reliability-e2e.test.d.ts.map +0 -1
  435. package/dist/workflows/__tests__/workflow-reliability-e2e.test.js +0 -199
  436. package/dist/workflows/__tests__/workflow-reliability-e2e.test.js.map +0 -1
  437. package/dist/workflows/api-executor.d.ts +0 -16
  438. package/dist/workflows/api-executor.d.ts.map +0 -1
  439. package/dist/workflows/api-executor.js +0 -94
  440. package/dist/workflows/api-executor.js.map +0 -1
  441. package/dist/workflows/barrier.d.ts +0 -72
  442. package/dist/workflows/barrier.d.ts.map +0 -1
  443. package/dist/workflows/barrier.js +0 -162
  444. package/dist/workflows/barrier.js.map +0 -1
  445. package/dist/workflows/budget-tracker.d.ts +0 -75
  446. package/dist/workflows/budget-tracker.d.ts.map +0 -1
  447. package/dist/workflows/budget-tracker.js +0 -184
  448. package/dist/workflows/budget-tracker.js.map +0 -1
  449. package/dist/workflows/builder.d.ts +0 -229
  450. package/dist/workflows/builder.d.ts.map +0 -1
  451. package/dist/workflows/builder.js +0 -430
  452. package/dist/workflows/builder.js.map +0 -1
  453. package/dist/workflows/channel-messenger.d.ts +0 -28
  454. package/dist/workflows/channel-messenger.d.ts.map +0 -1
  455. package/dist/workflows/channel-messenger.js +0 -275
  456. package/dist/workflows/channel-messenger.js.map +0 -1
  457. package/dist/workflows/cli-session-collector.d.ts +0 -39
  458. package/dist/workflows/cli-session-collector.d.ts.map +0 -1
  459. package/dist/workflows/cli-session-collector.js +0 -23
  460. package/dist/workflows/cli-session-collector.js.map +0 -1
  461. package/dist/workflows/cli.d.ts +0 -11
  462. package/dist/workflows/cli.d.ts.map +0 -1
  463. package/dist/workflows/cli.js +0 -395
  464. package/dist/workflows/cli.js.map +0 -1
  465. package/dist/workflows/cloud-runner.d.ts +0 -15
  466. package/dist/workflows/cloud-runner.d.ts.map +0 -1
  467. package/dist/workflows/cloud-runner.js +0 -41
  468. package/dist/workflows/cloud-runner.js.map +0 -1
  469. package/dist/workflows/cloud-schedules.d.ts +0 -3
  470. package/dist/workflows/cloud-schedules.d.ts.map +0 -1
  471. package/dist/workflows/cloud-schedules.js +0 -2
  472. package/dist/workflows/cloud-schedules.js.map +0 -1
  473. package/dist/workflows/collectors/claude.d.ts +0 -6
  474. package/dist/workflows/collectors/claude.d.ts.map +0 -1
  475. package/dist/workflows/collectors/claude.js +0 -330
  476. package/dist/workflows/collectors/claude.js.map +0 -1
  477. package/dist/workflows/collectors/codex.d.ts +0 -18
  478. package/dist/workflows/collectors/codex.d.ts.map +0 -1
  479. package/dist/workflows/collectors/codex.js +0 -265
  480. package/dist/workflows/collectors/codex.js.map +0 -1
  481. package/dist/workflows/collectors/opencode.d.ts +0 -6
  482. package/dist/workflows/collectors/opencode.d.ts.map +0 -1
  483. package/dist/workflows/collectors/opencode.js +0 -204
  484. package/dist/workflows/collectors/opencode.js.map +0 -1
  485. package/dist/workflows/coordinator.d.ts +0 -73
  486. package/dist/workflows/coordinator.d.ts.map +0 -1
  487. package/dist/workflows/coordinator.js +0 -647
  488. package/dist/workflows/coordinator.js.map +0 -1
  489. package/dist/workflows/custom-steps.d.ts +0 -73
  490. package/dist/workflows/custom-steps.d.ts.map +0 -1
  491. package/dist/workflows/custom-steps.js +0 -321
  492. package/dist/workflows/custom-steps.js.map +0 -1
  493. package/dist/workflows/default-logger.d.ts +0 -9
  494. package/dist/workflows/default-logger.d.ts.map +0 -1
  495. package/dist/workflows/default-logger.js +0 -104
  496. package/dist/workflows/default-logger.js.map +0 -1
  497. package/dist/workflows/dry-run-format.d.ts +0 -6
  498. package/dist/workflows/dry-run-format.d.ts.map +0 -1
  499. package/dist/workflows/dry-run-format.js +0 -76
  500. package/dist/workflows/dry-run-format.js.map +0 -1
  501. package/dist/workflows/file-db.d.ts +0 -85
  502. package/dist/workflows/file-db.d.ts.map +0 -1
  503. package/dist/workflows/file-db.js +0 -215
  504. package/dist/workflows/file-db.js.map +0 -1
  505. package/dist/workflows/index.d.ts +0 -36
  506. package/dist/workflows/index.d.ts.map +0 -1
  507. package/dist/workflows/index.js +0 -33
  508. package/dist/workflows/index.js.map +0 -1
  509. package/dist/workflows/listr-renderer.d.ts +0 -26
  510. package/dist/workflows/listr-renderer.d.ts.map +0 -1
  511. package/dist/workflows/listr-renderer.js +0 -230
  512. package/dist/workflows/listr-renderer.js.map +0 -1
  513. package/dist/workflows/memory-db.d.ts +0 -17
  514. package/dist/workflows/memory-db.d.ts.map +0 -1
  515. package/dist/workflows/memory-db.js +0 -33
  516. package/dist/workflows/memory-db.js.map +0 -1
  517. package/dist/workflows/process-backend-executor.d.ts +0 -18
  518. package/dist/workflows/process-backend-executor.d.ts.map +0 -1
  519. package/dist/workflows/process-backend-executor.js +0 -74
  520. package/dist/workflows/process-backend-executor.js.map +0 -1
  521. package/dist/workflows/process-spawner.d.ts +0 -35
  522. package/dist/workflows/process-spawner.d.ts.map +0 -1
  523. package/dist/workflows/process-spawner.js +0 -141
  524. package/dist/workflows/process-spawner.js.map +0 -1
  525. package/dist/workflows/proxy-env.d.ts +0 -52
  526. package/dist/workflows/proxy-env.d.ts.map +0 -1
  527. package/dist/workflows/proxy-env.js +0 -92
  528. package/dist/workflows/proxy-env.js.map +0 -1
  529. package/dist/workflows/run-script.d.ts +0 -82
  530. package/dist/workflows/run-script.d.ts.map +0 -1
  531. package/dist/workflows/run-script.js +0 -521
  532. package/dist/workflows/run-script.js.map +0 -1
  533. package/dist/workflows/run-summary-table.d.ts +0 -5
  534. package/dist/workflows/run-summary-table.d.ts.map +0 -1
  535. package/dist/workflows/run-summary-table.js +0 -132
  536. package/dist/workflows/run-summary-table.js.map +0 -1
  537. package/dist/workflows/run.d.ts +0 -45
  538. package/dist/workflows/run.d.ts.map +0 -1
  539. package/dist/workflows/run.js +0 -37
  540. package/dist/workflows/run.js.map +0 -1
  541. package/dist/workflows/runner.d.ts +0 -527
  542. package/dist/workflows/runner.d.ts.map +0 -1
  543. package/dist/workflows/runner.js +0 -6266
  544. package/dist/workflows/runner.js.map +0 -1
  545. package/dist/workflows/sibling-links.d.ts +0 -100
  546. package/dist/workflows/sibling-links.d.ts.map +0 -1
  547. package/dist/workflows/sibling-links.js +0 -205
  548. package/dist/workflows/sibling-links.js.map +0 -1
  549. package/dist/workflows/state.d.ts +0 -77
  550. package/dist/workflows/state.d.ts.map +0 -1
  551. package/dist/workflows/state.js +0 -140
  552. package/dist/workflows/state.js.map +0 -1
  553. package/dist/workflows/step-executor.d.ts +0 -95
  554. package/dist/workflows/step-executor.d.ts.map +0 -1
  555. package/dist/workflows/step-executor.js +0 -393
  556. package/dist/workflows/step-executor.js.map +0 -1
  557. package/dist/workflows/template-resolver.d.ts +0 -33
  558. package/dist/workflows/template-resolver.d.ts.map +0 -1
  559. package/dist/workflows/template-resolver.js +0 -144
  560. package/dist/workflows/template-resolver.js.map +0 -1
  561. package/dist/workflows/templates.d.ts +0 -47
  562. package/dist/workflows/templates.d.ts.map +0 -1
  563. package/dist/workflows/templates.js +0 -405
  564. package/dist/workflows/templates.js.map +0 -1
  565. package/dist/workflows/trajectory.d.ts +0 -87
  566. package/dist/workflows/trajectory.d.ts.map +0 -1
  567. package/dist/workflows/trajectory.js +0 -412
  568. package/dist/workflows/trajectory.js.map +0 -1
  569. package/dist/workflows/types.d.ts +0 -471
  570. package/dist/workflows/types.d.ts.map +0 -1
  571. package/dist/workflows/types.js +0 -37
  572. package/dist/workflows/types.js.map +0 -1
  573. package/dist/workflows/validator.d.ts +0 -11
  574. package/dist/workflows/validator.d.ts.map +0 -1
  575. package/dist/workflows/validator.js +0 -184
  576. package/dist/workflows/validator.js.map +0 -1
  577. package/dist/workflows/verification.d.ts +0 -53
  578. package/dist/workflows/verification.d.ts.map +0 -1
  579. package/dist/workflows/verification.js +0 -238
  580. package/dist/workflows/verification.js.map +0 -1
  581. /package/dist/{provisioner → actions}/types.js +0 -0
package/dist/relay.js DELETED
@@ -1,1682 +0,0 @@
1
- /**
2
- * High-level facade for the Agent Relay SDK.
3
- *
4
- * Provides a clean, property-based API on top of the lower-level
5
- * {@link AgentRelayClient} protocol client.
6
- *
7
- * @example
8
- * ```ts
9
- * import { AgentRelay } from "@agent-relay/sdk";
10
- *
11
- * const relay = new AgentRelay();
12
- *
13
- * relay.addListener('messageReceived', (message) => console.log(message));
14
- * relay.addListener('agentSpawned', (agent) => console.log("spawned", agent.name));
15
- *
16
- * const codex = await relay.codex.spawn();
17
- * const human = relay.human({ name: "System" });
18
- * await human.sendMessage({ to: codex.name, text: "Hello!" });
19
- *
20
- * const agents = await relay.listAgents();
21
- * for (const a of agents) await a.release();
22
- * await relay.shutdown();
23
- * ```
24
- */
25
- import { randomBytes } from 'node:crypto';
26
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
27
- import path from 'node:path';
28
- import { RelayCast } from '@relaycast/sdk';
29
- import { zodToJsonSchema } from 'zod-to-json-schema';
30
- import { AgentRelayClient } from './client.js';
31
- import { EventBus } from './event-bus.js';
32
- import { buildPersonaSpawnSpec, composePersonaTask, loadPersona, materializePersonaConfigFiles, restorePersonaConfigFiles, } from './personas.js';
33
- import { AgentRelayProtocolError } from './transport.js';
34
- import { followLogs as followLogsFromFile, getLogs as getLogsFromFile, listLoggedAgents as listLoggedAgentsFromFile, } from './logs.js';
35
- function isUnsupportedOperation(error) {
36
- return error instanceof AgentRelayProtocolError && error.code === 'unsupported_operation';
37
- }
38
- function buildUnsupportedOperationMessage(from, input) {
39
- return {
40
- eventId: 'unsupported_operation',
41
- from,
42
- to: input.to,
43
- text: input.text,
44
- threadId: input.threadId,
45
- data: input.data,
46
- mode: input.mode,
47
- };
48
- }
49
- const WORKSPACE_ID_PREFIX = 'rw_';
50
- const WORKSPACE_ID_ALPHABET = 'abcdefghijklmnopqrstuvwxyz0123456789';
51
- function normalizeWorkspaceId(value) {
52
- const trimmed = value?.trim();
53
- return trimmed ? trimmed : undefined;
54
- }
55
- function generateWorkspaceId() {
56
- const alphabetLength = WORKSPACE_ID_ALPHABET.length;
57
- const maxUnbiasedValue = Math.floor(256 / alphabetLength) * alphabetLength;
58
- let suffix = '';
59
- while (suffix.length < 8) {
60
- const bytes = randomBytes(8 - suffix.length);
61
- for (const byte of bytes) {
62
- if (byte >= maxUnbiasedValue)
63
- continue;
64
- suffix += WORKSPACE_ID_ALPHABET[byte % alphabetLength];
65
- if (suffix.length === 8)
66
- break;
67
- }
68
- }
69
- return `${WORKSPACE_ID_PREFIX}${suffix}`;
70
- }
71
- function toWorkspaceRegistryEntry(value) {
72
- if (!value || typeof value !== 'object') {
73
- return {};
74
- }
75
- const record = value;
76
- const relaycastApiKey = typeof record.relaycastApiKey === 'string' && record.relaycastApiKey.trim()
77
- ? record.relaycastApiKey.trim()
78
- : undefined;
79
- const relayfileUrl = typeof record.relayfileUrl === 'string' && record.relayfileUrl.trim()
80
- ? record.relayfileUrl.trim()
81
- : undefined;
82
- const createdAt = typeof record.createdAt === 'string' && record.createdAt.trim() ? record.createdAt.trim() : undefined;
83
- const agents = Array.isArray(record.agents)
84
- ? record.agents
85
- .filter((agent) => typeof agent === 'string')
86
- .map((agent) => agent.trim())
87
- .filter((agent) => agent.length > 0)
88
- : undefined;
89
- return {
90
- ...(relaycastApiKey ? { relaycastApiKey } : {}),
91
- ...(relayfileUrl ? { relayfileUrl } : {}),
92
- ...(createdAt ? { createdAt } : {}),
93
- ...(agents && agents.length > 0 ? { agents } : {}),
94
- };
95
- }
96
- // ── AgentRelay facade ───────────────────────────────────────────────────────
97
- export class AgentRelay {
98
- /**
99
- * Multi-listener event registry. Subscribe via {@link addListener} or
100
- * `bus.addListener` directly; emit happens internally as broker events
101
- * arrive and at SDK call sites for the spawn / release lifecycle hooks.
102
- *
103
- * The bus is shared with the underlying `AgentRelayClient` (created via
104
- * {@link ensureStarted}) so listeners registered on either object see
105
- * the same events.
106
- */
107
- bus = new EventBus();
108
- addListener(event, handler) {
109
- return this.bus.addListener(event, handler);
110
- }
111
- removeListener(event, handler) {
112
- this.bus.removeListener(event, handler);
113
- }
114
- // ── Public accessors ────────────────────────────────────────────────────
115
- /** The resolved Relaycast workspace API key (available after first spawn). */
116
- get workspaceKey() {
117
- return this.relayApiKey;
118
- }
119
- /** Observer URL for the auto-created workspace (available after first spawn). */
120
- get observerUrl() {
121
- if (!this.relayApiKey)
122
- return undefined;
123
- return `https://agentrelay.com/observer?key=${this.relayApiKey}`;
124
- }
125
- // Shorthand spawners
126
- codex;
127
- claude;
128
- gemini;
129
- opencode;
130
- clientOptions;
131
- defaultChannels;
132
- requestedWorkspaceId;
133
- workspaceName;
134
- relaycastBaseUrl;
135
- defaultPersonaDirs;
136
- relayApiKey;
137
- resolvedWorkspaceId;
138
- client;
139
- startPromise;
140
- unsubEvent;
141
- stderrListeners = new Set();
142
- knownAgents = new Map();
143
- readyAgents = new Set();
144
- messageReadyAgents = new Set();
145
- exitedAgents = new Set();
146
- idleAgents = new Set();
147
- deliveryStates = new Map();
148
- agentActivityStates = new Map();
149
- outputListeners = new Map();
150
- resultContracts = new Map();
151
- lastAgentResults = new Map();
152
- resultResolvers = new Map();
153
- resultResolverSeq = 0;
154
- exitResolvers = new Map();
155
- exitResolverSeq = 0;
156
- idleResolvers = new Map();
157
- idleResolverSeq = 0;
158
- constructor(options = {}) {
159
- const requestedWorkspaceId = normalizeWorkspaceId(options.workspaceId);
160
- this.defaultChannels = options.channels ?? ['general'];
161
- this.requestedWorkspaceId = requestedWorkspaceId;
162
- this.workspaceName = options.workspaceName;
163
- if (options.workspaceName && !options.workspaceId) {
164
- console.warn('[AgentRelay] workspaceName without workspaceId is deprecated and will be removed in a future major version. ' +
165
- 'Set workspaceId explicitly to avoid silent behavior changes.');
166
- }
167
- this.relaycastBaseUrl = options.relaycastBaseUrl;
168
- if (options.personaDirs)
169
- this.defaultPersonaDirs = [...options.personaDirs];
170
- this.clientOptions = {
171
- binaryPath: options.binaryPath,
172
- binaryArgs: options.binaryArgs,
173
- brokerName: options.brokerName ?? options.workspaceName ?? requestedWorkspaceId,
174
- channels: this.defaultChannels,
175
- cwd: options.cwd,
176
- env: options.env,
177
- requestTimeoutMs: options.requestTimeoutMs,
178
- };
179
- this.codex = this.createSpawner('codex', 'Codex', 'pty');
180
- this.claude = this.createSpawner('claude', 'Claude', 'pty');
181
- this.gemini = this.createSpawner('gemini', 'Gemini', 'pty');
182
- this.opencode = this.createSpawner('opencode', 'OpenCode', 'headless');
183
- }
184
- getWorkspaceRegistryPath() {
185
- return path.join(this.clientOptions.cwd ?? process.cwd(), '.relay', 'workspaces.json');
186
- }
187
- readWorkspaceRegistry() {
188
- const registryPath = this.getWorkspaceRegistryPath();
189
- if (!existsSync(registryPath)) {
190
- return {};
191
- }
192
- let raw;
193
- try {
194
- raw = readFileSync(registryPath, 'utf8').trim();
195
- }
196
- catch {
197
- return {};
198
- }
199
- if (!raw) {
200
- return {};
201
- }
202
- let parsed;
203
- try {
204
- parsed = JSON.parse(raw);
205
- }
206
- catch {
207
- // Registry file is corrupted (partial write, disk full, concurrent access).
208
- // Return empty registry so callers can re-create it.
209
- return {};
210
- }
211
- if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
212
- return {};
213
- }
214
- const registry = {};
215
- for (const [workspaceId, entry] of Object.entries(parsed)) {
216
- const normalizedId = normalizeWorkspaceId(workspaceId);
217
- if (!normalizedId)
218
- continue;
219
- registry[normalizedId] = toWorkspaceRegistryEntry(entry);
220
- }
221
- return registry;
222
- }
223
- writeWorkspaceRegistry(registry) {
224
- const registryPath = this.getWorkspaceRegistryPath();
225
- mkdirSync(path.dirname(registryPath), { recursive: true });
226
- writeFileSync(registryPath, `${JSON.stringify(registry, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
227
- }
228
- persistWorkspaceMapping(workspaceId, apiKey) {
229
- const registry = this.readWorkspaceRegistry();
230
- const existing = registry[workspaceId] ?? {};
231
- registry[workspaceId] = {
232
- ...existing,
233
- relaycastApiKey: apiKey,
234
- relayfileUrl: existing.relayfileUrl,
235
- createdAt: existing.createdAt ?? new Date().toISOString(),
236
- agents: existing.agents ?? [],
237
- };
238
- this.writeWorkspaceRegistry(registry);
239
- }
240
- findMappedWorkspaceIdByApiKey(apiKey) {
241
- const registry = this.readWorkspaceRegistry();
242
- for (const [workspaceId, entry] of Object.entries(registry)) {
243
- if (entry.relaycastApiKey === apiKey) {
244
- return workspaceId;
245
- }
246
- }
247
- return undefined;
248
- }
249
- getResolvedWorkspaceId() {
250
- return this.resolvedWorkspaceId ?? this.requestedWorkspaceId;
251
- }
252
- getRelaycastBaseUrl() {
253
- return (this.relaycastBaseUrl ??
254
- this.clientOptions.env?.RELAYCAST_BASE_URL ??
255
- process.env.RELAYCAST_BASE_URL ??
256
- 'https://api.relaycast.dev');
257
- }
258
- applyWorkspaceEnv(workspaceId, apiKey) {
259
- // `workspaceId` here is the **relaycast** workspace id resolved by this
260
- // SDK (auto-created or caller-supplied via `new AgentRelay({ workspaceId })`).
261
- // Do NOT write it into `RELAYFILE_WORKSPACE` — relayfile and relaycast
262
- // workspaces are independent ids and a relayfile JWT scoped to a
263
- // different workspace will 403 with "workspace mismatch". Callers that
264
- // share an id across both services (e.g. the canonical `relay on start`
265
- // flow) set `RELAYFILE_WORKSPACE` themselves.
266
- const env = {
267
- ...(this.clientOptions.env ?? process.env),
268
- RELAY_API_KEY: apiKey,
269
- RELAY_DEFAULT_WORKSPACE: workspaceId,
270
- RELAY_WORKSPACE_ID: workspaceId,
271
- RELAY_WORKSPACES_JSON: JSON.stringify([{ workspace_id: workspaceId, api_key: apiKey }]),
272
- };
273
- if (this.relaycastBaseUrl) {
274
- env.RELAYCAST_BASE_URL = this.relaycastBaseUrl;
275
- }
276
- this.clientOptions.env = env;
277
- }
278
- async createMappedRelaycastWorkspace(workspaceId) {
279
- const created = await RelayCast.createWorkspace(this.workspaceName ?? workspaceId, this.getRelaycastBaseUrl());
280
- const workspace = created;
281
- const apiKey = workspace.apiKey ?? workspace.api_key;
282
- if (!apiKey) {
283
- throw new Error('RelayCast.createWorkspace() did not return an API key');
284
- }
285
- return apiKey;
286
- }
287
- /**
288
- * Subscribe to broker stderr output. Listener is wired immediately if the
289
- * client is already started, otherwise it is attached when the client starts.
290
- * Returns an unsubscribe function.
291
- */
292
- onBrokerStderr(listener) {
293
- this.stderrListeners.add(listener);
294
- return () => {
295
- this.stderrListeners.delete(listener);
296
- };
297
- }
298
- // ── Spawning ────────────────────────────────────────────────────────────
299
- async spawnPty(input) {
300
- const client = await this.ensureStarted();
301
- if (!input.channels || input.channels.length === 0) {
302
- console.warn(`[AgentRelay] spawnPty("${input.name}"): no channels specified, defaulting to "general". ` +
303
- 'Set explicit channels for workflow isolation.');
304
- }
305
- const channels = input.channels ?? ['general'];
306
- const lifecycleContext = {
307
- name: input.name,
308
- cli: input.cli,
309
- channels,
310
- task: input.task,
311
- };
312
- await this.invokeLifecycleHook(input.onStart, lifecycleContext, `spawnPty("${input.name}") onStart`);
313
- let result;
314
- const resultContract = this.prepareAgentResultContract(input.result);
315
- if (resultContract) {
316
- this.resultContracts.set(input.name, resultContract);
317
- }
318
- try {
319
- result = await client.spawnPty({
320
- name: input.name,
321
- cli: input.cli,
322
- args: input.args,
323
- channels,
324
- task: input.task,
325
- model: input.model,
326
- cwd: input.cwd,
327
- team: input.team,
328
- agentToken: input.agentToken,
329
- shadowOf: input.shadowOf,
330
- shadowMode: input.shadowMode,
331
- idleThresholdSecs: input.idleThresholdSecs,
332
- restartPolicy: input.restartPolicy,
333
- skipRelayPrompt: input.skipRelayPrompt,
334
- agentResultSchema: resultContract?.jsonSchema,
335
- });
336
- }
337
- catch (error) {
338
- if (resultContract) {
339
- this.resultContracts.delete(input.name);
340
- }
341
- await this.invokeLifecycleHook(input.onError, {
342
- ...lifecycleContext,
343
- error,
344
- }, `spawnPty("${input.name}") onError`);
345
- throw error;
346
- }
347
- this.resetAgentLifecycleState(result.name);
348
- if (result.name !== input.name && resultContract) {
349
- this.resultContracts.delete(input.name);
350
- this.resultContracts.set(result.name, resultContract);
351
- }
352
- const agent = this.makeAgent(result.name, result.runtime, channels);
353
- this.knownAgents.set(agent.name, agent);
354
- await this.invokeLifecycleHook(input.onSuccess, {
355
- ...lifecycleContext,
356
- name: result.name,
357
- runtime: result.runtime,
358
- }, `spawnPty("${input.name}") onSuccess`);
359
- return agent;
360
- }
361
- async spawn(name, cli, task, options) {
362
- return this.spawnPty({
363
- name,
364
- cli,
365
- task,
366
- args: options?.args,
367
- channels: options?.channels,
368
- model: options?.model,
369
- cwd: options?.cwd,
370
- team: options?.team,
371
- agentToken: options?.agentToken,
372
- shadowOf: options?.shadowOf,
373
- shadowMode: options?.shadowMode,
374
- idleThresholdSecs: options?.idleThresholdSecs,
375
- restartPolicy: options?.restartPolicy,
376
- skipRelayPrompt: options?.skipRelayPrompt,
377
- result: options?.result,
378
- onStart: options?.onStart,
379
- onSuccess: options?.onSuccess,
380
- onError: options?.onError,
381
- });
382
- }
383
- async spawnAndWait(name, cli, task, options) {
384
- const { timeoutMs, waitForMessage, ...spawnOptions } = options ?? {};
385
- await this.spawn(name, cli, task, spawnOptions);
386
- if (waitForMessage) {
387
- return this.waitForAgentMessage(name, timeoutMs ?? 60_000);
388
- }
389
- return this.waitForAgentReady(name, timeoutMs ?? 60_000);
390
- }
391
- /**
392
- * Spawn an agent from a named AgentWorkforce persona.
393
- *
394
- * Looks up the persona JSON in the search-dir cascade
395
- * (`<cwd>/agentworkforce/personas`, `<cwd>/.agentworkforce/workforce/personas`,
396
- * `~/.agentworkforce/workforce/personas`, plus `AGENT_WORKFORCE_HOME`),
397
- * resolves the requested tier, and translates it to spawnPty args via
398
- * `@agentworkforce/harness-kit#buildInteractiveSpec`.
399
- *
400
- * For opencode, an `opencode.json` is materialized in the spawn cwd and
401
- * automatically restored when the agent exits. For codex, the persona's
402
- * systemPrompt is folded into the initial task (codex has no
403
- * system-prompt flag). Translation warnings are surfaced via console.warn.
404
- *
405
- * @param personaId — id of the persona to load
406
- * @param options — overrides for tier, search dirs, name, task, and the
407
- * underlying spawn options
408
- */
409
- async spawnPersona(personaId, options = {}) {
410
- const personaCwd = options.personaCwd ?? options.cwd ?? process.cwd();
411
- const searchDirs = options.searchDirs ?? this.defaultPersonaDirs;
412
- const loadOpts = {
413
- cwd: personaCwd,
414
- ...(searchDirs ? { searchDirs } : {}),
415
- ...(options.extraDirs ? { extraDirs: options.extraDirs } : {}),
416
- ...(options.tier ? { tier: options.tier } : {}),
417
- };
418
- const persona = options.persona ?? loadPersona(personaId, loadOpts);
419
- const spec = buildPersonaSpawnSpec(persona);
420
- for (const warning of spec.warnings) {
421
- console.warn(`[AgentRelay] ${warning}`);
422
- }
423
- const spawnCwd = options.cwd ?? process.cwd();
424
- const writes = spec.configFiles.length > 0 ? materializePersonaConfigFiles(spawnCwd, spec.configFiles) : [];
425
- const baseArgs = options.args ?? [];
426
- const mergedArgs = [...spec.args, ...baseArgs];
427
- const task = composePersonaTask(spec, options.task);
428
- const spawnName = options.name ?? persona.id;
429
- let agent;
430
- try {
431
- agent = await this.spawnPty({
432
- name: spawnName,
433
- cli: spec.cli,
434
- args: mergedArgs,
435
- ...(task !== undefined ? { task } : {}),
436
- channels: options.channels,
437
- model: spec.model,
438
- cwd: spawnCwd,
439
- team: options.team,
440
- agentToken: options.agentToken,
441
- shadowOf: options.shadowOf,
442
- shadowMode: options.shadowMode,
443
- idleThresholdSecs: options.idleThresholdSecs,
444
- restartPolicy: options.restartPolicy,
445
- skipRelayPrompt: options.skipRelayPrompt,
446
- result: options.result,
447
- onStart: options.onStart,
448
- onSuccess: options.onSuccess,
449
- onError: options.onError,
450
- });
451
- }
452
- catch (err) {
453
- restorePersonaConfigFiles(writes);
454
- throw err;
455
- }
456
- if (writes.length > 0) {
457
- void agent.waitForExit().finally(() => {
458
- restorePersonaConfigFiles(writes);
459
- });
460
- }
461
- return agent;
462
- }
463
- // ── Human source ────────────────────────────────────────────────────────
464
- human(opts) {
465
- return {
466
- name: opts.name,
467
- sendMessage: async (input) => {
468
- const client = await this.ensureStarted();
469
- let result;
470
- try {
471
- result = await client.sendMessage({
472
- to: input.to,
473
- text: input.text,
474
- from: opts.name,
475
- threadId: input.threadId,
476
- priority: input.priority,
477
- data: input.data,
478
- mode: input.mode,
479
- });
480
- }
481
- catch (error) {
482
- if (isUnsupportedOperation(error)) {
483
- return buildUnsupportedOperationMessage(opts.name, input);
484
- }
485
- throw error;
486
- }
487
- if (result?.event_id === 'unsupported_operation') {
488
- return buildUnsupportedOperationMessage(opts.name, input);
489
- }
490
- const eventId = result?.event_id ?? randomBytes(8).toString('hex');
491
- const msg = {
492
- eventId,
493
- from: opts.name,
494
- to: input.to,
495
- text: input.text,
496
- threadId: input.threadId,
497
- data: input.data,
498
- mode: input.mode,
499
- };
500
- void this.bus.emit('messageSent', msg);
501
- return msg;
502
- },
503
- };
504
- }
505
- system() {
506
- return this.human({ name: 'system' });
507
- }
508
- // ── Messaging ─────────────────────────────────────────────────────────
509
- /**
510
- * Broadcast a message to all connected agents.
511
- * @param text — the message body
512
- * @param options — optional sender name (defaults to "human:orchestrator")
513
- */
514
- async broadcast(text, options) {
515
- const from = options?.from ?? 'human:orchestrator';
516
- return this.human({ name: from }).sendMessage({ to: '*', text });
517
- }
518
- async sendAndWaitForDelivery(input, timeoutMs = 30_000) {
519
- const client = await this.ensureStarted();
520
- const result = await client.sendMessage(input);
521
- if (!result.targets.length) {
522
- return { eventId: result.event_id, status: 'failed', targets: [] };
523
- }
524
- return new Promise((resolve) => {
525
- let resolved = false;
526
- const ackedTargets = new Set();
527
- const confirmedTargets = new Set();
528
- // eslint-disable-next-line prefer-const
529
- let unsubscribe;
530
- const timer = setTimeout(() => {
531
- if (!resolved) {
532
- resolved = true;
533
- unsubscribe?.();
534
- resolve({ eventId: result.event_id, status: 'timeout', targets: result.targets });
535
- }
536
- }, timeoutMs);
537
- unsubscribe = client.onEvent((event) => {
538
- if (resolved)
539
- return;
540
- if (event.kind === 'delivery_ack' &&
541
- event.event_id === result.event_id &&
542
- result.targets.includes(event.name)) {
543
- ackedTargets.add(event.name);
544
- }
545
- if (event.kind === 'message_delivery_confirmed' &&
546
- event.event_id === result.event_id &&
547
- result.targets.includes(event.name)) {
548
- confirmedTargets.add(event.name);
549
- if (confirmedTargets.size >= result.targets.length) {
550
- resolved = true;
551
- clearTimeout(timer);
552
- unsubscribe?.();
553
- resolve({ eventId: result.event_id, status: 'ack', targets: result.targets });
554
- }
555
- }
556
- if (event.kind === 'message_delivery_failed' &&
557
- event.event_id === result.event_id &&
558
- result.targets.includes(event.name)) {
559
- resolved = true;
560
- clearTimeout(timer);
561
- unsubscribe?.();
562
- resolve({ eventId: result.event_id, status: 'failed', targets: result.targets });
563
- }
564
- });
565
- });
566
- }
567
- // ── Listing ─────────────────────────────────────────────────────────────
568
- async listAgents() {
569
- const client = await this.ensureStarted();
570
- const list = await client.listAgents();
571
- return list.map((entry) => {
572
- const existing = this.knownAgents.get(entry.name);
573
- if (existing)
574
- return existing;
575
- const agent = this.makeAgent(entry.name, entry.runtime, entry.channels);
576
- this.knownAgents.set(agent.name, agent);
577
- return agent;
578
- });
579
- }
580
- /** Pre-register a batch of agents with Relaycast before steps execute. */
581
- async preflightAgents(agents) {
582
- const client = await this.ensureStarted();
583
- await client.preflight(agents);
584
- }
585
- /** List agents with PIDs from the broker (for worker registration). */
586
- async listAgentsRaw() {
587
- const client = await this.ensureStarted();
588
- return client.listAgents();
589
- }
590
- // ── Status ────────────────────────────────────────────────────────────
591
- async getStatus() {
592
- const client = await this.ensureStarted();
593
- return client.getStatus();
594
- }
595
- async subscribe(opts) {
596
- const client = await this.ensureStarted();
597
- await client.subscribeChannels(opts.agent, opts.channels);
598
- this.addAgentChannels(opts.agent, opts.channels);
599
- }
600
- async unsubscribe(opts) {
601
- const client = await this.ensureStarted();
602
- await client.unsubscribeChannels(opts.agent, opts.channels);
603
- this.removeAgentChannels(opts.agent, opts.channels);
604
- }
605
- getDeliveryState(eventId) {
606
- return this.deliveryStates.get(eventId);
607
- }
608
- // ── Logs ──────────────────────────────────────────────────────────────
609
- /**
610
- * Read the last N lines of an agent's log file.
611
- *
612
- * @example
613
- * ```ts
614
- * const logs = await relay.getLogs("Worker1", { lines: 100 });
615
- * if (logs.found) console.log(logs.content);
616
- * ```
617
- */
618
- async getLogs(agentName, options) {
619
- const cwd = this.clientOptions.cwd ?? process.cwd();
620
- const logsDir = path.join(cwd, '.agent-relay', 'team', 'worker-logs');
621
- return getLogsFromFile(agentName, { logsDir, lines: options?.lines });
622
- }
623
- /** List all agents that have log files. */
624
- async listLoggedAgents() {
625
- const cwd = this.clientOptions.cwd ?? process.cwd();
626
- const logsDir = path.join(cwd, '.agent-relay', 'team', 'worker-logs');
627
- return listLoggedAgentsFromFile(logsDir);
628
- }
629
- /**
630
- * Follow an agent's local log file with history bootstrap + incremental updates.
631
- *
632
- * @example
633
- * ```ts
634
- * const handle = relay.followLogs("Worker1", {
635
- * historyLines: 100,
636
- * onEvent(event) {
637
- * if (event.type === "log") console.log(event.content);
638
- * },
639
- * });
640
- *
641
- * // Later:
642
- * handle.unsubscribe();
643
- * ```
644
- */
645
- followLogs(agentName, options) {
646
- const cwd = this.clientOptions.cwd ?? process.cwd();
647
- const logsDir = path.join(cwd, '.agent-relay', 'team', 'worker-logs');
648
- return followLogsFromFile(agentName, { ...options, logsDir });
649
- }
650
- // ── Wait helpers ──────────────────────────────────────────────────────
651
- /**
652
- * Wait for any one of the given agents to exit. Returns the first agent
653
- * that exits along with its exit reason.
654
- *
655
- * @example
656
- * ```ts
657
- * const { agent, result } = await AgentRelay.waitForAny([worker1, worker2], 60_000);
658
- * console.log(`${agent.name} finished: ${result}`);
659
- * ```
660
- */
661
- static async waitForAny(agents, timeoutMs) {
662
- if (agents.length === 0) {
663
- throw new Error('waitForAny requires at least one agent');
664
- }
665
- return Promise.race(agents.map(async (agent) => {
666
- const result = await agent.waitForExit(timeoutMs);
667
- return { agent, result };
668
- }));
669
- }
670
- /**
671
- * Resolves when the agent process has started and connected to the broker.
672
- * The agent's CLI may not yet be ready to receive messages.
673
- * Use `waitForAgentMessage()` for full readiness.
674
- */
675
- async waitForAgentReady(name, timeoutMs = 60_000) {
676
- const client = await this.ensureStarted();
677
- const existing = this.knownAgents.get(name);
678
- if (existing && this.readyAgents.has(name)) {
679
- return existing;
680
- }
681
- return new Promise((resolve, reject) => {
682
- let settled = false;
683
- let timeout;
684
- const cleanup = () => {
685
- unsubscribe();
686
- if (timeout) {
687
- clearTimeout(timeout);
688
- timeout = undefined;
689
- }
690
- };
691
- const resolveWith = (agent) => {
692
- if (settled)
693
- return;
694
- settled = true;
695
- cleanup();
696
- resolve(agent);
697
- };
698
- const rejectWith = (error) => {
699
- if (settled)
700
- return;
701
- settled = true;
702
- cleanup();
703
- reject(error);
704
- };
705
- const unsubscribe = client.onEvent((event) => {
706
- if (event.kind !== 'worker_ready' || event.name !== name) {
707
- return;
708
- }
709
- const agent = this.ensureAgentHandle(event.name, event.runtime);
710
- this.readyAgents.add(event.name);
711
- this.exitedAgents.delete(event.name);
712
- resolveWith(agent);
713
- });
714
- timeout = setTimeout(() => {
715
- rejectWith(new Error(`Timed out waiting for worker_ready for '${name}' after ${timeoutMs}ms`));
716
- }, timeoutMs);
717
- const known = this.knownAgents.get(name);
718
- if (known && this.readyAgents.has(name)) {
719
- resolveWith(known);
720
- }
721
- });
722
- }
723
- async waitForAgentMessage(name, timeoutMs = 60_000) {
724
- const client = await this.ensureStarted();
725
- const existing = this.knownAgents.get(name);
726
- if (existing && this.messageReadyAgents.has(name)) {
727
- return existing;
728
- }
729
- return new Promise((resolve, reject) => {
730
- let settled = false;
731
- let timeout;
732
- const cleanup = () => {
733
- unsubscribe();
734
- if (timeout) {
735
- clearTimeout(timeout);
736
- timeout = undefined;
737
- }
738
- };
739
- const resolveWith = (agent) => {
740
- if (settled)
741
- return;
742
- settled = true;
743
- cleanup();
744
- resolve(agent);
745
- };
746
- const rejectWith = (error) => {
747
- if (settled)
748
- return;
749
- settled = true;
750
- cleanup();
751
- reject(error);
752
- };
753
- const unsubscribe = client.onEvent((event) => {
754
- if (event.kind === 'relay_inbound' && event.from === name) {
755
- this.messageReadyAgents.add(name);
756
- this.exitedAgents.delete(name);
757
- resolveWith(this.ensureAgentHandle(name));
758
- return;
759
- }
760
- if (event.kind === 'agent_exited' && event.name === name) {
761
- rejectWith(new Error(`Agent '${name}' exited before sending its first relay message`));
762
- return;
763
- }
764
- if (event.kind === 'agent_released' && event.name === name) {
765
- rejectWith(new Error(`Agent '${name}' was released before sending its first relay message`));
766
- }
767
- });
768
- timeout = setTimeout(() => {
769
- rejectWith(new Error(`Timed out waiting for first relay message from '${name}' after ${timeoutMs}ms`));
770
- }, timeoutMs);
771
- const known = this.knownAgents.get(name);
772
- if (known && this.messageReadyAgents.has(name)) {
773
- resolveWith(known);
774
- }
775
- });
776
- }
777
- // ── Lifecycle ───────────────────────────────────────────────────────────
778
- async shutdown() {
779
- if (this.unsubEvent) {
780
- this.unsubEvent();
781
- this.unsubEvent = undefined;
782
- }
783
- let client = this.client;
784
- if (!client && this.startPromise) {
785
- try {
786
- client = await this.startPromise;
787
- }
788
- catch {
789
- client = undefined;
790
- }
791
- }
792
- if (client) {
793
- await client.shutdown();
794
- if (this.client === client) {
795
- this.client = undefined;
796
- }
797
- }
798
- this.startPromise = undefined;
799
- this.knownAgents.clear();
800
- this.readyAgents.clear();
801
- this.messageReadyAgents.clear();
802
- this.exitedAgents.clear();
803
- this.idleAgents.clear();
804
- this.deliveryStates.clear();
805
- this.agentActivityStates.clear();
806
- this.outputListeners.clear();
807
- for (const entry of this.exitResolvers.values()) {
808
- entry.resolve('released');
809
- }
810
- this.exitResolvers.clear();
811
- for (const entry of this.idleResolvers.values()) {
812
- entry.resolve('exited');
813
- }
814
- this.idleResolvers.clear();
815
- const shutdownError = new Error('AgentRelay shutdown before structured result was submitted');
816
- for (const waiters of this.resultResolvers.values()) {
817
- for (const waiter of waiters) {
818
- waiter.reject(shutdownError);
819
- }
820
- }
821
- this.resultResolvers.clear();
822
- this.resultContracts.clear();
823
- this.lastAgentResults.clear();
824
- }
825
- // ── Private helpers ─────────────────────────────────────────────────────
826
- ensureAgentHandle(name, runtime = 'pty', channels = []) {
827
- const existing = this.knownAgents.get(name);
828
- if (existing) {
829
- return existing;
830
- }
831
- const agent = this.makeAgent(name, runtime, channels);
832
- this.knownAgents.set(name, agent);
833
- return agent;
834
- }
835
- updateDeliveryState(eventId, to, status, updatedAt) {
836
- this.deliveryStates.set(eventId, { eventId, to, status, updatedAt });
837
- }
838
- ensureAgentActivityState(name) {
839
- const existing = this.agentActivityStates.get(name);
840
- if (existing) {
841
- return existing;
842
- }
843
- const state = {
844
- active: false,
845
- pendingDeliveries: new Map(),
846
- };
847
- this.agentActivityStates.set(name, state);
848
- return state;
849
- }
850
- getDeliveryActivityKey(deliveryId, eventId) {
851
- return deliveryId || eventId;
852
- }
853
- markAgentDeliveryPending(name, deliveryId, eventId, reason) {
854
- const state = this.ensureAgentActivityState(name);
855
- state.pendingDeliveries.set(this.getDeliveryActivityKey(deliveryId, eventId), eventId);
856
- this.setAgentActivity(name, state, state.pendingDeliveries.size > 0, reason, eventId);
857
- }
858
- closeAgentDelivery(name, reason, eventId, deliveryId) {
859
- const state = this.agentActivityStates.get(name);
860
- if (!state)
861
- return;
862
- const key = deliveryId && eventId ? this.getDeliveryActivityKey(deliveryId, eventId) : undefined;
863
- if (key) {
864
- state.pendingDeliveries.delete(key);
865
- }
866
- else if (eventId) {
867
- const matchingEntry = Array.from(state.pendingDeliveries.entries()).find(([, pendingEventId]) => {
868
- return pendingEventId === eventId;
869
- });
870
- if (matchingEntry) {
871
- state.pendingDeliveries.delete(matchingEntry[0]);
872
- }
873
- else {
874
- const oldestKey = state.pendingDeliveries.keys().next().value;
875
- if (oldestKey) {
876
- state.pendingDeliveries.delete(oldestKey);
877
- }
878
- }
879
- }
880
- this.setAgentActivity(name, state, state.pendingDeliveries.size > 0, reason, eventId);
881
- }
882
- clearAgentDeliveries(name, reason, eventId) {
883
- const state = this.agentActivityStates.get(name);
884
- if (!state)
885
- return;
886
- state.pendingDeliveries.clear();
887
- this.setAgentActivity(name, state, false, reason, eventId);
888
- }
889
- setAgentActivity(name, state, active, reason, eventId) {
890
- if (state.active === active) {
891
- return;
892
- }
893
- state.active = active;
894
- void this.bus.emit('agentActivityChanged', {
895
- name,
896
- active,
897
- pendingDeliveries: state.pendingDeliveries.size,
898
- reason,
899
- eventId,
900
- });
901
- }
902
- resolveEventTimestamp(candidate) {
903
- return typeof candidate === 'number' ? candidate : Date.now();
904
- }
905
- addAgentChannels(name, channels) {
906
- const agent = this.knownAgents.get(name);
907
- if (!agent || channels.length === 0)
908
- return;
909
- const next = [...new Set([...agent.channels, ...channels])];
910
- agent._setChannels(next);
911
- }
912
- removeAgentChannels(name, channels) {
913
- const agent = this.knownAgents.get(name);
914
- if (!agent || channels.length === 0)
915
- return;
916
- const removed = new Set(channels);
917
- agent._setChannels(agent.channels.filter((channel) => !removed.has(channel)));
918
- }
919
- /** Resolve a target to a channel name. If `to` is `#channel`, use that
920
- * channel. If it's a known agent name, use the agent's first channel.
921
- * Otherwise fall back to the relay's default channel. */
922
- resolveChannel(to) {
923
- if (to.startsWith('#'))
924
- return to.slice(1);
925
- const agent = this.knownAgents.get(to);
926
- if (agent && agent.channels.length > 0)
927
- return agent.channels[0];
928
- return this.defaultChannels[0];
929
- }
930
- inferOutputMode(callback) {
931
- const source = callback.toString().trim().replace(/\s+/g, ' ');
932
- if (source.startsWith('({') || source.startsWith('async ({') || source.startsWith('function ({')) {
933
- return 'structured';
934
- }
935
- return 'chunk';
936
- }
937
- dispatchOutput(name, stream, chunk) {
938
- const listeners = this.outputListeners.get(name);
939
- if (!listeners)
940
- return;
941
- for (const listener of listeners) {
942
- if (listener.stream !== undefined && listener.stream !== stream)
943
- continue;
944
- if (listener.mode === 'structured') {
945
- listener.callback({ stream, chunk });
946
- }
947
- else {
948
- listener.callback(chunk);
949
- }
950
- }
951
- }
952
- /**
953
- * Ensure a Relaycast workspace API key is available.
954
- * Resolution order:
955
- * 1. Already resolved (cached from a previous call)
956
- * 2. RELAY_API_KEY in options.env
957
- * 3. RELAY_API_KEY in process.env
958
- * 4. Auto-create a fresh workspace via the Relaycast REST API
959
- */
960
- async ensureRelaycastApiKey() {
961
- if (this.relayApiKey) {
962
- const workspaceId = this.getResolvedWorkspaceId();
963
- if (workspaceId) {
964
- this.applyWorkspaceEnv(workspaceId, this.relayApiKey);
965
- try {
966
- this.persistWorkspaceMapping(workspaceId, this.relayApiKey);
967
- }
968
- catch {
969
- /* non-critical */
970
- }
971
- }
972
- else {
973
- this.wireRelaycastBaseUrl();
974
- }
975
- return;
976
- }
977
- const envKey = this.clientOptions.env?.RELAY_API_KEY ?? process.env.RELAY_API_KEY;
978
- const requestedWorkspaceId = this.requestedWorkspaceId;
979
- if (requestedWorkspaceId) {
980
- const registry = this.readWorkspaceRegistry();
981
- const mappedKey = registry[requestedWorkspaceId]?.relaycastApiKey;
982
- const resolvedKey = mappedKey ?? envKey ?? (await this.createMappedRelaycastWorkspace(requestedWorkspaceId));
983
- this.relayApiKey = resolvedKey;
984
- this.resolvedWorkspaceId = requestedWorkspaceId;
985
- this.applyWorkspaceEnv(requestedWorkspaceId, resolvedKey);
986
- try {
987
- this.persistWorkspaceMapping(requestedWorkspaceId, resolvedKey);
988
- }
989
- catch {
990
- /* non-critical */
991
- }
992
- return;
993
- }
994
- const resolvedWorkspaceId = envKey
995
- ? (this.findMappedWorkspaceIdByApiKey(envKey) ?? generateWorkspaceId())
996
- : generateWorkspaceId();
997
- const resolvedKey = envKey ?? (await this.createMappedRelaycastWorkspace(resolvedWorkspaceId));
998
- this.relayApiKey = resolvedKey;
999
- this.resolvedWorkspaceId = resolvedWorkspaceId;
1000
- this.applyWorkspaceEnv(resolvedWorkspaceId, resolvedKey);
1001
- try {
1002
- this.persistWorkspaceMapping(resolvedWorkspaceId, resolvedKey);
1003
- }
1004
- catch {
1005
- /* non-critical */
1006
- }
1007
- }
1008
- /** Inject relaycastBaseUrl into broker env. Explicit option wins over inherited env. */
1009
- wireRelaycastBaseUrl() {
1010
- if (this.relaycastBaseUrl && this.clientOptions.env) {
1011
- this.clientOptions.env.RELAYCAST_BASE_URL = this.relaycastBaseUrl;
1012
- }
1013
- }
1014
- async ensureStarted() {
1015
- if (this.client)
1016
- return this.client;
1017
- if (this.startPromise)
1018
- return this.startPromise;
1019
- this.startPromise = this.ensureRelaycastApiKey()
1020
- .then(() => AgentRelayClient.spawn({
1021
- ...this.clientOptions,
1022
- eventBus: this.bus,
1023
- onStderr: (line) => {
1024
- for (const listener of this.stderrListeners) {
1025
- try {
1026
- listener(line);
1027
- }
1028
- catch {
1029
- /* ignore */
1030
- }
1031
- }
1032
- },
1033
- }))
1034
- .then((c) => {
1035
- // Use the workspace key the broker actually connected with.
1036
- // This ensures SDK and workers are always on the same workspace.
1037
- if (c.workspaceKey) {
1038
- this.relayApiKey = c.workspaceKey;
1039
- const workspaceId = this.getResolvedWorkspaceId();
1040
- if (workspaceId) {
1041
- this.applyWorkspaceEnv(workspaceId, c.workspaceKey);
1042
- try {
1043
- this.persistWorkspaceMapping(workspaceId, c.workspaceKey);
1044
- }
1045
- catch {
1046
- /* non-critical */
1047
- }
1048
- }
1049
- }
1050
- this.wireEvents(c);
1051
- this.client = c;
1052
- this.startPromise = undefined;
1053
- return c;
1054
- })
1055
- .catch((err) => {
1056
- this.client = undefined;
1057
- this.startPromise = undefined;
1058
- throw err;
1059
- });
1060
- return this.startPromise;
1061
- }
1062
- wireEvents(client) {
1063
- // eslint-disable-next-line complexity
1064
- this.unsubEvent = client.onEvent((event) => {
1065
- switch (event.kind) {
1066
- case 'relay_inbound': {
1067
- this.closeAgentDelivery(event.from, 'relay_inbound', event.event_id);
1068
- if (this.knownAgents.has(event.from)) {
1069
- this.messageReadyAgents.add(event.from);
1070
- this.exitedAgents.delete(event.from);
1071
- }
1072
- this.clearAgentDeliveries(event.from, 'relay_inbound', event.event_id);
1073
- const msg = {
1074
- eventId: event.event_id,
1075
- from: event.from,
1076
- to: event.target,
1077
- text: event.body,
1078
- threadId: event.thread_id,
1079
- mode: event.injection_mode ?? event.mode,
1080
- };
1081
- void this.bus.emit('messageReceived', msg);
1082
- break;
1083
- }
1084
- case 'agent_spawned': {
1085
- const agent = this.ensureAgentHandle(event.name, event.runtime);
1086
- this.readyAgents.delete(event.name);
1087
- this.messageReadyAgents.delete(event.name);
1088
- this.exitedAgents.delete(event.name);
1089
- this.idleAgents.delete(event.name);
1090
- void this.bus.emit('agentSpawned', agent);
1091
- break;
1092
- }
1093
- case 'agent_released': {
1094
- const agent = this.knownAgents.get(event.name) ?? this.ensureAgentHandle(event.name, 'pty', []);
1095
- this.clearAgentDeliveries(event.name, 'agent_released');
1096
- this.exitedAgents.add(event.name);
1097
- this.readyAgents.delete(event.name);
1098
- this.messageReadyAgents.delete(event.name);
1099
- this.idleAgents.delete(event.name);
1100
- void this.bus.emit('agentReleased', agent);
1101
- this.knownAgents.delete(event.name);
1102
- this.outputListeners.delete(event.name);
1103
- this.resultContracts.delete(event.name);
1104
- this.exitResolvers.get(event.name)?.resolve('released');
1105
- this.exitResolvers.delete(event.name);
1106
- this.idleResolvers.get(event.name)?.resolve('exited');
1107
- this.idleResolvers.delete(event.name);
1108
- for (const waiter of this.takeResultResolvers(event.name)) {
1109
- waiter.reject(new Error(`Agent '${event.name}' was released before submitting a result`));
1110
- }
1111
- break;
1112
- }
1113
- case 'agent_exited': {
1114
- const agent = this.knownAgents.get(event.name) ?? this.ensureAgentHandle(event.name, 'pty', []);
1115
- this.clearAgentDeliveries(event.name, 'agent_exited');
1116
- this.exitedAgents.add(event.name);
1117
- this.readyAgents.delete(event.name);
1118
- this.messageReadyAgents.delete(event.name);
1119
- this.idleAgents.delete(event.name);
1120
- // Populate exit info before firing the hook
1121
- agent.exitCode = event.code;
1122
- agent.exitSignal = event.signal;
1123
- if (event.reason !== undefined) {
1124
- agent.exitReason = event.reason;
1125
- }
1126
- void this.bus.emit('agentExited', agent);
1127
- this.knownAgents.delete(event.name);
1128
- this.outputListeners.delete(event.name);
1129
- this.resultContracts.delete(event.name);
1130
- this.exitResolvers.get(event.name)?.resolve('exited');
1131
- this.exitResolvers.delete(event.name);
1132
- this.idleResolvers.get(event.name)?.resolve('exited');
1133
- this.idleResolvers.delete(event.name);
1134
- for (const waiter of this.takeResultResolvers(event.name)) {
1135
- waiter.reject(new Error(`Agent '${event.name}' exited before submitting a result`));
1136
- }
1137
- break;
1138
- }
1139
- case 'agent_exit': {
1140
- const agent = this.knownAgents.get(event.name) ?? this.ensureAgentHandle(event.name, 'pty', []);
1141
- agent.exitReason = event.reason;
1142
- void this.bus.emit('agentExitRequested', { name: event.name, reason: event.reason });
1143
- break;
1144
- }
1145
- case 'worker_ready': {
1146
- const agent = this.ensureAgentHandle(event.name, event.runtime);
1147
- this.readyAgents.add(event.name);
1148
- this.exitedAgents.delete(event.name);
1149
- this.idleAgents.delete(event.name);
1150
- void this.bus.emit('agentReady', agent);
1151
- break;
1152
- }
1153
- case 'channel_subscribed': {
1154
- this.addAgentChannels(event.name, event.channels);
1155
- void this.bus.emit('channelSubscribed', { agent: event.name, channels: event.channels });
1156
- break;
1157
- }
1158
- case 'channel_unsubscribed': {
1159
- this.removeAgentChannels(event.name, event.channels);
1160
- void this.bus.emit('channelUnsubscribed', { agent: event.name, channels: event.channels });
1161
- break;
1162
- }
1163
- case 'delivery_queued': {
1164
- this.markAgentDeliveryPending(event.name, event.delivery_id, event.event_id, 'delivery_queued');
1165
- this.updateDeliveryState(event.event_id, event.name, 'queued', this.resolveEventTimestamp(event.timestamp));
1166
- break;
1167
- }
1168
- case 'delivery_injected': {
1169
- this.markAgentDeliveryPending(event.name, event.delivery_id, event.event_id, 'delivery_injected');
1170
- this.updateDeliveryState(event.event_id, event.name, 'injected', this.resolveEventTimestamp(event.timestamp));
1171
- break;
1172
- }
1173
- case 'delivery_active': {
1174
- this.markAgentDeliveryPending(event.name, event.delivery_id, event.event_id, 'delivery_active');
1175
- this.updateDeliveryState(event.event_id, event.name, 'active', this.resolveEventTimestamp());
1176
- break;
1177
- }
1178
- case 'delivery_verified': {
1179
- this.updateDeliveryState(event.event_id, event.name, 'verified', this.resolveEventTimestamp());
1180
- break;
1181
- }
1182
- case 'delivery_ack': {
1183
- // No-op for activity tracking. delivery_ack can arrive late, after
1184
- // relay_inbound / idle / exit already cleared activity, so re-adding
1185
- // pending state here would incorrectly flip the agent back to active.
1186
- break;
1187
- }
1188
- case 'delivery_failed': {
1189
- this.closeAgentDelivery(event.name, 'delivery_failed', event.event_id, event.delivery_id);
1190
- this.updateDeliveryState(event.event_id, event.name, 'failed', this.resolveEventTimestamp());
1191
- break;
1192
- }
1193
- case 'message_delivery_confirmed': {
1194
- this.closeAgentDelivery(event.name, 'message_delivery_confirmed', event.event_id, event.delivery_id);
1195
- this.updateDeliveryState(event.event_id, event.name, 'verified', this.resolveEventTimestamp());
1196
- break;
1197
- }
1198
- case 'message_delivery_failed': {
1199
- if (event.event_id) {
1200
- this.updateDeliveryState(event.event_id, event.name, 'failed', this.resolveEventTimestamp());
1201
- }
1202
- if (event.event_id && event.delivery_id) {
1203
- this.closeAgentDelivery(event.name, 'message_delivery_failed', event.event_id, event.delivery_id);
1204
- }
1205
- break;
1206
- }
1207
- case 'worker_stream': {
1208
- // Agent producing output is no longer idle
1209
- this.idleAgents.delete(event.name);
1210
- void this.bus.emit('workerOutput', {
1211
- name: event.name,
1212
- stream: event.stream,
1213
- chunk: event.chunk,
1214
- });
1215
- // Dispatch to per-agent output listeners
1216
- this.dispatchOutput(event.name, event.stream, event.chunk);
1217
- break;
1218
- }
1219
- case 'agent_idle': {
1220
- this.clearAgentDeliveries(event.name, 'agent_idle');
1221
- this.idleAgents.add(event.name);
1222
- void this.bus.emit('agentIdle', {
1223
- name: event.name,
1224
- idleSecs: event.idle_secs,
1225
- });
1226
- // Resolve idle waiters
1227
- this.idleResolvers.get(event.name)?.resolve('idle');
1228
- this.idleResolvers.delete(event.name);
1229
- break;
1230
- }
1231
- case 'agent_result': {
1232
- this.dispatchAgentResult(event.name, {
1233
- name: event.name,
1234
- resultId: event.result_id,
1235
- data: event.data,
1236
- final: event.final,
1237
- metadata: event.metadata ?? undefined,
1238
- });
1239
- break;
1240
- }
1241
- }
1242
- if (event.kind.startsWith('delivery_') || event.kind.startsWith('message_delivery_')) {
1243
- void this.bus.emit('deliveryUpdate', event);
1244
- }
1245
- });
1246
- }
1247
- prepareAgentResultContract(options) {
1248
- if (!options) {
1249
- return undefined;
1250
- }
1251
- return {
1252
- schema: options.schema,
1253
- jsonSchema: options.jsonSchema ?? this.schemaToJsonSchema(options.schema),
1254
- onResult: options.onResult,
1255
- };
1256
- }
1257
- schemaToJsonSchema(schema) {
1258
- if (schema && typeof schema === 'object' && this.isZodSchema(schema)) {
1259
- return zodToJsonSchema(schema, { target: 'jsonSchema7' });
1260
- }
1261
- return true;
1262
- }
1263
- isZodSchema(schema) {
1264
- return '_def' in schema && typeof schema.safeParse === 'function';
1265
- }
1266
- validateAgentResult(contract, value) {
1267
- const schema = contract?.schema;
1268
- if (!schema) {
1269
- return value;
1270
- }
1271
- if (typeof schema === 'function') {
1272
- return schema(value);
1273
- }
1274
- if (typeof schema.safeParse === 'function') {
1275
- const parsed = schema.safeParse(value);
1276
- if (parsed.success) {
1277
- return parsed.data;
1278
- }
1279
- throw new Error(`Agent result failed schema validation: ${String(parsed.error)}`);
1280
- }
1281
- if (typeof schema.parse === 'function') {
1282
- return schema.parse(value);
1283
- }
1284
- return value;
1285
- }
1286
- takeResultResolvers(name) {
1287
- const waiters = this.resultResolvers.get(name);
1288
- if (!waiters || waiters.length === 0)
1289
- return [];
1290
- this.resultResolvers.delete(name);
1291
- return waiters;
1292
- }
1293
- dispatchAgentResult(name, raw) {
1294
- const contract = this.resultContracts.get(name);
1295
- let result;
1296
- try {
1297
- const data = this.validateAgentResult(contract, raw.data);
1298
- result = { ...raw, data };
1299
- }
1300
- catch (error) {
1301
- const err = error instanceof Error ? error : new Error(String(error));
1302
- for (const waiter of this.takeResultResolvers(name))
1303
- waiter.reject(err);
1304
- console.warn(`[AgentRelay] structured result from "${name}" failed validation`, err);
1305
- return;
1306
- }
1307
- void this.bus.emit('agentResult', result);
1308
- if (contract?.onResult) {
1309
- Promise.resolve(contract.onResult(result.data, result)).catch((error) => {
1310
- console.warn(`[AgentRelay] result("${name}") onResult hook threw`, error);
1311
- });
1312
- }
1313
- if (result.final) {
1314
- this.lastAgentResults.set(name, result);
1315
- for (const waiter of this.takeResultResolvers(name))
1316
- waiter.resolve(result);
1317
- }
1318
- }
1319
- waitForAgentResult(name, timeoutMs) {
1320
- const existing = this.lastAgentResults.get(name);
1321
- if (existing) {
1322
- return Promise.resolve(existing);
1323
- }
1324
- // Don't register a waiter for an agent we don't know about and haven't
1325
- // observed a result for — the resolver would never settle.
1326
- if (!this.knownAgents.has(name) && !this.resultContracts.has(name)) {
1327
- return Promise.reject(new Error(`Agent '${name}' is not running and has no structured result`));
1328
- }
1329
- if (timeoutMs === 0) {
1330
- return Promise.reject(new Error(`Timed out waiting for structured result from '${name}'`));
1331
- }
1332
- return new Promise((resolve, reject) => {
1333
- let timer;
1334
- const token = ++this.resultResolverSeq;
1335
- const waiter = {
1336
- resolve: (result) => {
1337
- if (timer)
1338
- clearTimeout(timer);
1339
- resolve(result);
1340
- },
1341
- reject: (error) => {
1342
- if (timer)
1343
- clearTimeout(timer);
1344
- reject(error);
1345
- },
1346
- token,
1347
- };
1348
- const existingWaiters = this.resultResolvers.get(name);
1349
- if (existingWaiters) {
1350
- existingWaiters.push(waiter);
1351
- }
1352
- else {
1353
- this.resultResolvers.set(name, [waiter]);
1354
- }
1355
- if (timeoutMs !== undefined) {
1356
- timer = setTimeout(() => {
1357
- const list = this.resultResolvers.get(name);
1358
- if (list) {
1359
- const idx = list.findIndex((w) => w.token === token);
1360
- if (idx >= 0)
1361
- list.splice(idx, 1);
1362
- if (list.length === 0)
1363
- this.resultResolvers.delete(name);
1364
- }
1365
- reject(new Error(`Timed out waiting for structured result from '${name}' after ${timeoutMs}ms`));
1366
- }, timeoutMs);
1367
- }
1368
- });
1369
- }
1370
- makeAgent(name, runtime, channels) {
1371
- // eslint-disable-next-line @typescript-eslint/no-this-alias
1372
- const relay = this;
1373
- let agentChannels = [...channels];
1374
- const agent = {
1375
- name,
1376
- runtime,
1377
- get channels() {
1378
- return [...agentChannels];
1379
- },
1380
- get status() {
1381
- if (relay.exitedAgents.has(name))
1382
- return 'exited';
1383
- if (relay.idleAgents.has(name))
1384
- return 'idle';
1385
- if (relay.readyAgents.has(name))
1386
- return 'ready';
1387
- return 'spawning';
1388
- },
1389
- exitCode: undefined,
1390
- exitSignal: undefined,
1391
- async release(reasonOrOptions) {
1392
- const releaseOptions = relay.normalizeReleaseOptions(reasonOrOptions);
1393
- const releaseContext = {
1394
- name,
1395
- reason: releaseOptions.reason,
1396
- };
1397
- if (!relay.knownAgents.has(name)) {
1398
- await relay.invokeLifecycleHook(releaseOptions.onStart, releaseContext, `release("${name}") onStart`);
1399
- await relay.invokeLifecycleHook(releaseOptions.onSuccess, releaseContext, `release("${name}") onSuccess`);
1400
- return;
1401
- }
1402
- const client = await relay.ensureStarted();
1403
- await relay.invokeLifecycleHook(releaseOptions.onStart, releaseContext, `release("${name}") onStart`);
1404
- try {
1405
- await client.release(name, releaseOptions.reason);
1406
- await relay.invokeLifecycleHook(releaseOptions.onSuccess, releaseContext, `release("${name}") onSuccess`);
1407
- }
1408
- catch (error) {
1409
- if (error instanceof AgentRelayProtocolError && error.code === 'agent_not_found') {
1410
- relay.exitedAgents.add(name);
1411
- relay.readyAgents.delete(name);
1412
- relay.messageReadyAgents.delete(name);
1413
- relay.idleAgents.delete(name);
1414
- relay.knownAgents.delete(name);
1415
- relay.outputListeners.delete(name);
1416
- relay.exitResolvers.get(name)?.resolve('released');
1417
- relay.exitResolvers.delete(name);
1418
- relay.idleResolvers.get(name)?.resolve('exited');
1419
- relay.idleResolvers.delete(name);
1420
- relay.resultContracts.delete(name);
1421
- relay.lastAgentResults.delete(name);
1422
- for (const waiter of relay.takeResultResolvers(name)) {
1423
- waiter.reject(new Error(`Agent '${name}' was released before submitting a result`));
1424
- }
1425
- await relay.invokeLifecycleHook(releaseOptions.onSuccess, releaseContext, `release("${name}") onSuccess`);
1426
- return;
1427
- }
1428
- await relay.invokeLifecycleHook(releaseOptions.onError, {
1429
- ...releaseContext,
1430
- error,
1431
- }, `release("${name}") onError`);
1432
- throw error;
1433
- }
1434
- },
1435
- async waitForReady(timeoutMs = 60_000) {
1436
- await relay.waitForAgentReady(name, timeoutMs);
1437
- },
1438
- waitForExit(timeoutMs) {
1439
- return new Promise((resolve) => {
1440
- // If already gone, resolve immediately
1441
- if (!relay.knownAgents.has(name)) {
1442
- resolve('exited');
1443
- return;
1444
- }
1445
- // Non-blocking poll: timeoutMs === 0 means "check now, return immediately"
1446
- if (timeoutMs === 0) {
1447
- resolve('timeout');
1448
- return;
1449
- }
1450
- let timer;
1451
- const token = ++relay.exitResolverSeq;
1452
- relay.exitResolvers.set(name, {
1453
- resolve(reason) {
1454
- if (timer)
1455
- clearTimeout(timer);
1456
- resolve(reason);
1457
- },
1458
- token,
1459
- });
1460
- if (timeoutMs !== undefined) {
1461
- timer = setTimeout(() => {
1462
- // Only delete if this is still our resolver (not one from a later call)
1463
- const current = relay.exitResolvers.get(name);
1464
- if (current?.token === token) {
1465
- relay.exitResolvers.delete(name);
1466
- }
1467
- resolve('timeout');
1468
- }, timeoutMs);
1469
- }
1470
- });
1471
- },
1472
- waitForIdle(timeoutMs) {
1473
- return new Promise((resolve) => {
1474
- if (!relay.knownAgents.has(name)) {
1475
- resolve('exited');
1476
- return;
1477
- }
1478
- if (timeoutMs === 0) {
1479
- resolve('timeout');
1480
- return;
1481
- }
1482
- let timer;
1483
- const token = ++relay.idleResolverSeq;
1484
- relay.idleResolvers.set(name, {
1485
- resolve(reason) {
1486
- if (timer)
1487
- clearTimeout(timer);
1488
- resolve(reason);
1489
- },
1490
- token,
1491
- });
1492
- if (timeoutMs !== undefined) {
1493
- timer = setTimeout(() => {
1494
- const current = relay.idleResolvers.get(name);
1495
- if (current?.token === token) {
1496
- relay.idleResolvers.delete(name);
1497
- }
1498
- resolve('timeout');
1499
- }, timeoutMs);
1500
- }
1501
- });
1502
- },
1503
- waitForResult(timeoutMs) {
1504
- return relay.waitForAgentResult(name, timeoutMs);
1505
- },
1506
- async sendMessage(input) {
1507
- const client = await relay.ensureStarted();
1508
- let result;
1509
- try {
1510
- result = await client.sendMessage({
1511
- to: input.to,
1512
- text: input.text,
1513
- from: name,
1514
- threadId: input.threadId,
1515
- priority: input.priority,
1516
- data: input.data,
1517
- mode: input.mode,
1518
- });
1519
- }
1520
- catch (error) {
1521
- if (isUnsupportedOperation(error)) {
1522
- return buildUnsupportedOperationMessage(name, input);
1523
- }
1524
- throw error;
1525
- }
1526
- if (result?.event_id === 'unsupported_operation') {
1527
- return buildUnsupportedOperationMessage(name, input);
1528
- }
1529
- const eventId = result?.event_id ?? randomBytes(8).toString('hex');
1530
- const msg = {
1531
- eventId,
1532
- from: name,
1533
- to: input.to,
1534
- text: input.text,
1535
- threadId: input.threadId,
1536
- data: input.data,
1537
- mode: input.mode,
1538
- };
1539
- void relay.bus.emit('messageSent', msg);
1540
- return msg;
1541
- },
1542
- async subscribe(channelsToAdd) {
1543
- await relay.subscribe({ agent: name, channels: channelsToAdd });
1544
- },
1545
- async unsubscribe(channelsToRemove) {
1546
- await relay.unsubscribe({ agent: name, channels: channelsToRemove });
1547
- },
1548
- onOutput(callback, options) {
1549
- let listeners = relay.outputListeners.get(name);
1550
- if (!listeners) {
1551
- listeners = new Set();
1552
- relay.outputListeners.set(name, listeners);
1553
- }
1554
- const listener = {
1555
- callback,
1556
- mode: options?.mode ?? relay.inferOutputMode(callback),
1557
- stream: options?.stream,
1558
- };
1559
- listeners.add(listener);
1560
- return () => {
1561
- listeners.delete(listener);
1562
- if (listeners.size === 0) {
1563
- relay.outputListeners.delete(name);
1564
- }
1565
- };
1566
- },
1567
- _setChannels(nextChannels) {
1568
- agentChannels = [...nextChannels];
1569
- },
1570
- };
1571
- return agent;
1572
- }
1573
- createSpawner(cli, defaultName, runtime) {
1574
- return {
1575
- spawn: async (options) => {
1576
- const name = options?.name ?? defaultName;
1577
- const channels = options?.channels ?? ['general'];
1578
- const args = options?.args ?? [];
1579
- const task = options?.task;
1580
- if (runtime === 'pty') {
1581
- return this.spawnPty({
1582
- name,
1583
- cli,
1584
- args,
1585
- channels,
1586
- task,
1587
- model: options?.model,
1588
- cwd: options?.cwd,
1589
- idleThresholdSecs: options?.idleThresholdSecs,
1590
- agentToken: options?.agentToken,
1591
- skipRelayPrompt: options?.skipRelayPrompt,
1592
- result: options?.result,
1593
- onStart: options?.onStart,
1594
- onSuccess: options?.onSuccess,
1595
- onError: options?.onError,
1596
- });
1597
- }
1598
- const client = await this.ensureStarted();
1599
- const lifecycleContext = {
1600
- name,
1601
- cli,
1602
- channels,
1603
- task,
1604
- };
1605
- await this.invokeLifecycleHook(options?.onStart, lifecycleContext, `spawn("${name}") onStart`);
1606
- let result;
1607
- const resultContract = this.prepareAgentResultContract(options?.result);
1608
- if (resultContract) {
1609
- this.resultContracts.set(name, resultContract);
1610
- }
1611
- try {
1612
- result = await client.spawnProvider({
1613
- name,
1614
- provider: cli,
1615
- transport: 'headless',
1616
- args,
1617
- channels,
1618
- task,
1619
- model: options?.model,
1620
- cwd: options?.cwd,
1621
- idleThresholdSecs: options?.idleThresholdSecs,
1622
- agentToken: options?.agentToken,
1623
- skipRelayPrompt: options?.skipRelayPrompt,
1624
- agentResultSchema: resultContract?.jsonSchema,
1625
- });
1626
- }
1627
- catch (error) {
1628
- if (resultContract) {
1629
- this.resultContracts.delete(name);
1630
- }
1631
- await this.invokeLifecycleHook(options?.onError, {
1632
- ...lifecycleContext,
1633
- error,
1634
- }, `spawn("${name}") onError`);
1635
- throw error;
1636
- }
1637
- this.resetAgentLifecycleState(result.name);
1638
- if (result.name !== name && resultContract) {
1639
- this.resultContracts.delete(name);
1640
- this.resultContracts.set(result.name, resultContract);
1641
- }
1642
- const agent = this.makeAgent(result.name, result.runtime, channels);
1643
- this.knownAgents.set(agent.name, agent);
1644
- await this.invokeLifecycleHook(options?.onSuccess, {
1645
- ...lifecycleContext,
1646
- name: result.name,
1647
- runtime: result.runtime,
1648
- }, `spawn("${name}") onSuccess`);
1649
- return agent;
1650
- },
1651
- };
1652
- }
1653
- async invokeLifecycleHook(hook, context, label) {
1654
- if (!hook) {
1655
- return;
1656
- }
1657
- try {
1658
- await hook(context);
1659
- }
1660
- catch (error) {
1661
- console.warn(`[AgentRelay] ${label} hook threw`, error);
1662
- }
1663
- }
1664
- resetAgentLifecycleState(name) {
1665
- this.readyAgents.delete(name);
1666
- this.messageReadyAgents.delete(name);
1667
- this.exitedAgents.delete(name);
1668
- this.idleAgents.delete(name);
1669
- this.agentActivityStates.delete(name);
1670
- this.lastAgentResults.delete(name);
1671
- for (const waiter of this.takeResultResolvers(name)) {
1672
- waiter.reject(new Error(`Agent '${name}' lifecycle reset before structured result was submitted`));
1673
- }
1674
- }
1675
- normalizeReleaseOptions(reasonOrOptions) {
1676
- if (typeof reasonOrOptions === 'string' || reasonOrOptions === undefined) {
1677
- return { reason: reasonOrOptions };
1678
- }
1679
- return reasonOrOptions;
1680
- }
1681
- }
1682
- //# sourceMappingURL=relay.js.map