@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
@@ -1,22 +1,34 @@
1
+ import { pluginHelpers } from './plugin-loader.js';
2
+ import { runPluginEffect } from './authored-plugin-effect.js';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { dirname } from 'node:path';
5
+ import { runHelperEffect } from './authored-helper-effect.js';
6
+ import { checkSlackHelpers } from './slack-preflight.js';
7
+ import { snapshotJsonValue } from './json-value.js';
8
+ import type { SlackCall } from './slack-writeback.js';
9
+ import { checkMcpHeader, McpPreflightError } from './cli/check-typescript.js';
10
+ import { buildMcpProxy, runMcpEffect } from './authored-mcp.js';
11
+ import { AuthoredBudget } from './authored-budget.js';
12
+ import { assertMemoryReachable, authoredMemory, scriptMemoryScope } from './authored-memory.js';
13
+ import { authoredDeterministicRunner, authoredWorkerRunner } from './authored-worker-step.js';
14
+ import { isSurfaceRunCompletionReason } from './authored-step-output.js';
1
15
  import {
2
- COMPLETION_REASONS,
3
- RUN_COMPLETION_REASONS,
4
- type AgentOptions,
5
16
  type AgentResult,
17
+ type LlmOptions,
6
18
  type CloudHelper,
7
19
  type CompletionReason as SurfaceCompletionReason,
8
20
  type Ctx,
21
+ type FlowCompletionReason,
9
22
  type RunCompletionReason as SurfaceRunCompletionReason,
10
23
  type Step,
11
24
  } from '@relayflows/surface';
12
- import type { FlowHandle } from '@relayflows/surface/runtime';
25
+ import { createHelpers, helperProviders, type HelperCall, type FlowHandle } from '@relayflows/surface/runtime';
13
26
  import { join } from 'node:path';
14
- import { compileSpec, toKernelSpec } from './compile.js';
27
+ import { observeStep, type ProgressEvent } from './progress.js';
28
+ import { parseStepTimeout } from './compile.js';
15
29
  import { getAuthoredFlowDefinition } from './authored-flow.js';
16
30
  import type { GetFlowDefinition } from './authored-flow-loader.js';
