@relayflows/sdk 2.0.9 → 2.0.10

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 (475) hide show
  1. package/dist/adapters/base.d.ts +46 -0
  2. package/dist/adapters/base.d.ts.map +1 -0
  3. package/dist/adapters/base.js +15 -0
  4. package/dist/adapters/base.js.map +1 -0
  5. package/dist/adapters/claude.d.ts +5 -0
  6. package/dist/adapters/claude.d.ts.map +1 -0
  7. package/dist/adapters/claude.js +44 -0
  8. package/dist/adapters/claude.js.map +1 -0
  9. package/dist/adapters/codex.d.ts +5 -0
  10. package/dist/adapters/codex.d.ts.map +1 -0
  11. package/dist/adapters/codex.js +45 -0
  12. package/dist/adapters/codex.js.map +1 -0
  13. package/dist/adapters/index.d.ts +14 -0
  14. package/dist/adapters/index.d.ts.map +1 -0
  15. package/dist/adapters/index.js +29 -0
  16. package/dist/adapters/index.js.map +1 -0
  17. package/dist/adapters/wrapper.d.ts +12 -0
  18. package/dist/adapters/wrapper.d.ts.map +1 -0
  19. package/dist/adapters/wrapper.js +31 -0
  20. package/dist/adapters/wrapper.js.map +1 -0
  21. package/dist/agent-relay-transport.d.ts +84 -0
  22. package/dist/agent-relay-transport.d.ts.map +1 -0
  23. package/dist/agent-relay-transport.js +134 -0
  24. package/dist/agent-relay-transport.js.map +1 -0
  25. package/dist/authored-budget.d.ts +13 -0
  26. package/dist/authored-budget.d.ts.map +1 -0
  27. package/dist/authored-budget.js +78 -0
  28. package/dist/authored-budget.js.map +1 -0
  29. package/dist/authored-flow-error.d.ts +2 -21
  30. package/dist/authored-flow-error.d.ts.map +1 -1
  31. package/dist/authored-flow-error.js +1 -12
  32. package/dist/authored-flow-error.js.map +1 -1
  33. package/dist/authored-flow-executor.d.ts +13 -7
  34. package/dist/authored-flow-executor.d.ts.map +1 -1
  35. package/dist/authored-flow-executor.js +116 -235
  36. package/dist/authored-flow-executor.js.map +1 -1
  37. package/dist/authored-flow-loader.d.ts +10 -1
  38. package/dist/authored-flow-loader.d.ts.map +1 -1
  39. package/dist/authored-flow-loader.js +56 -3
  40. package/dist/authored-flow-loader.js.map +1 -1
  41. package/dist/authored-flow-operation.d.ts +9 -1
  42. package/dist/authored-flow-operation.d.ts.map +1 -1
  43. package/dist/authored-flow-operation.js +35 -4
  44. package/dist/authored-flow-operation.js.map +1 -1
  45. package/dist/authored-helper-effect.d.ts +12 -0
  46. package/dist/authored-helper-effect.d.ts.map +1 -0
  47. package/dist/authored-helper-effect.js +144 -0
  48. package/dist/authored-helper-effect.js.map +1 -0
  49. package/dist/authored-mcp.d.ts +17 -0
  50. package/dist/authored-mcp.d.ts.map +1 -0
  51. package/dist/authored-mcp.js +171 -0
  52. package/dist/authored-mcp.js.map +1 -0
  53. package/dist/authored-memory.d.ts +7 -0
  54. package/dist/authored-memory.d.ts.map +1 -0
  55. package/dist/authored-memory.js +60 -0
  56. package/dist/authored-memory.js.map +1 -0
  57. package/dist/authored-plugin-effect.d.ts +16 -0
  58. package/dist/authored-plugin-effect.d.ts.map +1 -0
  59. package/dist/authored-plugin-effect.js +163 -0
  60. package/dist/authored-plugin-effect.js.map +1 -0
  61. package/dist/authored-step-output.d.ts +23 -0
  62. package/dist/authored-step-output.d.ts.map +1 -0
  63. package/dist/authored-step-output.js +67 -0
  64. package/dist/authored-step-output.js.map +1 -0
  65. package/dist/authored-worker-step.d.ts +15 -0
  66. package/dist/authored-worker-step.d.ts.map +1 -0
  67. package/dist/authored-worker-step.js +136 -0
  68. package/dist/authored-worker-step.js.map +1 -0
  69. package/dist/budget-preflight.d.ts +5 -0
  70. package/dist/budget-preflight.d.ts.map +1 -0
  71. package/dist/budget-preflight.js +33 -0
  72. package/dist/budget-preflight.js.map +1 -0
  73. package/dist/budget.d.ts +14 -0
  74. package/dist/budget.d.ts.map +1 -0
  75. package/dist/budget.js +52 -0
  76. package/dist/budget.js.map +1 -0
  77. package/dist/bundle-transport.d.ts +18 -0
  78. package/dist/bundle-transport.d.ts.map +1 -0
  79. package/dist/bundle-transport.js +111 -0
  80. package/dist/bundle-transport.js.map +1 -0
  81. package/dist/bundle-typescript.d.ts +8 -0
  82. package/dist/bundle-typescript.d.ts.map +1 -0
  83. package/dist/bundle-typescript.js +108 -0
  84. package/dist/bundle-typescript.js.map +1 -0
  85. package/dist/bundle.d.ts +25 -0
  86. package/dist/bundle.d.ts.map +1 -0
  87. package/dist/bundle.js +199 -0
  88. package/dist/bundle.js.map +1 -0
  89. package/dist/child-stop.d.ts +59 -0
  90. package/dist/child-stop.d.ts.map +1 -0
  91. package/dist/child-stop.js +94 -0
  92. package/dist/child-stop.js.map +1 -0
  93. package/dist/cli/add.d.ts +6 -0
  94. package/dist/cli/add.d.ts.map +1 -0
  95. package/dist/cli/add.js +47 -0
  96. package/dist/cli/add.js.map +1 -0
  97. package/dist/cli/build.d.ts +13 -0
  98. package/dist/cli/build.d.ts.map +1 -0
  99. package/dist/cli/build.js +224 -0
  100. package/dist/cli/build.js.map +1 -0
  101. package/dist/cli/bundle-preflight.d.ts +5 -0
  102. package/dist/cli/bundle-preflight.d.ts.map +1 -0
  103. package/dist/cli/bundle-preflight.js +28 -0
  104. package/dist/cli/bundle-preflight.js.map +1 -0
  105. package/dist/cli/check-helper-body.d.ts +4 -0
  106. package/dist/cli/check-helper-body.d.ts.map +1 -0
  107. package/dist/cli/check-helper-body.js +15 -0
  108. package/dist/cli/check-helper-body.js.map +1 -0
  109. package/dist/cli/check-triggers.d.ts +14 -0
  110. package/dist/cli/check-triggers.d.ts.map +1 -0
  111. package/dist/cli/check-triggers.js +37 -0
  112. package/dist/cli/check-triggers.js.map +1 -0
  113. package/dist/cli/check-typescript.d.ts +20 -0
  114. package/dist/cli/check-typescript.d.ts.map +1 -0
  115. package/dist/cli/check-typescript.js +54 -0
  116. package/dist/cli/check-typescript.js.map +1 -0
  117. package/dist/cli/check.d.ts +36 -3
  118. package/dist/cli/check.d.ts.map +1 -1
  119. package/dist/cli/check.js +122 -11
  120. package/dist/cli/check.js.map +1 -1
  121. package/dist/cli/cloud-run.d.ts +8 -0
  122. package/dist/cli/cloud-run.d.ts.map +1 -0
  123. package/dist/cli/cloud-run.js +50 -0
  124. package/dist/cli/cloud-run.js.map +1 -0
  125. package/dist/cli/deploy.d.ts +9 -0
  126. package/dist/cli/deploy.d.ts.map +1 -0
  127. package/dist/cli/deploy.js +58 -0
  128. package/dist/cli/deploy.js.map +1 -0
  129. package/dist/cli/deterministic-failure.d.ts +5 -0
  130. package/dist/cli/deterministic-failure.d.ts.map +1 -0
  131. package/dist/cli/deterministic-failure.js +66 -0
  132. package/dist/cli/deterministic-failure.js.map +1 -0
  133. package/dist/cli/direct-run.d.ts.map +1 -1
  134. package/dist/cli/direct-run.js +83 -18
  135. package/dist/cli/direct-run.js.map +1 -1
  136. package/dist/cli/hn-monitor.d.ts.map +1 -1
  137. package/dist/cli/hn-monitor.js +2 -1
  138. package/dist/cli/hn-monitor.js.map +1 -1
  139. package/dist/cli/replay.d.ts +12 -0
  140. package/dist/cli/replay.d.ts.map +1 -0
  141. package/dist/cli/replay.js +82 -0
  142. package/dist/cli/replay.js.map +1 -0
  143. package/dist/cli/reuse.d.ts +8 -0
  144. package/dist/cli/reuse.d.ts.map +1 -0
  145. package/dist/cli/reuse.js +25 -0
  146. package/dist/cli/reuse.js.map +1 -0
  147. package/dist/cli/run-digest.d.ts +4 -0
  148. package/dist/cli/run-digest.d.ts.map +1 -0
  149. package/dist/cli/run-digest.js +24 -0
  150. package/dist/cli/run-digest.js.map +1 -0
  151. package/dist/cli/run.d.ts +16 -5
  152. package/dist/cli/run.d.ts.map +1 -1
  153. package/dist/cli/run.js +99 -17
  154. package/dist/cli/run.js.map +1 -1
  155. package/dist/cli/serve-webhook.d.ts +40 -0
  156. package/dist/cli/serve-webhook.d.ts.map +1 -0
  157. package/dist/cli/serve-webhook.js +233 -0
  158. package/dist/cli/serve-webhook.js.map +1 -0
  159. package/dist/cli/tick-runner.d.ts.map +1 -1
  160. package/dist/cli/tick-runner.js +2 -1
  161. package/dist/cli/tick-runner.js.map +1 -1
  162. package/dist/cli-adapter.d.ts +8 -14
  163. package/dist/cli-adapter.d.ts.map +1 -1
  164. package/dist/cli-adapter.js +19 -64
  165. package/dist/cli-adapter.js.map +1 -1
  166. package/dist/cli-watch.d.ts +13 -0
  167. package/dist/cli-watch.d.ts.map +1 -0
  168. package/dist/cli-watch.js +185 -0
  169. package/dist/cli-watch.js.map +1 -0
  170. package/dist/cli.d.ts +4 -0
  171. package/dist/cli.d.ts.map +1 -1
  172. package/dist/cli.js +387 -14
  173. package/dist/cli.js.map +1 -1
  174. package/dist/cloud-http.d.ts +22 -0
  175. package/dist/cloud-http.d.ts.map +1 -0
  176. package/dist/cloud-http.js +84 -0
  177. package/dist/cloud-http.js.map +1 -0
  178. package/dist/cloud-run.d.ts +38 -0
  179. package/dist/cloud-run.d.ts.map +1 -0
  180. package/dist/cloud-run.js +112 -0
  181. package/dist/cloud-run.js.map +1 -0
  182. package/dist/compile.d.ts +21 -3
  183. package/dist/compile.d.ts.map +1 -1
  184. package/dist/compile.js +97 -23
  185. package/dist/compile.js.map +1 -1
  186. package/dist/create-flow.d.ts +17 -0
  187. package/dist/create-flow.d.ts.map +1 -0
  188. package/dist/create-flow.js +72 -0
  189. package/dist/create-flow.js.map +1 -0
  190. package/dist/daemon-connection.d.ts +14 -0
  191. package/dist/daemon-connection.d.ts.map +1 -1
  192. package/dist/daemon-connection.js +33 -1
  193. package/dist/daemon-connection.js.map +1 -1
  194. package/dist/demo-hn-monitor.js +2 -1
  195. package/dist/demo-hn-monitor.js.map +1 -1
  196. package/dist/effect-channel.d.ts +30 -0
  197. package/dist/effect-channel.d.ts.map +1 -0
  198. package/dist/effect-channel.js +71 -0
  199. package/dist/effect-channel.js.map +1 -0
  200. package/dist/failure-kinds.d.ts +14 -3
  201. package/dist/failure-kinds.d.ts.map +1 -1
  202. package/dist/failure-kinds.js +27 -0
  203. package/dist/failure-kinds.js.map +1 -1
  204. package/dist/gate-contract.d.ts.map +1 -1
  205. package/dist/gate-contract.js +9 -0
  206. package/dist/gate-contract.js.map +1 -1
  207. package/dist/helper-preflight.d.ts +18 -0
  208. package/dist/helper-preflight.d.ts.map +1 -0
  209. package/dist/helper-preflight.js +32 -0
  210. package/dist/helper-preflight.js.map +1 -0
  211. package/dist/helper-storage.d.ts +5 -0
  212. package/dist/helper-storage.d.ts.map +1 -0
  213. package/dist/helper-storage.js +31 -0
  214. package/dist/helper-storage.js.map +1 -0
  215. package/dist/helper-writeback.d.ts +12 -0
  216. package/dist/helper-writeback.d.ts.map +1 -0
  217. package/dist/helper-writeback.js +95 -0
  218. package/dist/helper-writeback.js.map +1 -0
  219. package/dist/index.d.ts +10 -2
  220. package/dist/index.d.ts.map +1 -1
  221. package/dist/index.js +7 -1
  222. package/dist/index.js.map +1 -1
  223. package/dist/input-binding.d.ts +4 -0
  224. package/dist/input-binding.d.ts.map +1 -0
  225. package/dist/input-binding.js +78 -0
  226. package/dist/input-binding.js.map +1 -0
  227. package/dist/journal-client.d.ts +12 -4
  228. package/dist/journal-client.d.ts.map +1 -1
  229. package/dist/journal-client.js +17 -6
  230. package/dist/journal-client.js.map +1 -1
  231. package/dist/journal-offset.d.ts +3 -0
  232. package/dist/journal-offset.d.ts.map +1 -0
  233. package/dist/journal-offset.js +69 -0
  234. package/dist/journal-offset.js.map +1 -0
  235. package/dist/journal-reader.d.ts +30 -0
  236. package/dist/journal-reader.d.ts.map +1 -0
  237. package/dist/journal-reader.js +156 -0
  238. package/dist/journal-reader.js.map +1 -0
  239. package/dist/json-schema.d.ts +2 -0
  240. package/dist/json-schema.d.ts.map +1 -1
  241. package/dist/json-schema.js +38 -22
  242. package/dist/json-schema.js.map +1 -1
  243. package/dist/llm-worker.d.ts +16 -0
  244. package/dist/llm-worker.d.ts.map +1 -0
  245. package/dist/llm-worker.js +79 -0
  246. package/dist/llm-worker.js.map +1 -0
  247. package/dist/local-agent.d.ts +8 -0
  248. package/dist/local-agent.d.ts.map +1 -0
  249. package/dist/local-agent.js +25 -0
  250. package/dist/local-agent.js.map +1 -0
  251. package/dist/mcp-client.d.ts +15 -0
  252. package/dist/mcp-client.d.ts.map +1 -0
  253. package/dist/mcp-client.js +104 -0
  254. package/dist/mcp-client.js.map +1 -0
  255. package/dist/mcp-config.d.ts +4 -0
  256. package/dist/mcp-config.d.ts.map +1 -0
  257. package/dist/mcp-config.js +61 -0
  258. package/dist/mcp-config.js.map +1 -0
  259. package/dist/mcp-stdio.d.ts +24 -0
  260. package/dist/mcp-stdio.d.ts.map +1 -0
  261. package/dist/mcp-stdio.js +89 -0
  262. package/dist/mcp-stdio.js.map +1 -0
  263. package/dist/model-pricing.d.ts +22 -0
  264. package/dist/model-pricing.d.ts.map +1 -0
  265. package/dist/model-pricing.js +30 -0
  266. package/dist/model-pricing.js.map +1 -0
  267. package/dist/mount-registry.d.ts +9 -0
  268. package/dist/mount-registry.d.ts.map +1 -0
  269. package/dist/mount-registry.js +47 -0
  270. package/dist/mount-registry.js.map +1 -0
  271. package/dist/named-gate-lowering.d.ts +9 -0
  272. package/dist/named-gate-lowering.d.ts.map +1 -0
  273. package/dist/named-gate-lowering.js +152 -0
  274. package/dist/named-gate-lowering.js.map +1 -0
  275. package/dist/named-gates.d.ts +10 -0
  276. package/dist/named-gates.d.ts.map +1 -0
  277. package/dist/named-gates.js +69 -0
  278. package/dist/named-gates.js.map +1 -0
  279. package/dist/observer-link.d.ts +129 -0
  280. package/dist/observer-link.d.ts.map +1 -0
  281. package/dist/observer-link.js +274 -0
  282. package/dist/observer-link.js.map +1 -0
  283. package/dist/plugin-loader.d.ts +13 -0
  284. package/dist/plugin-loader.d.ts.map +1 -0
  285. package/dist/plugin-loader.js +110 -0
  286. package/dist/plugin-loader.js.map +1 -0
  287. package/dist/plugin-manifest.d.ts +27 -0
  288. package/dist/plugin-manifest.d.ts.map +1 -0
  289. package/dist/plugin-manifest.js +89 -0
  290. package/dist/plugin-manifest.js.map +1 -0
  291. package/dist/preflight.d.ts +26 -2
  292. package/dist/preflight.d.ts.map +1 -1
  293. package/dist/preflight.js +175 -1
  294. package/dist/preflight.js.map +1 -1
  295. package/dist/progress.d.ts +14 -0
  296. package/dist/progress.d.ts.map +1 -0
  297. package/dist/progress.js +39 -0
  298. package/dist/progress.js.map +1 -0
  299. package/dist/protocol.d.ts +11 -0
  300. package/dist/protocol.d.ts.map +1 -1
  301. package/dist/pty-sidechannel.d.ts +14 -0
  302. package/dist/pty-sidechannel.d.ts.map +1 -0
  303. package/dist/pty-sidechannel.js +103 -0
  304. package/dist/pty-sidechannel.js.map +1 -0
  305. package/dist/scope-compiler.d.ts +52 -0
  306. package/dist/scope-compiler.d.ts.map +1 -0
  307. package/dist/scope-compiler.js +62 -0
  308. package/dist/scope-compiler.js.map +1 -0
  309. package/dist/slack-preflight.d.ts +6 -0
  310. package/dist/slack-preflight.d.ts.map +1 -0
  311. package/dist/slack-preflight.js +28 -0
  312. package/dist/slack-preflight.js.map +1 -0
  313. package/dist/slack-writeback.d.ts +40 -0
  314. package/dist/slack-writeback.d.ts.map +1 -0
  315. package/dist/slack-writeback.js +60 -0
  316. package/dist/slack-writeback.js.map +1 -0
  317. package/dist/spec.d.ts +134 -4
  318. package/dist/spec.d.ts.map +1 -1
  319. package/dist/spec.js.map +1 -1
  320. package/dist/step-dependencies.d.ts.map +1 -1
  321. package/dist/step-dependencies.js +2 -1
  322. package/dist/step-dependencies.js.map +1 -1
  323. package/dist/step-fields.d.ts +4 -4
  324. package/dist/step-fields.d.ts.map +1 -1
  325. package/dist/step-fields.js +5 -2
  326. package/dist/step-fields.js.map +1 -1
  327. package/dist/trigger-executor.d.ts +7 -0
  328. package/dist/trigger-executor.d.ts.map +1 -0
  329. package/dist/trigger-executor.js +35 -0
  330. package/dist/trigger-executor.js.map +1 -0
  331. package/dist/validate.d.ts.map +1 -1
  332. package/dist/validate.js +53 -6
  333. package/dist/validate.js.map +1 -1
  334. package/dist/webhook-rate-limit.d.ts +29 -0
  335. package/dist/webhook-rate-limit.d.ts.map +1 -0
  336. package/dist/webhook-rate-limit.js +38 -0
  337. package/dist/webhook-rate-limit.js.map +1 -0
  338. package/dist/webhook-signature.d.ts +22 -0
  339. package/dist/webhook-signature.d.ts.map +1 -0
  340. package/dist/webhook-signature.js +53 -0
  341. package/dist/webhook-signature.js.map +1 -0
  342. package/dist/worker-cli.d.ts +13 -1
  343. package/dist/worker-cli.d.ts.map +1 -1
  344. package/dist/worker-cli.js +133 -12
  345. package/dist/worker-cli.js.map +1 -1
  346. package/dist/worker-input.d.ts +4 -0
  347. package/dist/worker-input.d.ts.map +1 -0
  348. package/dist/worker-input.js +14 -0
  349. package/dist/worker-input.js.map +1 -0
  350. package/dist/worker-lease.d.ts +5 -0
  351. package/dist/worker-lease.d.ts.map +1 -0
  352. package/dist/worker-lease.js +80 -0
  353. package/dist/worker-lease.js.map +1 -0
  354. package/dist/worker-spend.d.ts +19 -0
  355. package/dist/worker-spend.d.ts.map +1 -0
  356. package/dist/worker-spend.js +22 -0
  357. package/dist/worker-spend.js.map +1 -0
  358. package/dist/worker-usage.d.ts +7 -0
  359. package/dist/worker-usage.d.ts.map +1 -0
  360. package/dist/worker-usage.js +54 -0
  361. package/dist/worker-usage.js.map +1 -0
  362. package/dist/worker.d.ts +2 -0
  363. package/dist/worker.d.ts.map +1 -1
  364. package/dist/worker.js +22 -8
  365. package/dist/worker.js.map +1 -1
  366. package/dist/wrapper-session.d.ts +1 -1
  367. package/dist/wrapper-session.d.ts.map +1 -1
  368. package/dist/wrapper-session.js +56 -19
  369. package/dist/wrapper-session.js.map +1 -1
  370. package/dist/yaml-helper-effect.d.ts +8 -0
  371. package/dist/yaml-helper-effect.d.ts.map +1 -0
  372. package/dist/yaml-helper-effect.js +79 -0
  373. package/dist/yaml-helper-effect.js.map +1 -0
  374. package/dist/yaml-helpers.d.ts +18 -0
  375. package/dist/yaml-helpers.d.ts.map +1 -0
  376. package/dist/yaml-helpers.js +116 -0
  377. package/dist/yaml-helpers.js.map +1 -0
  378. package/package.json +19 -2
  379. package/src/adapters/base.ts +53 -0
  380. package/src/adapters/claude.ts +55 -0
  381. package/src/adapters/codex.ts +56 -0
  382. package/src/adapters/index.ts +36 -0
  383. package/src/adapters/wrapper.ts +42 -0
  384. package/src/agent-relay-transport.ts +187 -0
  385. package/src/authored-budget.ts +69 -0
  386. package/src/authored-flow-error.ts +10 -10
  387. package/src/authored-flow-executor.ts +171 -347
  388. package/src/authored-flow-loader.ts +60 -3
  389. package/src/authored-flow-operation.ts +38 -5
  390. package/src/authored-helper-effect.ts +143 -0
  391. package/src/authored-mcp.ts +166 -0
  392. package/src/authored-memory.ts +55 -0
  393. package/src/authored-plugin-effect.ts +152 -0
  394. package/src/authored-step-output.ts +107 -0
  395. package/src/authored-worker-step.ts +181 -0
  396. package/src/budget-preflight.ts +31 -0
  397. package/src/budget.ts +49 -0
  398. package/src/bundle-transport.ts +79 -0
  399. package/src/bundle-typescript.ts +98 -0
  400. package/src/bundle.ts +182 -0
  401. package/src/child-stop.ts +138 -0
  402. package/src/cli/add.ts +45 -0
  403. package/src/cli/build.ts +214 -0
  404. package/src/cli/bundle-preflight.ts +28 -0
  405. package/src/cli/check-helper-body.ts +14 -0
  406. package/src/cli/check-triggers.ts +41 -0
  407. package/src/cli/check-typescript.ts +63 -0
  408. package/src/cli/check.ts +132 -14
  409. package/src/cli/cloud-run.ts +47 -0
  410. package/src/cli/deploy.ts +52 -0
  411. package/src/cli/deterministic-failure.ts +69 -0
  412. package/src/cli/direct-run.ts +79 -18
  413. package/src/cli/hn-monitor.ts +2 -1
  414. package/src/cli/replay.ts +81 -0
  415. package/src/cli/reuse.ts +23 -0
  416. package/src/cli/run-digest.ts +24 -0
  417. package/src/cli/run.ts +104 -21
  418. package/src/cli/serve-webhook.ts +246 -0
  419. package/src/cli/tick-runner.ts +2 -1
  420. package/src/cli-adapter.ts +31 -74
  421. package/src/cli-watch.ts +174 -0
  422. package/src/cli.ts +396 -17
  423. package/src/cloud-http.ts +100 -0
  424. package/src/cloud-run.ts +137 -0
  425. package/src/compile.ts +102 -23
  426. package/src/create-flow.ts +82 -0
  427. package/src/daemon-connection.ts +32 -1
  428. package/src/demo-hn-monitor.ts +2 -1
  429. package/src/effect-channel.ts +97 -0
  430. package/src/failure-kinds.ts +38 -0
  431. package/src/gate-contract.ts +7 -0
  432. package/src/helper-preflight.ts +34 -0
  433. package/src/helper-storage.ts +23 -0
  434. package/src/helper-writeback.ts +83 -0
  435. package/src/index.ts +26 -0
  436. package/src/input-binding.ts +76 -0
  437. package/src/journal-client.ts +20 -7
  438. package/src/journal-offset.ts +60 -0
  439. package/src/journal-reader.ts +165 -0
  440. package/src/json-schema.ts +34 -18
  441. package/src/llm-worker.ts +82 -0
  442. package/src/local-agent.ts +30 -0
  443. package/src/mcp-client.ts +97 -0
  444. package/src/mcp-config.ts +42 -0
  445. package/src/mcp-stdio.ts +84 -0
  446. package/src/model-pricing.ts +32 -0
  447. package/src/mount-registry.ts +44 -0
  448. package/src/named-gate-lowering.ts +147 -0
  449. package/src/named-gates.ts +76 -0
  450. package/src/observer-link.ts +368 -0
  451. package/src/plugin-loader.ts +88 -0
  452. package/src/plugin-manifest.ts +76 -0
  453. package/src/preflight.ts +178 -4
  454. package/src/progress.ts +51 -0
  455. package/src/protocol.ts +12 -0
  456. package/src/pty-sidechannel.ts +92 -0
  457. package/src/scope-compiler.ts +105 -0
  458. package/src/slack-preflight.ts +25 -0
  459. package/src/slack-writeback.ts +63 -0
  460. package/src/spec.ts +112 -4
  461. package/src/step-dependencies.ts +3 -1
  462. package/src/step-fields.ts +5 -2
  463. package/src/trigger-executor.ts +34 -0
  464. package/src/validate.ts +47 -6
  465. package/src/webhook-rate-limit.ts +69 -0
  466. package/src/webhook-signature.ts +74 -0
  467. package/src/worker-cli.ts +156 -11
  468. package/src/worker-input.ts +15 -0
  469. package/src/worker-lease.ts +85 -0
  470. package/src/worker-spend.ts +23 -0
  471. package/src/worker-usage.ts +48 -0
  472. package/src/worker.ts +27 -9
  473. package/src/wrapper-session.ts +50 -15
  474. package/src/yaml-helper-effect.ts +78 -0
  475. package/src/yaml-helpers.ts +131 -0
@@ -0,0 +1,10 @@
1
+ import type { NamedDataGate, VerificationSpec } from './spec.js';
2
+ export declare const NAMED_GATE_FAILURE_KINDS: readonly ["unknown_gate_kind", "gate_pattern_invalid", "gate_command_missing", "gate_bound_invalid"];
3
+ export type NamedGateFailureKind = typeof NAMED_GATE_FAILURE_KINDS[number];
4
+ export declare const NAMED_GATE_KEYS: Record<NamedDataGate['type'], readonly string[]>;
5
+ export declare function isNamedGate(gate: VerificationSpec | undefined): gate is NamedDataGate;
6
+ export declare function regexFlags(flags: string): number;
7
+ /** Called only on snapshotted data, including by the public validator. */
8
+ export declare function namedGateErrors(gate: Record<string, unknown>, input: unknown, at: string): string[];
9
+ export declare function namedGateFailure(errors: readonly string[]): NamedGateFailureKind | undefined;
10
+ //# sourceMappingURL=named-gates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"named-gates.d.ts","sourceRoot":"","sources":["../src/named-gates.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAEjE,eAAO,MAAM,wBAAwB,sGAE3B,CAAC;AACX,MAAM,MAAM,oBAAoB,GAAG,OAAO,wBAAwB,CAAC,MAAM,CAAC,CAAC;AAE3E,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAK5E,CAAC;AAEF,wBAAgB,WAAW,CAAC,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,IAAI,IAAI,aAAa,CAErF;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CA6CnG;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,oBAAoB,GAAG,SAAS,CAE5F"}
@@ -0,0 +1,69 @@
1
+ import { RE2JS } from 're2js';
2
+ export const NAMED_GATE_FAILURE_KINDS = [
3
+ 'unknown_gate_kind', 'gate_pattern_invalid', 'gate_command_missing', 'gate_bound_invalid',
4
+ ];
5
+ export const NAMED_GATE_KEYS = {
6
+ references_input: ['type', 'input_key', 'in_output_at'],
7
+ subprocess_gate: ['type', 'command', 'from_output'],
8
+ word_count_bounds: ['type', 'min', 'max'],
9
+ regex_match: ['type', 'pattern', 'in_output_at', 'flags'],
10
+ };
11
+ export function isNamedGate(gate) {
12
+ return gate !== undefined && Object.hasOwn(NAMED_GATE_KEYS, gate.type);
13
+ }
14
+ export function regexFlags(flags) {
15
+ return (flags.includes('i') ? RE2JS.CASE_INSENSITIVE : 0)
16
+ | (flags.includes('m') ? RE2JS.MULTILINE : 0)
17
+ | (flags.includes('s') ? RE2JS.DOTALL : 0);
18
+ }
19
+ /** Called only on snapshotted data, including by the public validator. */
20
+ export function namedGateErrors(gate, input, at) {
21
+ const errors = [];
22
+ for (const key of ['in_output_at', 'from_output']) {
23
+ const path = gate[key];
24
+ if (path !== undefined && (!Array.isArray(path) || !path.every(segment => typeof segment === 'string' || (Number.isSafeInteger(segment) && segment >= 0)))) {
25
+ errors.push(`${at}.${key}: expected an array of object keys or non-negative integer indices`);
26
+ }
27
+ }
28
+ switch (gate.type) {
29
+ case 'references_input':
30
+ if (typeof gate.input_key !== 'string' || !gate.input_key.trim()
31
+ || input === null || typeof input !== 'object' || !Object.hasOwn(input, gate.input_key)) {
32
+ errors.push(`${at}.input_key: must name a declared input binding`);
33
+ }
34
+ break;
35
+ case 'subprocess_gate':
36
+ if (typeof gate.command !== 'string' || !gate.command.trim() || gate.command.includes('\0')) {
37
+ errors.push(`${at}.command: gate_command_missing: expected a non-empty shell command`);
38
+ }
39
+ break;
40
+ case 'word_count_bounds': {
41
+ const { min, max } = gate;
42
+ if ([min, max].some(n => n !== undefined && (!Number.isSafeInteger(n) || n < 0))
43
+ || (typeof min === 'number' && typeof max === 'number' && min > max)) {
44
+ errors.push(`${at}: gate_bound_invalid: min and max must be non-negative safe integers with min <= max`);
45
+ }
46
+ break;
47
+ }
48
+ case 'regex_match':
49
+ try {
50
+ if (typeof gate.pattern !== 'string' || gate.pattern.length > 8192) {
51
+ throw new Error('pattern must be a string of at most 8192 characters');
52
+ }
53
+ const flags = gate.flags ?? '';
54
+ if (typeof flags !== 'string' || !/^(?!.*(.).*\1)[ims]*$/.test(flags)) {
55
+ throw new Error('flags must be a non-repeating subset of i, m, s');
56
+ }
57
+ RE2JS.compile(gate.pattern, regexFlags(flags));
58
+ }
59
+ catch (error) {
60
+ errors.push(`${at}: gate_pattern_invalid: ${error instanceof Error ? error.message : 'invalid RE2 pattern'}`);
61
+ }
62
+ break;
63
+ }
64
+ return errors;
65
+ }
66
+ export function namedGateFailure(errors) {
67
+ return NAMED_GATE_FAILURE_KINDS.find(kind => errors.some(error => error.includes(`${kind}:`)));
68
+ }
69
+ //# sourceMappingURL=named-gates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"named-gates.js","sourceRoot":"","sources":["../src/named-gates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAG9B,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,mBAAmB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,oBAAoB;CACjF,CAAC;AAGX,MAAM,CAAC,MAAM,eAAe,GAAqD;IAC/E,gBAAgB,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,CAAC;IACvD,eAAe,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,CAAC;IACnD,iBAAiB,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC;IACzC,WAAW,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC;CAC1D,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,IAAkC;IAC5D,OAAO,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;UACrD,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;UAC3C,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,eAAe,CAAC,IAA6B,EAAE,KAAc,EAAE,EAAU;IACvF,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CACvE,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,IAAK,OAAkB,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/F,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,GAAG,oEAAoE,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IACD,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,kBAAkB;YACrB,IAAI,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;mBAC3D,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1F,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,gDAAgD,CAAC,CAAC;YACrE,CAAC;YACD,MAAM;QACR,KAAK,iBAAiB;YACpB,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5F,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,oEAAoE,CAAC,CAAC;YACzF,CAAC;YACD,MAAM;QACR,KAAK,mBAAmB,CAAC,CAAC,CAAC;YACzB,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;YAC1B,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAK,CAAY,GAAG,CAAC,CAAC,CAAC;mBACvF,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC;gBACvE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,sFAAsF,CAAC,CAAC;YAC3G,CAAC;YACD,MAAM;QACR,CAAC;QACD,KAAK,aAAa;YAChB,IAAI,CAAC;gBACH,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;oBACnE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;gBACzE,CAAC;gBACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBACtE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;gBACrE,CAAC;gBACD,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;YACjD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,2BAA2B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,EAAE,CAAC,CAAC;YAChH,CAAC;YACD,MAAM;IACV,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAyB;IACxD,OAAO,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;AACjG,CAAC"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Observer-link support for `flows run`: mint a scoped read-only observer token
3
+ * from a Relaycast workspace admin key, then print
4
+ * `Observer: <url>?key=<ot_live_...>` on stdout so an operator can drop into the
5
+ * Relaycast observer dashboard with the live-stream credential pre-filled.
6
+ *
7
+ * The workspace admin key (`rk_live_*`) is refused by the realtime endpoint —
8
+ * only an `ot_live_*` observer token with `stream:read` may open the workspace
9
+ * stream. So we do the same thing the Relaycast observer dashboard does when a
10
+ * workspace admin logs in with their admin key: mint a fresh, uniquely-named,
11
+ * scoped, short-lived observer token on their behalf and hand *that* to the
12
+ * URL. The workspace admin key never leaves the operator's machine.
13
+ *
14
+ * Everything here is best-effort. A missing workspace key means "no observer
15
+ * link, silently" — this is a parity feature relaying v1's convenience, not a
16
+ * requirement of a local run. A mint failure emits a labeled diagnostic to
17
+ * stderr and continues; a run must never fail because the observer link failed.
18
+ */
19
+ export interface ObserverLinkEnv {
20
+ workspaceKey?: string;
21
+ /** Base URL for the mint API (`POST /v1/observer-tokens`). */
22
+ baseUrl?: string;
23
+ /** Base URL for the observer dashboard the emitted link points at. */
24
+ dashboardUrl?: string;
25
+ /** `FLOWS_NO_OBSERVER=1` suppresses the mint even when a key is present. */
26
+ suppressed: boolean;
27
+ }
28
+ /**
29
+ * Path to the `agent-relay` local workspace-key store. Structure:
30
+ * `{ active: string, workspaces: { [name]: { key: string } } }`. Written
31
+ * by `agent-relay workspace set_key` / `agent-relay workspace join`; the
32
+ * canonical file the `@agent-relay/cloud` package reads via
33
+ * `resolveActiveWorkspaceKey`. Verified against
34
+ * `packages/cloud/src/workspace-store.ts` in `AgentWorkforce/relay`.
35
+ *
36
+ * Respects `AGENT_RELAY_HOME` so a caller can point at a different store
37
+ * for tests without touching the real one. Falls back to
38
+ * `~/.agentworkforce/relay/workspaces.json` -- the same default that
39
+ * package uses.
40
+ */
41
+ export declare function agentRelayWorkspaceStorePath(env?: NodeJS.ProcessEnv): string;
42
+ /**
43
+ * Read the active workspace key from the `agent-relay cloud login` /
44
+ * `agent-relay workspace set_key` store. Returns `undefined` on every
45
+ * failure mode -- file absent, unreadable, malformed JSON, no active
46
+ * workspace, active workspace has no key, key is empty -- so the caller
47
+ * can silently fall through to "no observer link" the same way an unset
48
+ * `RELAYCAST_WORKSPACE_KEY` does.
49
+ *
50
+ * A file-shape mismatch is INTENTIONALLY not a hard error: `agent-relay`
51
+ * may extend this file in future without warning, and refusing a flow
52
+ * because a fallback credential store looked odd would be strictly worse
53
+ * than falling back to the explicit env var (which is the primary path).
54
+ */
55
+ export declare function readAgentRelayWorkspaceKey(env?: NodeJS.ProcessEnv, readFile?: (path: string) => string): string | undefined;
56
+ /**
57
+ * Options controlling `resolveObserverLinkEnv`'s fallback behavior. The
58
+ * `readWorkspaceKey` seam is what the tests inject to simulate presence,
59
+ * absence, and malformed shapes of the on-disk store without touching the
60
+ * real home directory.
61
+ */
62
+ export interface ResolveObserverLinkEnvOptions {
63
+ readWorkspaceKey?: (env: NodeJS.ProcessEnv) => string | undefined;
64
+ }
65
+ /**
66
+ * Env-first observer link resolution with an `agent-relay` cloud fallback.
67
+ *
68
+ * Priority (from the task spec, explicit beats implicit):
69
+ * 1. `RELAYCAST_WORKSPACE_KEY` if set and non-empty.
70
+ * 2. Active workspace key from `~/.agentworkforce/relay/workspaces.json`
71
+ * (populated by `agent-relay cloud login` + `agent-relay workspace
72
+ * set_key`), when readable.
73
+ * 3. Nothing -- silent skip, same as an unset primary env var.
74
+ *
75
+ * `FLOWS_NO_OBSERVER=1` still suppresses regardless of source.
76
+ */
77
+ export declare function resolveObserverLinkEnv(env?: NodeJS.ProcessEnv, options?: ResolveObserverLinkEnvOptions): ObserverLinkEnv;
78
+ /**
79
+ * Read the observer-link config from the environment. Both trims and
80
+ * emptiness-checks the workspace key so a `RELAYCAST_WORKSPACE_KEY=` with no
81
+ * value reads the same as unset (no observer link, silently).
82
+ */
83
+ export declare function readObserverLinkEnv(env?: NodeJS.ProcessEnv): ObserverLinkEnv;
84
+ /**
85
+ * Minimal `fetch` shape we depend on. Kept structural so tests can inject a
86
+ * mock without pulling in a fetch replacement library.
87
+ */
88
+ export type ObserverFetch = (url: string, init: {
89
+ method: string;
90
+ headers: Record<string, string>;
91
+ body: string;
92
+ signal?: AbortSignal;
93
+ }) => Promise<{
94
+ ok: boolean;
95
+ status: number;
96
+ json: () => Promise<unknown>;
97
+ }>;
98
+ export interface MintObserverOptions {
99
+ workspaceKey: string;
100
+ /** Base URL of the mint API (default `https://cast.agentrelay.com`). */
101
+ baseUrl?: string;
102
+ /** Base URL of the observer dashboard the returned URL points at
103
+ * (default `https://agentrelay.com`). Separate axis from `baseUrl` — the
104
+ * mint API lives on a different subdomain from the dashboard. */
105
+ dashboardUrl?: string;
106
+ fetch?: ObserverFetch;
107
+ now?: () => number;
108
+ /** Called for the token's uniquely-suffixed name; injectable for tests. */
109
+ uuid?: () => string;
110
+ signal?: AbortSignal;
111
+ timeoutMs?: number;
112
+ }
113
+ export interface MintObserverOutcome {
114
+ observerUrl?: string;
115
+ /**
116
+ * A short diagnostic to log when mint failed. `undefined` on success or on
117
+ * "no observer link is possible" (missing key/suppressed) so the caller can
118
+ * distinguish silent-skip from "warn about the miss".
119
+ */
120
+ warning?: string;
121
+ }
122
+ /**
123
+ * Mint an `ot_live_*` observer token via `POST /v1/observer-tokens` and return
124
+ * the observer dashboard URL that pre-fills it. Any failure — 4xx/5xx from the
125
+ * engine, malformed response, network error, timeout — returns a `warning`
126
+ * string and no URL. The caller must not fail the run on `warning`.
127
+ */
128
+ export declare function mintObserverUrl(options: MintObserverOptions): Promise<MintObserverOutcome>;
129
+ //# sourceMappingURL=observer-link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer-link.d.ts","sourceRoot":"","sources":["../src/observer-link.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AA6CH,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,4BAA4B,CAC1C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAGR;AAaD;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,QAAQ,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAwB,GACnD,MAAM,GAAG,SAAS,CAwBpB;AAMD;;;;;GAKG;AACH,MAAM,WAAW,6BAA6B;IAC5C,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,KAAK,MAAM,GAAG,SAAS,CAAC;CACnE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,OAAO,GAAE,6BAAkC,GAC1C,eAAe,CAYjB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,eAAe,CAiBjB;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,CAC1B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IACJ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,KACE,OAAO,CAAC;IACX,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9B,CAAC,CAAC;AAEH,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;qEAEiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,mBAAmB,CAAC,CA0E9B"}
@@ -0,0 +1,274 @@
1
+ /**
2
+ * Observer-link support for `flows run`: mint a scoped read-only observer token
3
+ * from a Relaycast workspace admin key, then print
4
+ * `Observer: <url>?key=<ot_live_...>` on stdout so an operator can drop into the
5
+ * Relaycast observer dashboard with the live-stream credential pre-filled.
6
+ *
7
+ * The workspace admin key (`rk_live_*`) is refused by the realtime endpoint —
8
+ * only an `ot_live_*` observer token with `stream:read` may open the workspace
9
+ * stream. So we do the same thing the Relaycast observer dashboard does when a
10
+ * workspace admin logs in with their admin key: mint a fresh, uniquely-named,
11
+ * scoped, short-lived observer token on their behalf and hand *that* to the
12
+ * URL. The workspace admin key never leaves the operator's machine.
13
+ *
14
+ * Everything here is best-effort. A missing workspace key means "no observer
15
+ * link, silently" — this is a parity feature relaying v1's convenience, not a
16
+ * requirement of a local run. A mint failure emits a labeled diagnostic to
17
+ * stderr and continues; a run must never fail because the observer link failed.
18
+ */
19
+ import { readFileSync } from 'node:fs';
20
+ import { homedir } from 'node:os';
21
+ import { join } from 'node:path';
22
+ /** Scopes the minted token carries. Mirrors the observer dashboard's set. */
23
+ const OBSERVER_SCOPES = [
24
+ 'stream:read',
25
+ 'messages:read',
26
+ 'threads:read',
27
+ 'dms:read',
28
+ 'channels:read',
29
+ 'search:read',
30
+ 'agents:read',
31
+ 'nodes:read',
32
+ 'deliveries:read',
33
+ 'activity:read',
34
+ 'files:read',
35
+ 'reactions:read',
36
+ ];
37
+ /** Token lifetime for a `flows run` session. 24h is well past the longest run. */
38
+ const OBSERVER_TOKEN_TTL_MS = 60 * 60 * 24 * 1000;
39
+ /**
40
+ * Default hosts for the two axes of the observer link. They are DIFFERENT
41
+ * subdomains and must not be conflated (empirically verified 2026-09-10):
42
+ *
43
+ * - Mint API: `POST cast.agentrelay.com/v1/observer-tokens`. `agentrelay.com`
44
+ * returns 404 for this path. Overridable via `RELAYCAST_API_URL`.
45
+ * - Observer dashboard: `agentrelay.com/observer?key=<ot_live_...>`.
46
+ * `cast.agentrelay.com/observer` returns 404. Overridable via
47
+ * `RELAYCAST_DASHBOARD_URL`.
48
+ *
49
+ * An earlier fix collapsed both to `cast.agentrelay.com` and closed #278 for
50
+ * the mint half only; a demo verification then landed on the 404 dashboard
51
+ * URL. Keep the two constants distinct.
52
+ */
53
+ const DEFAULT_RELAYCAST_MINT_URL = 'https://cast.agentrelay.com';
54
+ const DEFAULT_RELAYCAST_DASHBOARD_URL = 'https://agentrelay.com';
55
+ /** Bounded so a stalled Relaycast API cannot delay the RUN summary. */
56
+ const MINT_TIMEOUT_MS = 5_000;
57
+ /**
58
+ * Path to the `agent-relay` local workspace-key store. Structure:
59
+ * `{ active: string, workspaces: { [name]: { key: string } } }`. Written
60
+ * by `agent-relay workspace set_key` / `agent-relay workspace join`; the
61
+ * canonical file the `@agent-relay/cloud` package reads via
62
+ * `resolveActiveWorkspaceKey`. Verified against
63
+ * `packages/cloud/src/workspace-store.ts` in `AgentWorkforce/relay`.
64
+ *
65
+ * Respects `AGENT_RELAY_HOME` so a caller can point at a different store
66
+ * for tests without touching the real one. Falls back to
67
+ * `~/.agentworkforce/relay/workspaces.json` -- the same default that
68
+ * package uses.
69
+ */
70
+ export function agentRelayWorkspaceStorePath(env = process.env) {
71
+ const dir = env['AGENT_RELAY_HOME'] ?? join(homedir(), '.agentworkforce/relay');
72
+ return join(dir, 'workspaces.json');
73
+ }
74
+ /**
75
+ * Read the active workspace key from the `agent-relay cloud login` /
76
+ * `agent-relay workspace set_key` store. Returns `undefined` on every
77
+ * failure mode -- file absent, unreadable, malformed JSON, no active
78
+ * workspace, active workspace has no key, key is empty -- so the caller
79
+ * can silently fall through to "no observer link" the same way an unset
80
+ * `RELAYCAST_WORKSPACE_KEY` does.
81
+ *
82
+ * A file-shape mismatch is INTENTIONALLY not a hard error: `agent-relay`
83
+ * may extend this file in future without warning, and refusing a flow
84
+ * because a fallback credential store looked odd would be strictly worse
85
+ * than falling back to the explicit env var (which is the primary path).
86
+ */
87
+ export function readAgentRelayWorkspaceKey(env = process.env, readFile = defaultReadFile) {
88
+ let raw;
89
+ try {
90
+ raw = readFile(agentRelayWorkspaceStorePath(env));
91
+ }
92
+ catch {
93
+ return undefined;
94
+ }
95
+ let parsed;
96
+ try {
97
+ parsed = JSON.parse(raw);
98
+ }
99
+ catch {
100
+ return undefined;
101
+ }
102
+ if (typeof parsed !== 'object' || parsed === null)
103
+ return undefined;
104
+ const activeName = parsed.active;
105
+ if (typeof activeName !== 'string' || activeName === '')
106
+ return undefined;
107
+ const workspaces = parsed.workspaces;
108
+ if (typeof workspaces !== 'object' || workspaces === null)
109
+ return undefined;
110
+ const entry = workspaces[activeName];
111
+ if (typeof entry !== 'object' || entry === null)
112
+ return undefined;
113
+ const key = entry.key;
114
+ if (typeof key !== 'string')
115
+ return undefined;
116
+ const trimmed = key.trim();
117
+ return trimmed === '' ? undefined : trimmed;
118
+ }
119
+ function defaultReadFile(filePath) {
120
+ return readFileSync(filePath, 'utf8');
121
+ }
122
+ /**
123
+ * Env-first observer link resolution with an `agent-relay` cloud fallback.
124
+ *
125
+ * Priority (from the task spec, explicit beats implicit):
126
+ * 1. `RELAYCAST_WORKSPACE_KEY` if set and non-empty.
127
+ * 2. Active workspace key from `~/.agentworkforce/relay/workspaces.json`
128
+ * (populated by `agent-relay cloud login` + `agent-relay workspace
129
+ * set_key`), when readable.
130
+ * 3. Nothing -- silent skip, same as an unset primary env var.
131
+ *
132
+ * `FLOWS_NO_OBSERVER=1` still suppresses regardless of source.
133
+ */
134
+ export function resolveObserverLinkEnv(env = process.env, options = {}) {
135
+ const primary = readObserverLinkEnv(env);
136
+ if (primary.workspaceKey !== undefined || primary.suppressed) {
137
+ return primary;
138
+ }
139
+ const readWorkspaceKey = options.readWorkspaceKey ?? readAgentRelayWorkspaceKey;
140
+ const fallback = readWorkspaceKey(env);
141
+ if (fallback === undefined)
142
+ return primary;
143
+ return {
144
+ ...primary,
145
+ workspaceKey: fallback,
146
+ };
147
+ }
148
+ /**
149
+ * Read the observer-link config from the environment. Both trims and
150
+ * emptiness-checks the workspace key so a `RELAYCAST_WORKSPACE_KEY=` with no
151
+ * value reads the same as unset (no observer link, silently).
152
+ */
153
+ export function readObserverLinkEnv(env = process.env) {
154
+ const rawKey = env['RELAYCAST_WORKSPACE_KEY'];
155
+ const workspaceKey = typeof rawKey === 'string' ? rawKey.trim() : '';
156
+ const rawApi = env['RELAYCAST_API_URL'];
157
+ const baseUrl = typeof rawApi === 'string' && rawApi.trim() !== ''
158
+ ? rawApi.trim()
159
+ : undefined;
160
+ const rawDashboard = env['RELAYCAST_DASHBOARD_URL'];
161
+ const dashboardUrl = typeof rawDashboard === 'string' && rawDashboard.trim() !== ''
162
+ ? rawDashboard.trim()
163
+ : undefined;
164
+ return {
165
+ ...(workspaceKey !== '' ? { workspaceKey } : {}),
166
+ ...(baseUrl !== undefined ? { baseUrl } : {}),
167
+ ...(dashboardUrl !== undefined ? { dashboardUrl } : {}),
168
+ suppressed: env['FLOWS_NO_OBSERVER'] === '1',
169
+ };
170
+ }
171
+ /**
172
+ * Mint an `ot_live_*` observer token via `POST /v1/observer-tokens` and return
173
+ * the observer dashboard URL that pre-fills it. Any failure — 4xx/5xx from the
174
+ * engine, malformed response, network error, timeout — returns a `warning`
175
+ * string and no URL. The caller must not fail the run on `warning`.
176
+ */
177
+ export async function mintObserverUrl(options) {
178
+ const doFetch = options.fetch ?? (globalThis.fetch);
179
+ if (typeof doFetch !== 'function') {
180
+ return { warning: 'no fetch implementation available' };
181
+ }
182
+ const rawApi = options.baseUrl ?? DEFAULT_RELAYCAST_MINT_URL;
183
+ const rawDashboard = options.dashboardUrl ?? DEFAULT_RELAYCAST_DASHBOARD_URL;
184
+ let mintUrl;
185
+ let observerBase;
186
+ try {
187
+ mintUrl = new URL('/v1/observer-tokens', rawApi);
188
+ }
189
+ catch {
190
+ return { warning: `invalid RELAYCAST_API_URL "${rawApi}"` };
191
+ }
192
+ try {
193
+ observerBase = new URL('/observer', rawDashboard);
194
+ }
195
+ catch {
196
+ return { warning: `invalid RELAYCAST_DASHBOARD_URL "${rawDashboard}"` };
197
+ }
198
+ const uuid = (options.uuid ?? defaultUuid)();
199
+ const now = options.now ?? (() => Date.now());
200
+ const timeoutMs = options.timeoutMs ?? MINT_TIMEOUT_MS;
201
+ const deadline = AbortSignal.timeout(timeoutMs);
202
+ const signal = options.signal
203
+ ? AbortSignal.any([options.signal, deadline])
204
+ : deadline;
205
+ const payload = {
206
+ name: `flows-run-${uuid}`,
207
+ description: 'Auto-minted by `flows run` for the observer dashboard link.',
208
+ scopes: OBSERVER_SCOPES,
209
+ filters: { include_dms: true },
210
+ expires_at: new Date(now() + OBSERVER_TOKEN_TTL_MS).toISOString(),
211
+ };
212
+ let response;
213
+ try {
214
+ response = await doFetch(mintUrl.toString(), {
215
+ method: 'POST',
216
+ headers: {
217
+ Authorization: `Bearer ${options.workspaceKey}`,
218
+ 'Content-Type': 'application/json',
219
+ },
220
+ body: JSON.stringify(payload),
221
+ signal,
222
+ });
223
+ }
224
+ catch (error) {
225
+ return { warning: `network error: ${errorMessage(error)}` };
226
+ }
227
+ if (!response.ok) {
228
+ return { warning: `mint API returned HTTP ${response.status}` };
229
+ }
230
+ let body;
231
+ try {
232
+ body = await response.json();
233
+ }
234
+ catch (error) {
235
+ return { warning: `malformed response: ${errorMessage(error)}` };
236
+ }
237
+ const token = pickToken(body);
238
+ if (token === undefined) {
239
+ return { warning: 'mint API response missing ot_live_ token' };
240
+ }
241
+ // `URL.searchParams.set` percent-encodes any exotic characters the token
242
+ // could carry. It also collapses the leading `/observer` path correctly.
243
+ observerBase.searchParams.set('key', token);
244
+ return { observerUrl: observerBase.toString() };
245
+ }
246
+ /**
247
+ * Pick `data.token` from a `POST /v1/observer-tokens` response, refusing any
248
+ * shape that is not a plain `ot_live_*` string. Anything else is treated as
249
+ * "response too weird to trust" and produces no URL.
250
+ */
251
+ function pickToken(body) {
252
+ if (typeof body !== 'object' || body === null)
253
+ return undefined;
254
+ const data = body['data'];
255
+ if (typeof data !== 'object' || data === null)
256
+ return undefined;
257
+ const token = data['token'];
258
+ if (typeof token !== 'string' || !token.startsWith('ot_live_'))
259
+ return undefined;
260
+ return token;
261
+ }
262
+ function defaultUuid() {
263
+ // `crypto.randomUUID()` is available on every Node 20+ target the SDK
264
+ // supports. The token name is not a security surface — it only has to be
265
+ // unique per (workspace, name) — so the fallback is a plain timestamp.
266
+ const c = globalThis.crypto;
267
+ return c?.randomUUID?.() ?? String(Date.now());
268
+ }
269
+ function errorMessage(error) {
270
+ if (error instanceof Error)
271
+ return error.message;
272
+ return 'unknown error';
273
+ }
274
+ //# sourceMappingURL=observer-link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer-link.js","sourceRoot":"","sources":["../src/observer-link.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Step } from '@relayflows/surface';
2
+ import { type PluginManifest, type PluginVerb } from './plugin-manifest.js';
3
+ export interface LoadedPlugin {
4
+ readonly directory: string;
5
+ readonly manifest: PluginManifest;
6
+ }
7
+ export declare function findPluginProject(start: string): string | undefined;
8
+ export declare function readPlugin(directory: string, packageName: string): LoadedPlugin;
9
+ export declare function probePlugin(plugin: LoadedPlugin, env?: NodeJS.ProcessEnv): Promise<void>;
10
+ export declare function loadPlugins(start: string): Promise<readonly LoadedPlugin[]>;
11
+ export declare function pluginHelpers(plugins: readonly LoadedPlugin[], invoke: (plugin: LoadedPlugin, verb: PluginVerb, args: unknown) => Step<unknown>): Record<string, unknown>;
12
+ export declare function invokePlugin(plugin: LoadedPlugin, verb: PluginVerb, args: unknown, idempotencyKey: string): Promise<unknown>;
13
+ //# sourceMappingURL=plugin-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../src/plugin-loader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAEhD,OAAO,EAAiF,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAE3J,MAAM,WAAW,YAAY;IAAG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;CAAE;AAC/F,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQnE;AACD,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,YAAY,CAS/E;AACD,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAW3G;AACD,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC,CA2BjF;AACD,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAczK;AACD,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAIlI"}
@@ -0,0 +1,110 @@
1
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
2
+ import { dirname, join, resolve } from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+ import { Ajv } from 'ajv';
5
+ import { snapshotJsonValue } from './json-value.js';
6
+ import { assertSupportedPlugin, PluginError, pluginPackageName, validatePluginManifest } from './plugin-manifest.js';
7
+ export function findPluginProject(start) {
8
+ let current = resolve(start);
9
+ for (;;) {
10
+ if (existsSync(join(current, 'flows.json')))
11
+ return current;
12
+ const parent = dirname(current);
13
+ if (parent === current)
14
+ return undefined;
15
+ current = parent;
16
+ }
17
+ }
18
+ export function readPlugin(directory, packageName) {
19
+ const path = join(directory, 'flows-plugin.json');
20
+ if (!existsSync(path))
21
+ throw new PluginError('plugin_manifest_missing', `${packageName} has no flows-plugin.json.`);
22
+ let input;
23
+ try {
24
+ input = JSON.parse(readFileSync(path, 'utf8'));
25
+ }
26
+ catch {
27
+ throw new PluginError('plugin_manifest_invalid', `${packageName} manifest is unreadable or invalid JSON.`);
28
+ }
29
+ const manifest = validatePluginManifest(input, packageName);
30
+ assertSupportedPlugin(manifest);
31
+ return Object.freeze({ directory, manifest });
32
+ }
33
+ export async function probePlugin(plugin, env = process.env) {
34
+ for (const credential of plugin.manifest.preflight.credentials) {
35
+ if (!env[credential]?.trim())
36
+ throw new PluginError('plugin_credential_missing', `${plugin.manifest.name} requires ${credential}.`);
37
+ }
38
+ for (const server of plugin.manifest.preflight.servers) {
39
+ try {
40
+ const response = await fetch(server, { method: 'HEAD', signal: AbortSignal.timeout(5000) });
41
+ await response.body?.cancel();
42
+ if (!response.ok)
43
+ throw new Error('unsuccessful response');
44
+ }
45
+ catch {
46
+ throw new PluginError('plugin_server_unreachable', `${plugin.manifest.name} cannot reach ${server}.`);
47
+ }
48
+ }
49
+ }
50
+ export async function loadPlugins(start) {
51
+ const root = findPluginProject(start);
52
+ if (root === undefined)
53
+ return Object.freeze([]);
54
+ let config;
55
+ try {
56
+ config = JSON.parse(readFileSync(join(root, 'flows.json'), 'utf8'));
57
+ }
58
+ catch {
59
+ throw new PluginError('plugin_manifest_invalid', 'Invalid flows.json.');
60
+ }
61
+ if (config === null || typeof config !== 'object' || (config.plugins !== undefined && (!Array.isArray(config.plugins) || !config.plugins.every(p => typeof p === 'string')))) {
62
+ throw new PluginError('plugin_manifest_invalid', 'flows.json plugins must be package names.');
63
+ }
64
+ const scope = join(root, 'node_modules/@flows');
65
+ const names = new Set(config.plugins?.map(pluginPackageName));
66
+ if (existsSync(scope))
67
+ for (const name of readdirSync(scope).sort()) {
68
+ if (name.startsWith('helper-') && !names.has(`@flows/${name}`)) {
69
+ throw new PluginError('plugin_unlisted', `@flows/${name} is installed but not declared in flows.json plugins. Run flows add ${name}.`);
70
+ }
71
+ }
72
+ const plugins = [...names].sort().map(name => readPlugin(join(root, 'node_modules', name), name));
73
+ const namespaces = new Set();
74
+ for (const plugin of plugins) {
75
+ for (const namespace of new Set(plugin.manifest.verbs.map(v => v.namespace))) {
76
+ if (namespaces.has(namespace))
77
+ throw new PluginError('plugin_manifest_invalid', `Duplicate plugin namespace ${namespace}.`);
78
+ namespaces.add(namespace);
79
+ }
80
+ await probePlugin(plugin);
81
+ if (!existsSync(join(plugin.directory, 'src/index.js')))
82
+ throw new PluginError('plugin_manifest_invalid', `${plugin.manifest.name} requires src/index.js.`);
83
+ }
84
+ return Object.freeze(plugins);
85
+ }
86
+ export function pluginHelpers(plugins, invoke) {
87
+ const helpers = Object.create(null);
88
+ const ajv = new Ajv({ strict: false });
89
+ for (const plugin of plugins)
90
+ for (const verb of plugin.manifest.verbs) {
91
+ const validate = ajv.compile(verb.args);
92
+ const namespace = helpers[verb.namespace] ??= Object.create(null);
93
+ namespace[verb.method] = args => {
94
+ const snapshot = snapshotJsonValue(args, `f.${verb.namespace}.${verb.method} arguments`);
95
+ if (!validate(snapshot))
96
+ throw new PluginError('plugin_manifest_invalid', `Invalid arguments for ${verb.namespace}.${verb.method}: ${ajv.errorsText(validate.errors)}`);
97
+ return invoke(plugin, verb, snapshot);
98
+ };
99
+ }
100
+ for (const helper of Object.values(helpers))
101
+ Object.freeze(helper);
102
+ return Object.freeze(helpers);
103
+ }
104
+ export async function invokePlugin(plugin, verb, args, idempotencyKey) {
105
+ const module = await import(pathToFileURL(join(plugin.directory, 'src/index.js')).href);
106
+ if (typeof module.execute !== 'function')
107
+ throw new Error('plugin_runtime_invalid: expected execute export');
108
+ return snapshotJsonValue(await module.execute(verb.namespace, verb.method, args, Object.freeze({ idempotencyKey })), 'plugin output');
109
+ }
110
+ //# sourceMappingURL=plugin-loader.js.map