17
- import { checkAuthoredFlow } from './cli/check.js';
18
- import { classifyOutcome, type RunLifecycleOptions } from './cli/run.js';
19
- import type { PreflightDiagnostic } from './preflight.js';
31
+ import type { RunLifecycleOptions } from './cli/run.js';
20
32
  import {
21
33
  AuthoredFlowExecutionError,
22
34
  type AuthoredFlowExecutionErrorCode,
@@ -31,9 +43,7 @@ import { JournalClient } from './journal-client.js';
31
43
  import type {
32
44
  CompletionReason as ProtocolCompletionReason,
33
45
  RunCompletionReason as ProtocolRunCompletionReason,
34
- RunOutcome,
35
46
  } from './protocol.js';
36
- import { SPEC_SCHEMA_VERSION, type FlowSpec } from './spec.js';
37
47
 
38
48
  type Assert<T extends true> = T;
39
49
  type Equal<A, B> = [A] extends [B]
@@ -46,8 +56,8 @@ type RunCompletionVocabularyMatchesProtocol = Assert<
46
56
  Equal<SurfaceRunCompletionReason, ProtocolRunCompletionReason>
47
57
  >;
48
58
  type DoneCompletionReason = Parameters<Ctx['done']>[0];
49
- type DoneAcceptsOnlyRunCompletionReasons = Assert<
50
- DoneCompletionReason extends SurfaceRunCompletionReason ? true : false
59
+ type DoneAcceptsOnlyFlowCompletionReasons = Assert<
60
+ Equal<DoneCompletionReason, FlowCompletionReason>
51
61
  >;
52
62
  type EveryRunCompletionReasonIsAcceptedByDone = Assert<
53
63
  SurfaceRunCompletionReason extends DoneCompletionReason ? true : false
@@ -55,15 +65,6 @@ type EveryRunCompletionReasonIsAcceptedByDone = Assert<
55
65
 
56
66
  export { AuthoredFlowExecutionError, type AuthoredFlowExecutionErrorCode };
57
67
 
58
- /**
59
- * Matches the `"path/glob: readonly"` / `"path/glob: readwrite"` shorthand
60
- * shown in docs/SURFACE.md and the examples — the only shape a workspace
61
- * string could plausibly declare a permission in. No parser anywhere in this
62
- * package turns that annotation into a real restriction, so `lowerAgent`
63
- * refuses rather than silently accepting and ignoring it.
64
- */
65
- const WORKSPACE_PERMISSION_ANNOTATION = /:\s*(readonly|readwrite)\s*$/i;
66
-
67
68
  export interface AuthoredFlowJournalStep {
68
69
  readonly id: string;
69
70
  readonly runId: string;
@@ -72,12 +73,12 @@ export interface AuthoredFlowJournalStep {
72
73
 
73
74
  export interface AuthoredFlowExecutionResult {
74
75
  readonly name: string;
75
- readonly completionReason: ProtocolRunCompletionReason;
76
+ readonly completionReason: FlowCompletionReason;
76
77
  readonly journalSteps: readonly AuthoredFlowJournalStep[];
77
78
  }
78
79
 
79
- type ExecutionResultUsesRunCompletionReason = Assert<
80
- Equal<AuthoredFlowExecutionResult['completionReason'], ProtocolRunCompletionReason>
80
+ type ExecutionResultUsesFlowCompletionReason = Assert<
81
+ Equal<AuthoredFlowExecutionResult['completionReason'], FlowCompletionReason>
81
82
  >;
82
83
  type JournalStepUsesStepCompletionReason = Assert<
83
84
  Equal<AuthoredFlowJournalStep['completionReason'], ProtocolCompletionReason>
@@ -88,9 +89,9 @@ type JournalStepUsesStepCompletionReason = Assert<
88
89
  *
89
90
  * This is deliberately not exported by the SDK package: without a durable
90
91
  * authored root, it is not a resumable public runner. The seam is narrow: an
91
- * empty-header flow may await plain `f.run(...)` steps and must finish with
92
- * `f.done("success")`. Every run and
93
- * the terminal marker is a compiled deterministic spec submitted through
92
+ * flow with an optional budget may await `f.run`, `f.llm`, and `f.agent` steps and must
93
+ * finish with `f.done("success")` or `f.done("needs_human")`. Each step and the terminal marker is
94
+ * a compiled spec submitted through
94
95
  * `JournalClient`; values are read back from `step.completed` journal entries.
95
96
  * Unsupported headers, verbs, gates, or completion lowering fail closed.
96
97
  */
@@ -102,6 +103,8 @@ export interface ExecuteAuthoredFlowOptions {
102
103
  * `getDefinition` instead; see authored-flow-loader.ts's comment on why.
103
104
  */
104
105
  readonly getDefinition?: GetFlowDefinition;
106
+ /** Helper receipt and mock-writeback storage; CLI passes its daemon data directory. */
107
+ readonly dataDir?: string;
105
108
  /**
106
109
  * The flow file's own path — passed straight to `checkAuthoredFlow`
107
110
  * (cli/check.ts) so `f.agent` resolves a CLI the same way a declarative
@@ -117,6 +120,8 @@ export interface ExecuteAuthoredFlowOptions {
117
120
  /** Passed straight through to classifyOutcome (cli/run.ts) for f.agent's wait. */
118
121
  readonly signal?: RunLifecycleOptions['signal'];
119
122
  readonly onWait?: RunLifecycleOptions['onWait'];
123
+ readonly onProgress?: (event: ProgressEvent) => void;
124
+ readonly localAgentStream?: string;
120
125
  }
121
126
 
122
127
  export async function executeAuthoredFlow<Input = undefined>(
@@ -126,218 +131,159 @@ export async function executeAuthoredFlow<Input = undefined>(
126
131
  options: ExecuteAuthoredFlowOptions = {},
127
132
  ): Promise<AuthoredFlowExecutionResult> {
128
133
  const getDefinition = options.getDefinition ?? getAuthoredFlowDefinition;
134
+ const localAgentStream = options.localAgentStream;
135
+ const onProgress = options.onProgress;
129
136
  const flowPath = options.flowPath ?? join(process.cwd(), 'flow.ts');
130
- // Named separately from `options` because `lowerAgent` below has its own,
131
- // differently-typed `options: AgentOptions` parameter that shadows this one.
132
137
  const waitOptions: RunLifecycleOptions = {
133
138
  ...(options.signal !== undefined ? { signal: options.signal } : {}),
134
139
  ...(options.onWait !== undefined ? { onWait: options.onWait } : {}),
135
140
  };
136
141
  const definition = getDefinition<Input>(handle);
137
- // `agents` is the one header field this executor lowers today (into
138
- // `FlowSpec.agents`, resolved by `lowerAgent` below exactly like the
139
- // declarative dialect's `agents:` map). Every other header field remains
140
- // unimplemented and refuses closed rather than being silently ignored.
141
- const unsupportedHeaderFields = Object.keys(definition.header)
142
- .filter((field) => field !== 'agents');
143
- if (unsupportedHeaderFields.length > 0) {
142
+ const headerFields = Object.keys(definition.header).filter(key => key !== 'tools' && key !== 'budget' && key !== 'memory');
143
+ if (definition.header.tools && Object.keys(definition.header.tools).some(key => !['mcp', ...helperProviders.map(p => p.namespace)].includes(key))) headerFields.push('tools');
144
+ if (definition.header.tools?.relayfile !== undefined) headerFields.push('tools.relayfile');
145
+ const helperPreflight = checkSlackHelpers(definition);
146
+ if (!helperPreflight.ok) {
147
+ const diagnostic = helperPreflight.diagnostics[0]!;
148
+ throw new AuthoredFlowExecutionError(diagnostic.kind as AuthoredFlowExecutionErrorCode, diagnostic.message);
149
+ }
150
+ if (headerFields.length > 0) {
144
151
  throw new AuthoredFlowExecutionError(
145
152
  'unsupported_header',
146
- `flow "${definition.name}" uses unsupported header fields: ${unsupportedHeaderFields.join(', ')}`,
153
+ `flow "${definition.name}" uses unsupported header fields: ${headerFields.join(', ')}`,
147
154
  );
148
155
  }
149
- // Every declared named agent's model must be checked BEFORE the body runs,
150
- // not lazily the first time a matching `f.agent` call happens to be
151
- // reached: the declarative dialect's own preflight (preflight.ts's
152
- // unknownModelDiagnostics) checks every entry in `flow.agents`, used or
153
- // not, before any step submits — an unregistered model on a header entry
154
- // the body never selects must refuse the same way, not silently pass. This
155
- // is header data available before the body starts (no need to predict
156
- // arbitrary TS control flow): a placeholder no-op deterministic step
157
- // carries the declared `agents` map through the same real preflight
158
- // `lowerAgent` uses, without probing any CLI (deterministic steps are
159
- // never CLI-resolved) and without journaling anything on success.
160
- if (definition.header.agents !== undefined && Object.keys(definition.header.agents).length > 0) {
161
- const { report } = checkAuthoredFlow({
162
- version: SPEC_SCHEMA_VERSION,
163
- name: `${definition.name}/declared-agents`,
164
- agents: { ...definition.header.agents },
165
- steps: [{ id: 'declared-agents', type: 'deterministic', command: ':' }],
166
- }, flowPath);
167
- if (!report.ok) {
168
- const refusal = report.diagnostics.find(
169
- (diagnostic): diagnostic is PreflightDiagnostic & { severity: 'refusal' } =>
170
- diagnostic.severity === 'refusal',
171
- );
172
- throw new AuthoredFlowExecutionError(
173
- 'agent_cli_unresolved',
174
- refusal?.message
175
- ?? `flow "${definition.name}" declares an invalid named agent`,
176
- undefined,
177
- undefined,
178
- refusal?.kind ?? 'invalid_spec',
179
- );
180
- }
156
+
157
+ const checkedMcp = await checkMcpHeader(definition, flowPath);
158
+ if (!checkedMcp.report.ok) throw new McpPreflightError(checkedMcp.report);
159
+
160
+ const budget = new AuthoredBudget(definition.header.budget);
161
+ if (definition.header.memory?.agent === true) {
162
+ throw new AuthoredFlowExecutionError('unsupported_header', 'memory.agent requires the follow-up identity-scoped agent memory adapter');
163
+ }
164
+ // Direct member use is checked before any body effects; aliases are checked
165
+ // by the helper itself, without executing the body during discovery.
166
+ if (definition.header.memory !== undefined || /\.memory\b/.test(String(definition.body))) {
167
+ await assertMemoryReachable();
181
168
  }
182
169
 
183
170
  const journalSteps: AuthoredFlowJournalStep[] = [];
184
171
  const authoredSteps: AuthoredFlowOperation<unknown>[] = [];
185
172
  const lifecycle = new AuthoredFlowLifecycle();
186
173
  let nextStep = 1;
187
- let requestedCompletion: SurfaceRunCompletionReason | undefined;
174
+ let requestedCompletion: FlowCompletionReason | undefined;
188
175
 
189
- const lowerDeterministic = async (
190
- id: string,
191
- command: string,
192
- ): Promise<string> => {
193
- const spec = toKernelSpec(compileSpec({
194
- version: SPEC_SCHEMA_VERSION,
195
- name: `${definition.name}/${id}`,
196
- steps: [{ id, type: 'deterministic', command }],
197
- }));
198
- const outcome = await journal.runStart(spec);
199
- return readSuccessfulOutput(journal, outcome, id, journalSteps);
200
- };
176
+ const lowerDeterministic = authoredDeterministicRunner(definition.name, journal, journalSteps, budget);
201
177
 
202
- // `name` (the first f.agent argument, e.g. "fixer") selects a NAMED
203
- // declaration from the flow header's `agents` map, exactly like the
204
- // declarative dialect's `agent: fixer` step field selects from a top-level
205
- // `agents:` map but ONLY when `name` actually matches a declared entry.
206
- // `compile.ts`'s `resolveNamedAgent` throws `unknown named agent` for any
207
- // `step.agent` that doesn't resolve, so setting it unconditionally would
208
- // break every call that uses `name` purely for step-id readability (the
209
- // common case, and every pre-existing `f.agent` caller). When there's no
210
- // match, `agent` stays unset and CLI selection falls through to the
211
- // project's flows.json default below, same as a bare `type: agent` YAML
212
- // step with no explicit `cli`/`agent`. `options.cli`/`options.model`
213
- // always pass through as step-level overrides, which win over any named
214
- // declaration independent of whether `name` matched one.
215
- const lowerAgent = async (
216
- id: string,
217
- name: string,
218
- options: AgentOptions,
219
- ): Promise<AgentResult> => {
220
- if (options.workspace !== undefined && WORKSPACE_PERMISSION_ANNOTATION.test(options.workspace)) {
221
- throw new AuthoredFlowExecutionError(
222
- 'unsupported_workspace_permission',
223
- `flow "${definition.name}" step "${id}": workspace "${options.workspace}" declares a `
224
- + 'permission annotation ("...: readonly" / "...: readwrite"), but nothing enforces it — '
225
- + 'no parser anywhere in this package turns that annotation into a real restriction '
226
- + '(kernel/DAEMON-LIFECYCLE.md\'s permission model is untouched by f.agent). '
227
- + 'Silently accepting and ignoring it would let a flow believe a restriction is in effect '
228
- + "when it is not. Declare a bare surface name (no trailing \": readonly\"/\": readwrite\") "
229
- + 'if you do not need enforcement, or use the declarative spec\'s `permissions` field, which is real.',
230
- );
231
- }
232
- const namedAgents = definition.header.agents;
233
- const matchesNamedAgent = namedAgents !== undefined && Object.hasOwn(namedAgents, name);
234
- const authoring: FlowSpec = {
235
- version: SPEC_SCHEMA_VERSION,
236
- name: `${definition.name}/${id}`,
237
- ...(namedAgents === undefined ? {} : { agents: { ...namedAgents } }),
238
- steps: [{
239
- id,
240
- type: 'agent',
241
- instruction: options.task,
242
- ...(matchesNamedAgent ? { agent: name } : {}),
243
- ...(options.cli === undefined ? {} : { cli: options.cli }),
244
- ...(options.model === undefined ? {} : { model: options.model }),
245
- ...(options.workspace === undefined ? {} : {
246
- surfaces: { workspace: [{ surface: options.workspace }] },
247
- }),
248
- }],
249
- };
250
- // The kernel never resolves a `cli` on its own — every declarative
251
- // `flows run`/`flows check` binds it first via this exact function
252
- // (cli/check.ts), searching for the nearest flows.json from `flowPath`
253
- // and real-probing auth/model readiness. An authored agent step gets
254
- // nothing for free just because it was declared in TS instead of YAML.
255
- const { report, flow: resolved } = checkAuthoredFlow(authoring, flowPath);
256
- if (!report.ok || resolved === undefined) {
257
- const refusal = report.diagnostics.find(
258
- (diagnostic): diagnostic is PreflightDiagnostic & { severity: 'refusal' } =>
259
- diagnostic.severity === 'refusal',
260
- );
261
- throw new AuthoredFlowExecutionError(
262
- 'agent_cli_unresolved',
263
- refusal?.message
264
- ?? `flow "${definition.name}" step "${id}": no CLI could be resolved for f.agent `
265
- + `(searched for flows.json from "${flowPath}")`,
266
- undefined,
267
- undefined,
268
- refusal?.kind ?? 'invalid_spec',
269
- );
270
- }
271
- const spec = toKernelSpec(resolved);
272
- const outcome = await journal.runStart(spec);
273
- // Reuse the declarative CLI's own wait/classification (cli/run.ts) rather
274
- // than a hand-rolled poll: `step.completed` and the run's own terminal
275
- // state are appended as two SEPARATE actions (kernel/relayflowd-core/src/machine.rs
276
- // completion_actions vs complete_run_actions), so a naive read right
277
- // after runStart can race a real, valid completion — and a genuinely
278
- // long-running agent has no reason to be bounded by anything other than
279
- // its own worker's lease, which classifyOutcome already follows
280
- // (renewing as the lease renews, per docs/SURFACE.md §5's WAITING
281
- // [worker_lease] contract), never an unrelated fixed deadline.
282
- const execution = await classifyOutcome(journal, 'run', outcome, report, '', waitOptions);
283
- if (execution.exitCode === 3) {
284
- const parked = execution.report.parkedStep;
285
- throw new AuthoredFlowExecutionError(
286
- 'agent_parked',
287
- execution.report.diagnostics.at(-1)?.message
288
- ?? `flow "${definition.name}" step "${id}" parked`
289
- + (parked !== undefined ? ` (${parked.type})` : '')
290
- + ': no worker is attached to run it.',
291
- undefined,
292
- outcome.run_id,
293
- );
294
- }
295
- if (execution.exitCode !== 0) {
296
- const reason = execution.report.completionReason;
297
- throw new AuthoredFlowExecutionError(
298
- 'step_failed',
299
- execution.report.diagnostics.at(-1)?.message
300
- ?? `flow "${definition.name}" step "${id}" did not complete successfully `
301
- + `(status: ${execution.report.status ?? 'unknown'})`,
302
- isSurfaceCompletionReason(reason) ? reason : undefined,
303
- outcome.run_id,
304
- );
305
- }
306
- return readSuccessfulAgentOutput(journal, outcome.run_id, id, journalSteps);
307
- };
178
+ const worker = authoredWorkerRunner(definition, journal, flowPath, journalSteps, waitOptions, localAgentStream, budget, definition.header.budget);
179
+
180
+ function llmOperation(strings: TemplateStringsArray, ...values: unknown[]): Step<string>;
181
+ function llmOperation(prompt: string, options: LlmOptions): Step<unknown>;
182
+ function llmOperation(prompt: string | TemplateStringsArray, ...values: unknown[]): Step<unknown> {
183
+ assertOperationAllowed('llm', definition.name, requestedCompletion);
184
+ const id = `llm-${nextStep++}`;
185
+ // Hoist the operation reference so the start closure can read the
186
+ // caller's `.gate(config)` at spec-build time. AuthoredFlowOperation
187
+ // begins after construction returns, so `llmOp` is defined by then.
188
+ let llmOp!: AuthoredFlowOperation<unknown>;
189
+ llmOp = new AuthoredFlowOperation(
190
+ id, 'llm',
191
+ () => assertOperationAllowed('llm', definition.name, requestedCompletion),
192
+ () => observeStep(id, 'llm', () => {
193
+ if (typeof prompt === 'string') {
194
+ if (values.length !== 1 || values[0] === undefined) {
195
+ throw new AuthoredFlowExecutionError('llm_cli_unresolved', 'f.llm(prompt, options) requires an output JSON Schema.');
196
+ }
197
+ return worker.llm(id, prompt, values[0] as LlmOptions, llmOp.namedGate);
198
+ }
199
+ const text = prompt.reduce((result, part, index) => result + part
200
+ + (index < values.length ? String(values[index]) : ''), '');
201
+ return worker.llm(id, text, undefined, llmOp.namedGate);
202
+ }, onProgress),
203
+ lifecycle,
204
+ );
205
+ return trackStep(authoredSteps, llmOp);
206
+ }
207
+
208
+ const slackRun = randomUUID();
209
+ function slackOperation<T>(call: SlackCall): Step<T> {
210
+ assertOperationAllowed(`slack.${call.verb}`, definition.name, requestedCompletion);
211
+ const snapshot = snapshotJsonValue(call, 'f.slack call') as unknown as SlackCall;
212
+ const id = `slack-${slackRun}-${nextStep++}`;
213
+ return trackStep(authoredSteps, new AuthoredFlowOperation<T>(
214
+ id, `slack.${call.verb}`,
215
+ () => assertOperationAllowed(`slack.${call.verb}`, definition.name, requestedCompletion),
216
+ async () => {
217
+ const receipt = await runHelperEffect(journal, definition.name, id, snapshot,
218
+ options.dataDir ?? dirname(journal.socketPath), journalSteps);
219
+ return (call.verb === 'react' ? undefined : receipt) as T;
220
+ },
221
+ lifecycle,
222
+ ));
223
+ }
308
224
 
309
225
  const context: Ctx = {
310
- run(command) {
226
+ ...createHelpers(<T>(call: HelperCall): Step<T> => {
227
+ const verb = `${call.provider}.${call.verb}`;
228
+ assertOperationAllowed(verb, definition.name, requestedCompletion);
229
+ const snapshot = snapshotJsonValue(call, `f.${verb} call`) as unknown as HelperCall;
230
+ const id = `${call.provider}-${slackRun}-${nextStep++}`;
231
+ return trackStep(authoredSteps, new AuthoredFlowOperation<T>(id, verb,
232
+ () => assertOperationAllowed(verb, definition.name, requestedCompletion),
233
+ async () => await runHelperEffect(journal, definition.name, id, snapshot,
234
+ options.dataDir ?? dirname(journal.socketPath), journalSteps) as T,
235
+ lifecycle));
236
+ }),
237
+ slack: {
238
+ post: (channel, text, opts) => slackOperation({ type: 'effect', provider: 'slack', verb: 'post', params: { channel, text, ...(opts === undefined ? {} : { opts }) } }),
239
+ dm: (user, text) => slackOperation({ type: 'effect', provider: 'slack', verb: 'dm', params: { user, text } }),
240
+ reply: (channel, threadTs, text) => slackOperation({ type: 'effect', provider: 'slack', verb: 'reply', params: { channel, threadTs, text } }),
241
+ react: (channel, messageTs, emoji) => slackOperation({ type: 'effect', provider: 'slack', verb: 'react', params: { channel, messageTs, emoji } }),
242
+ },
243
+ mcp: buildMcpProxy(checkedMcp.inventory, (server, tool, args, known) => {
244
+ assertOperationAllowed('mcp', definition.name, requestedCompletion);
245
+ const id = `mcp-${nextStep++}`;
246
+ return trackStep(authoredSteps, new AuthoredFlowOperation(
247
+ id, 'mcp',
248
+ () => assertOperationAllowed('mcp', definition.name, requestedCompletion),
249
+ () => runMcpEffect(journal, definition.name, id, server, tool, args,
250
+ known, checkedMcp.servers[server]!, journalSteps),
251
+ lifecycle,
252
+ ));
253
+ }),
254
+ memory: authoredMemory(
255
+ scriptMemoryScope(flowPath, definition.name),
256
+ () => assertOperationAllowed('memory', definition.name, requestedCompletion),
257
+ definition.header.memory?.script !== false,
258
+ ),
259
+ run(command, runOptions) {
311
260
  assertOperationAllowed('run', definition.name, requestedCompletion);
261
+ const leaseMs = runOptions?.timeout === undefined ? undefined : parseStepTimeout(runOptions.timeout);
312
262
  const id = `run-${nextStep++}`;
313
- return trackStep(authoredSteps, new AuthoredFlowOperation(
263
+ let runOp!: AuthoredFlowOperation<string>;
264
+ runOp = new AuthoredFlowOperation<string>(
314
265
  id,
315
266
  'run',
316
267
  () => assertOperationAllowed('run', definition.name, requestedCompletion),
317
- () => lowerDeterministic(id, command),
318
- lifecycle,
319
- ));
320
- },
321
- llm() {
322
- assertOperationAllowed('llm', definition.name, requestedCompletion);
323
- const id = `llm-${nextStep++}`;
324
- return trackStep(authoredSteps, unsupportedStep(
325
- id,
326
- 'llm',
327
- () => assertOperationAllowed('llm', definition.name, requestedCompletion),
268
+ () => observeStep(id, 'deterministic', () => lowerDeterministic(id, command, false, leaseMs, runOp.namedGate), options.onProgress),
328
269
  lifecycle,
329
- ));
270
+ );
271
+ return trackStep(authoredSteps, runOp);
330
272
  },
273
+ llm: llmOperation,
331
274
  agent(name, options) {
332
275
  assertOperationAllowed('agent', definition.name, requestedCompletion);
276
+ void name; // Authored headers do not yet declare reusable named agents.
333
277
  const id = `agent-${nextStep++}`;
334
- return trackStep(authoredSteps, new AuthoredFlowOperation(
278
+ let agentOp!: AuthoredFlowOperation<AgentResult>;
279
+ agentOp = new AuthoredFlowOperation<AgentResult>(
335
280
  id,
336
281
  'agent',
337
282
  () => assertOperationAllowed('agent', definition.name, requestedCompletion),
338
- () => lowerAgent(id, name, options),
283
+ () => observeStep(id, 'agent', () => worker.agent(id, options, agentOp.namedGate), onProgress),
339
284
  lifecycle,
340
- ));
285
+ );
286
+ return trackStep(authoredSteps, agentOp);
341
287
  },
342
288
  human() {
343
289
  assertOperationAllowed('human', definition.name, requestedCompletion);
@@ -348,7 +294,7 @@ export async function executeAuthoredFlow<Input = undefined>(
348
294
  throw unsupportedVerb('dispatch');
349
295
  },
350
296
  done(reason) {
351
- if (!isSurfaceRunCompletionReason(reason)) {
297
+ if (reason !== 'needs_human' && !isSurfaceRunCompletionReason(reason)) {
352
298
  throw new AuthoredFlowExecutionError(
353
299
  'unsupported_completion',
354
300
  `unknown completion reason: ${String(reason)}`,
@@ -360,7 +306,7 @@ export async function executeAuthoredFlow<Input = undefined>(
360
306
  `flow "${definition.name}" called done() more than once`,
361
307
  );
362
308
  }
363
- if (reason !== 'success') {
309
+ if (reason !== 'success' && reason !== 'needs_human') {
364
310
  throw new AuthoredFlowExecutionError(
365
311
  'unsupported_completion',
366
312
  `the initial authored executor cannot lower done("${reason}")`,
@@ -375,6 +321,17 @@ export async function executeAuthoredFlow<Input = undefined>(
375
321
  ),
376
322
  };
377
323
 
324
+ Object.assign(context, pluginHelpers(checkedMcp.plugins ?? [], (plugin, verb, args) => {
325
+ const label = `${verb.namespace}.${verb.method}`;
326
+ assertOperationAllowed(label, definition.name, requestedCompletion);
327
+ const id = `plugin-${nextStep++}`;
328
+ return trackStep(authoredSteps, new AuthoredFlowOperation(
329
+ id, label, () => assertOperationAllowed(label, definition.name, requestedCompletion),
330
+ () => runPluginEffect(journal, definition.name, id, plugin, verb, args, journalSteps, budget),
331
+ lifecycle,
332
+ ));
333
+ }));
334
+
378
335
  let bodyFailed = false;
379
336
  let bodyFailure: unknown;
380
337
  try {
@@ -424,7 +381,11 @@ export async function executeAuthoredFlow<Input = undefined>(
424
381
  lifecycle.close();
425
382
  }
426
383
 
427
- await lowerDeterministic(`complete-${nextStep}`, ':');
384
+ // The authored runner has no durable root yet. Record the handoff as a
385
+ // successful effect containing the authored outcome, not a fabricated kernel
386
+ // run.completed reason. The CLI reports this outcome as parked (exit 3).
387
+ await lowerDeterministic(`complete-${nextStep}`, requestedCompletion === 'needs_human'
388
+ ? `printf '%s' '{"completionReason":"needs_human"}'` : ':', true);
428
389
  return Object.freeze({
429
390
  name: definition.name,
430
391
  completionReason: requestedCompletion,
@@ -440,17 +401,6 @@ function trackStep<T>(
440
401
  return operation.step;
441
402
  }
442
403
 
443
- function unsupportedStep<T>(
444
- id: string,
445
- verb: string,
446
- assertCanStart: () => void,
447
- lifecycle: AuthoredFlowLifecycle,
448
- ): AuthoredFlowOperation<T> {
449
- return new AuthoredFlowOperation<T>(id, verb, assertCanStart, async () => {
450
- throw unsupportedVerb(verb);
451
- }, lifecycle);
452
- }
453
-
454
404
  function unsupportedVerb(verb: string): AuthoredFlowExecutionError {
455
405
  return new AuthoredFlowExecutionError(
456
406
  'unsupported_verb',
@@ -461,13 +411,13 @@ function unsupportedVerb(verb: string): AuthoredFlowExecutionError {
461
411
  function assertOperationAllowed(
462
412
  verb: string,
463
413
  flowName: string,
464
- completion: SurfaceRunCompletionReason | undefined,
414
+ completion: FlowCompletionReason | undefined,
465
415
  ): void {
466
416
  if (completion !== undefined) {
467
417
  throw new AuthoredFlowExecutionError(
468
418
  'operation_after_completion',
469
419
  `flow "${flowName}" called f.${verb} after done()`,
470
- completion,
420
+ completion === 'needs_human' ? undefined : completion,
471
421
  );
472
422
  }
473
423
  }
@@ -480,129 +430,3 @@ function unsupportedCloud(assertOpen: () => void): CloudHelper {
480
430
  },
481
431
  }) as CloudHelper;
482
432
  }
483
-
484
- /**
485
- * Shared by every `f.*` verb that lowers to one kernel step run in isolation:
486
- * find its `step.completed` entry, record it, and refuse anything but a
487
- * clean success before handing the raw `output` back for verb-specific
488
- * extraction (a plain string for `f.run`, an `AgentResult` for `f.agent`).
489
- *
490
- * Callers are responsible for having already established that the RUN
491
- * reached a terminal, successful state before calling this — `f.run`'s
492
- * caller relies on `runStart`'s own immediate response (the kernel drives a
493
- * deterministic step to completion inline, no race); `f.agent`'s caller
494
- * relies on `classifyOutcome` (cli/run.ts) having already polled to a true
495
- * terminal state. Given that, a single read from the start of this run's
496
- * (small, single-step) journal is enough — no polling here, and no run
497
- * outcome ever needs re-checking.
498
- */
499
- async function readCompletedStepOutput(
500
- journal: JournalClient,
501
- runId: string,
502
- stepId: string,
503
- journalSteps: AuthoredFlowJournalStep[],
504
- ): Promise<unknown> {
505
- const entries = (await journal.journalRead(runId, 1)).entries;
506
- const completed = entries.find((entry) => isStepCompleted(entry, stepId));
507
- if (!isStepCompleted(completed, stepId)) {
508
- throw protocolViolation(runId, `journal has no step.completed for "${stepId}"`);
509
- }
510
-
511
- const reason = completed.payload.completionReason;
512
- journalSteps.push(Object.freeze({ id: stepId, runId, completionReason: reason }));
513
- if (reason !== 'success') {
514
- throw new AuthoredFlowExecutionError(
515
- 'step_failed',
516
- `journal step "${stepId}" completed with ${reason}`,
517
- reason,
518
- runId,
519
- );
520
- }
521
- return completed.payload.output;
522
- }
523
-
524
- async function readSuccessfulOutput(
525
- journal: JournalClient,
526
- outcome: RunOutcome,
527
- stepId: string,
528
- journalSteps: AuthoredFlowJournalStep[],
529
- ): Promise<string> {
530
- const output = await readCompletedStepOutput(journal, outcome.run_id, stepId, journalSteps);
531
- if (!isRecord(output) || typeof output['stdout_tail'] !== 'string') {
532
- throw protocolViolation(outcome.run_id, `step "${stepId}" has no string stdout_tail`);
533
- }
534
- return output['stdout_tail'];
535
- }
536
-
537
- /**
538
- * The kernel journals an agent step's raw `CliResult` shape
539
- * (`exit_code`/`stdout_tail`/`stderr_tail`) — same as a deterministic step —
540
- * UNLESS the CLI's stdout parsed as JSON, in which case `output` is that
541
- * parsed object directly (worker.ts: `parseJsonOutput(result.stdout_tail) ??
542
- * result`). Neither shape carries a real `artifacts` list today: nothing in
543
- * the kernel or worker enumerates files an agent wrote, and `f.agent`'s
544
- * `AgentOptions` has no `output` schema parameter for a CLI to target either
545
- * (unlike the declarative `AgentStepSpec.output` field). `artifacts` is
546
- * therefore always empty here — honest about what data exists, not a
547
- * placeholder for something not yet wired.
548
- */
549
- async function readSuccessfulAgentOutput(
550
- journal: JournalClient,
551
- runId: string,
552
- stepId: string,
553
- journalSteps: AuthoredFlowJournalStep[],
554
- ): Promise<AgentResult> {
555
- const output = await readCompletedStepOutput(journal, runId, stepId, journalSteps);
556
- if (!isRecord(output)) {
557
- throw protocolViolation(runId, `step "${stepId}" produced a non-object output`);
558
- }
559
- if (typeof output['stdout_tail'] === 'string') {
560
- return { summary: output['stdout_tail'], artifacts: [] };
561
- }
562
- // The CLI's stdout parsed as JSON, so `output` is that value, not a
563
- // CliResult. Fall back to a stable, inspectable summary rather than
564
- // refusing a run whose agent step genuinely succeeded.
565
- return { summary: JSON.stringify(output), artifacts: [] };
566
- }
567
-
568
- interface StepCompletedEntry {
569
- entry_type: 'step.completed';
570
- step_id: string;
571
- payload: {
572
- completionReason: ProtocolCompletionReason;
573
- output: unknown;
574
- };
575
- }
576
-
577
- function isStepCompleted(value: unknown, stepId: string): value is StepCompletedEntry {
578
- if (!isRecord(value) || value['entry_type'] !== 'step.completed' || value['step_id'] !== stepId) {
579
- return false;
580
- }
581
- const payload = value['payload'];
582
- return isRecord(payload)
583
- && isSurfaceCompletionReason(payload['completionReason'])
584
- && 'output' in payload;
585
- }
586
-
587
- function isSurfaceCompletionReason(value: unknown): value is ProtocolCompletionReason {
588
- return typeof value === 'string'
589
- && (COMPLETION_REASONS as readonly string[]).includes(value);
590
- }
591
-
592
- function isSurfaceRunCompletionReason(value: unknown): value is ProtocolRunCompletionReason {
593
- return typeof value === 'string'
594
- && (RUN_COMPLETION_REASONS as readonly string[]).includes(value);
595
- }
596
-
597
- function isRecord(value: unknown): value is Record<string, unknown> {
598
- return typeof value === 'object' && value !== null && !Array.isArray(value);
599
- }
600
-
601
- function protocolViolation(runId: string, detail: string): AuthoredFlowExecutionError {
602
- return new AuthoredFlowExecutionError(
603
- 'journal_protocol_violation',
604
- detail,
605
- undefined,
606
- runId,
607
- );
608
- }