agent-relay 2.3.2 → 2.3.5

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 (334) hide show
  1. package/README.md +1 -1
  2. package/dist/index.cjs +1 -1
  3. package/dist/src/cli/index.js +124 -7
  4. package/dist/src/cli/index.js.map +1 -1
  5. package/package.json +20 -26
  6. package/packages/acp-bridge/package.json +2 -2
  7. package/packages/bridge/package.json +7 -7
  8. package/packages/config/dist/cloud-config.d.ts +1 -1
  9. package/packages/config/dist/cloud-config.d.ts.map +1 -1
  10. package/packages/config/dist/cloud-config.js.map +1 -1
  11. package/packages/config/dist/schemas.d.ts +5 -5
  12. package/packages/config/dist/schemas.js +1 -1
  13. package/packages/config/dist/schemas.js.map +1 -1
  14. package/packages/config/package.json +2 -2
  15. package/packages/config/src/cloud-config.ts +2 -2
  16. package/packages/config/src/schemas.test.ts +48 -0
  17. package/packages/config/src/schemas.ts +1 -1
  18. package/packages/continuity/package.json +2 -2
  19. package/packages/daemon/package.json +12 -12
  20. package/packages/hooks/package.json +4 -4
  21. package/packages/mcp/package.json +5 -5
  22. package/packages/memory/package.json +2 -2
  23. package/packages/policy/package.json +2 -2
  24. package/packages/protocol/package.json +1 -1
  25. package/packages/resiliency/package.json +1 -1
  26. package/packages/sdk/dist/index.d.ts +1 -29
  27. package/packages/sdk/dist/index.d.ts.map +1 -1
  28. package/packages/sdk/dist/index.js +1 -38
  29. package/packages/sdk/dist/index.js.map +1 -1
  30. package/packages/sdk/package.json +4 -25
  31. package/packages/sdk/src/index.ts +1 -69
  32. package/packages/sdk-py/README.md +56 -0
  33. package/packages/sdk-py/pyproject.toml +23 -0
  34. package/packages/sdk-py/src/agent_relay/__init__.py +27 -0
  35. package/packages/sdk-py/src/agent_relay/builder.py +367 -0
  36. package/packages/sdk-py/src/agent_relay/types.py +92 -0
  37. package/packages/sdk-py/tests/__init__.py +0 -0
  38. package/packages/sdk-py/tests/test_builder.py +101 -0
  39. package/packages/sdk-ts/dist/__tests__/facade.test.d.ts +2 -0
  40. package/packages/sdk-ts/dist/__tests__/facade.test.d.ts.map +1 -0
  41. package/packages/sdk-ts/dist/__tests__/facade.test.js +257 -0
  42. package/packages/sdk-ts/dist/__tests__/facade.test.js.map +1 -0
  43. package/packages/sdk-ts/dist/__tests__/unit.test.d.ts +2 -0
  44. package/packages/sdk-ts/dist/__tests__/unit.test.d.ts.map +1 -0
  45. package/packages/sdk-ts/dist/__tests__/unit.test.js +124 -0
  46. package/packages/sdk-ts/dist/__tests__/unit.test.js.map +1 -0
  47. package/packages/sdk-ts/dist/client.d.ts +2 -0
  48. package/packages/sdk-ts/dist/client.d.ts.map +1 -1
  49. package/packages/sdk-ts/dist/client.js +2 -0
  50. package/packages/sdk-ts/dist/client.js.map +1 -1
  51. package/packages/sdk-ts/dist/index.d.ts +1 -0
  52. package/packages/sdk-ts/dist/index.d.ts.map +1 -1
  53. package/packages/sdk-ts/dist/index.js +1 -0
  54. package/packages/sdk-ts/dist/index.js.map +1 -1
  55. package/packages/sdk-ts/dist/protocol.d.ts +1 -0
  56. package/packages/sdk-ts/dist/protocol.d.ts.map +1 -1
  57. package/packages/sdk-ts/dist/relay.d.ts +44 -0
  58. package/packages/sdk-ts/dist/relay.d.ts.map +1 -1
  59. package/packages/sdk-ts/dist/relay.js +89 -11
  60. package/packages/sdk-ts/dist/relay.js.map +1 -1
  61. package/packages/sdk-ts/dist/relaycast.js +2 -2
  62. package/packages/sdk-ts/dist/relaycast.js.map +1 -1
  63. package/packages/sdk-ts/dist/workflows/barrier.d.ts +72 -0
  64. package/packages/sdk-ts/dist/workflows/barrier.d.ts.map +1 -0
  65. package/packages/sdk-ts/dist/workflows/barrier.js +162 -0
  66. package/packages/sdk-ts/dist/workflows/barrier.js.map +1 -0
  67. package/packages/sdk-ts/dist/workflows/builder.d.ts +101 -0
  68. package/packages/sdk-ts/dist/workflows/builder.d.ts.map +1 -0
  69. package/packages/sdk-ts/dist/workflows/builder.js +179 -0
  70. package/packages/sdk-ts/dist/workflows/builder.js.map +1 -0
  71. package/packages/sdk-ts/dist/workflows/cli.d.ts +10 -0
  72. package/packages/sdk-ts/dist/workflows/cli.d.ts.map +1 -0
  73. package/packages/sdk-ts/dist/workflows/cli.js +82 -0
  74. package/packages/sdk-ts/dist/workflows/cli.js.map +1 -0
  75. package/packages/sdk-ts/dist/workflows/coordinator.d.ts +68 -0
  76. package/packages/sdk-ts/dist/workflows/coordinator.d.ts.map +1 -0
  77. package/packages/sdk-ts/dist/workflows/coordinator.js +353 -0
  78. package/packages/sdk-ts/dist/workflows/coordinator.js.map +1 -0
  79. package/packages/sdk-ts/dist/workflows/index.d.ts +10 -0
  80. package/packages/sdk-ts/dist/workflows/index.d.ts.map +1 -0
  81. package/packages/sdk-ts/dist/workflows/index.js +10 -0
  82. package/packages/sdk-ts/dist/workflows/index.js.map +1 -0
  83. package/packages/sdk-ts/dist/workflows/memory-db.d.ts +17 -0
  84. package/packages/sdk-ts/dist/workflows/memory-db.d.ts.map +1 -0
  85. package/packages/sdk-ts/dist/workflows/memory-db.js +33 -0
  86. package/packages/sdk-ts/dist/workflows/memory-db.js.map +1 -0
  87. package/packages/sdk-ts/dist/workflows/run.d.ts +31 -0
  88. package/packages/sdk-ts/dist/workflows/run.d.ts.map +1 -0
  89. package/packages/sdk-ts/dist/workflows/run.js +24 -0
  90. package/packages/sdk-ts/dist/workflows/run.js.map +1 -0
  91. package/packages/sdk-ts/dist/workflows/runner.d.ts +119 -0
  92. package/packages/sdk-ts/dist/workflows/runner.d.ts.map +1 -0
  93. package/packages/sdk-ts/dist/workflows/runner.js +650 -0
  94. package/packages/sdk-ts/dist/workflows/runner.js.map +1 -0
  95. package/packages/sdk-ts/dist/workflows/state.d.ts +77 -0
  96. package/packages/sdk-ts/dist/workflows/state.d.ts.map +1 -0
  97. package/packages/sdk-ts/dist/workflows/state.js +140 -0
  98. package/packages/sdk-ts/dist/workflows/state.js.map +1 -0
  99. package/packages/sdk-ts/dist/workflows/templates.d.ts +47 -0
  100. package/packages/sdk-ts/dist/workflows/templates.d.ts.map +1 -0
  101. package/packages/sdk-ts/dist/workflows/templates.js +395 -0
  102. package/packages/sdk-ts/dist/workflows/templates.js.map +1 -0
  103. package/packages/sdk-ts/dist/workflows/types.d.ts +126 -0
  104. package/packages/sdk-ts/dist/workflows/types.d.ts.map +1 -0
  105. package/packages/sdk-ts/dist/workflows/types.js +8 -0
  106. package/packages/sdk-ts/dist/workflows/types.js.map +1 -0
  107. package/packages/sdk-ts/package.json +9 -3
  108. package/packages/sdk-ts/src/__tests__/error-scenarios.test.ts +682 -0
  109. package/packages/sdk-ts/src/__tests__/facade.test.ts +296 -0
  110. package/packages/sdk-ts/src/__tests__/swarm-coordinator.test.ts +416 -0
  111. package/packages/sdk-ts/src/__tests__/unit.test.ts +152 -0
  112. package/packages/sdk-ts/src/__tests__/workflow-runner.test.ts +333 -0
  113. package/packages/sdk-ts/src/client.ts +4 -0
  114. package/packages/sdk-ts/src/index.ts +1 -0
  115. package/packages/sdk-ts/src/protocol.ts +1 -1
  116. package/packages/sdk-ts/src/relay.ts +112 -11
  117. package/packages/sdk-ts/src/relaycast.ts +2 -2
  118. package/packages/sdk-ts/src/workflows/README.md +450 -0
  119. package/packages/sdk-ts/src/workflows/barrier.ts +254 -0
  120. package/packages/sdk-ts/src/workflows/builder.ts +241 -0
  121. package/packages/sdk-ts/src/workflows/builtin-templates/bug-fix.yaml +75 -0
  122. package/packages/sdk-ts/src/workflows/builtin-templates/code-review.yaml +82 -0
  123. package/packages/sdk-ts/src/workflows/builtin-templates/documentation.yaml +70 -0
  124. package/packages/sdk-ts/src/workflows/builtin-templates/feature-dev.yaml +76 -0
  125. package/packages/sdk-ts/src/workflows/builtin-templates/refactor.yaml +82 -0
  126. package/packages/sdk-ts/src/workflows/builtin-templates/security-audit.yaml +84 -0
  127. package/packages/sdk-ts/src/workflows/cli.ts +93 -0
  128. package/packages/sdk-ts/src/workflows/coordinator.ts +520 -0
  129. package/packages/sdk-ts/src/workflows/index.ts +9 -0
  130. package/packages/sdk-ts/src/workflows/memory-db.ts +39 -0
  131. package/packages/sdk-ts/src/workflows/run.ts +47 -0
  132. package/packages/sdk-ts/src/workflows/runner.ts +873 -0
  133. package/packages/sdk-ts/src/workflows/schema.json +321 -0
  134. package/packages/sdk-ts/src/workflows/state.ts +279 -0
  135. package/packages/sdk-ts/src/workflows/templates.ts +544 -0
  136. package/packages/sdk-ts/src/workflows/types.ts +178 -0
  137. package/packages/sdk-ts/tsconfig.json +6 -1
  138. package/packages/spawner/package.json +1 -1
  139. package/packages/state/package.json +1 -1
  140. package/packages/storage/package.json +2 -2
  141. package/packages/telemetry/package.json +1 -1
  142. package/packages/trajectory/package.json +2 -2
  143. package/packages/user-directory/package.json +2 -2
  144. package/packages/utils/package.json +3 -3
  145. package/packages/wrapper/package.json +5 -6
  146. package/scripts/postinstall.js +106 -2
  147. package/packages/api-types/.trajectories/active/traj_xbsvuzogscey.json +0 -15
  148. package/packages/api-types/.trajectories/index.json +0 -12
  149. package/packages/api-types/dist/index.d.ts +0 -21
  150. package/packages/api-types/dist/index.d.ts.map +0 -1
  151. package/packages/api-types/dist/index.js +0 -22
  152. package/packages/api-types/dist/index.js.map +0 -1
  153. package/packages/api-types/dist/schemas/agent.d.ts +0 -259
  154. package/packages/api-types/dist/schemas/agent.d.ts.map +0 -1
  155. package/packages/api-types/dist/schemas/agent.js +0 -102
  156. package/packages/api-types/dist/schemas/agent.js.map +0 -1
  157. package/packages/api-types/dist/schemas/api.d.ts +0 -290
  158. package/packages/api-types/dist/schemas/api.d.ts.map +0 -1
  159. package/packages/api-types/dist/schemas/api.js +0 -162
  160. package/packages/api-types/dist/schemas/api.js.map +0 -1
  161. package/packages/api-types/dist/schemas/decision.d.ts +0 -230
  162. package/packages/api-types/dist/schemas/decision.d.ts.map +0 -1
  163. package/packages/api-types/dist/schemas/decision.js +0 -104
  164. package/packages/api-types/dist/schemas/decision.js.map +0 -1
  165. package/packages/api-types/dist/schemas/fleet.d.ts +0 -615
  166. package/packages/api-types/dist/schemas/fleet.d.ts.map +0 -1
  167. package/packages/api-types/dist/schemas/fleet.js +0 -71
  168. package/packages/api-types/dist/schemas/fleet.js.map +0 -1
  169. package/packages/api-types/dist/schemas/history.d.ts +0 -180
  170. package/packages/api-types/dist/schemas/history.d.ts.map +0 -1
  171. package/packages/api-types/dist/schemas/history.js +0 -72
  172. package/packages/api-types/dist/schemas/history.js.map +0 -1
  173. package/packages/api-types/dist/schemas/index.d.ts +0 -14
  174. package/packages/api-types/dist/schemas/index.d.ts.map +0 -1
  175. package/packages/api-types/dist/schemas/index.js +0 -22
  176. package/packages/api-types/dist/schemas/index.js.map +0 -1
  177. package/packages/api-types/dist/schemas/message.d.ts +0 -456
  178. package/packages/api-types/dist/schemas/message.d.ts.map +0 -1
  179. package/packages/api-types/dist/schemas/message.js +0 -88
  180. package/packages/api-types/dist/schemas/message.js.map +0 -1
  181. package/packages/api-types/dist/schemas/session.d.ts +0 -60
  182. package/packages/api-types/dist/schemas/session.d.ts.map +0 -1
  183. package/packages/api-types/dist/schemas/session.js +0 -36
  184. package/packages/api-types/dist/schemas/session.js.map +0 -1
  185. package/packages/api-types/dist/schemas/task.d.ts +0 -111
  186. package/packages/api-types/dist/schemas/task.d.ts.map +0 -1
  187. package/packages/api-types/dist/schemas/task.js +0 -64
  188. package/packages/api-types/dist/schemas/task.js.map +0 -1
  189. package/packages/api-types/package.json +0 -61
  190. package/packages/api-types/scripts/generate-openapi.ts +0 -106
  191. package/packages/api-types/src/index.ts +0 -22
  192. package/packages/api-types/src/schemas/agent.test.ts +0 -164
  193. package/packages/api-types/src/schemas/agent.ts +0 -110
  194. package/packages/api-types/src/schemas/api.test.ts +0 -372
  195. package/packages/api-types/src/schemas/api.ts +0 -194
  196. package/packages/api-types/src/schemas/decision.test.ts +0 -324
  197. package/packages/api-types/src/schemas/decision.ts +0 -136
  198. package/packages/api-types/src/schemas/fleet.test.ts +0 -212
  199. package/packages/api-types/src/schemas/fleet.ts +0 -83
  200. package/packages/api-types/src/schemas/history.test.ts +0 -242
  201. package/packages/api-types/src/schemas/history.ts +0 -84
  202. package/packages/api-types/src/schemas/index.ts +0 -148
  203. package/packages/api-types/src/schemas/message.test.ts +0 -192
  204. package/packages/api-types/src/schemas/message.ts +0 -98
  205. package/packages/api-types/src/schemas/session.test.ts +0 -104
  206. package/packages/api-types/src/schemas/session.ts +0 -40
  207. package/packages/api-types/src/schemas/task.test.ts +0 -192
  208. package/packages/api-types/src/schemas/task.ts +0 -78
  209. package/packages/api-types/tsconfig.json +0 -19
  210. package/packages/api-types/vitest.config.ts +0 -9
  211. package/packages/benchmark/README.md +0 -200
  212. package/packages/benchmark/datasets/coding-tasks.yaml +0 -127
  213. package/packages/benchmark/datasets/coordination-tasks.yaml +0 -122
  214. package/packages/benchmark/datasets/quick-test.yaml +0 -20
  215. package/packages/benchmark/dist/benchmark.d.ts +0 -47
  216. package/packages/benchmark/dist/benchmark.d.ts.map +0 -1
  217. package/packages/benchmark/dist/benchmark.js +0 -224
  218. package/packages/benchmark/dist/benchmark.js.map +0 -1
  219. package/packages/benchmark/dist/cli.d.ts +0 -8
  220. package/packages/benchmark/dist/cli.d.ts.map +0 -1
  221. package/packages/benchmark/dist/cli.js +0 -185
  222. package/packages/benchmark/dist/cli.js.map +0 -1
  223. package/packages/benchmark/dist/harbor.d.ts +0 -53
  224. package/packages/benchmark/dist/harbor.d.ts.map +0 -1
  225. package/packages/benchmark/dist/harbor.js +0 -127
  226. package/packages/benchmark/dist/harbor.js.map +0 -1
  227. package/packages/benchmark/dist/index.d.ts +0 -48
  228. package/packages/benchmark/dist/index.d.ts.map +0 -1
  229. package/packages/benchmark/dist/index.js +0 -50
  230. package/packages/benchmark/dist/index.js.map +0 -1
  231. package/packages/benchmark/dist/runners/base.d.ts +0 -63
  232. package/packages/benchmark/dist/runners/base.d.ts.map +0 -1
  233. package/packages/benchmark/dist/runners/base.js +0 -156
  234. package/packages/benchmark/dist/runners/base.js.map +0 -1
  235. package/packages/benchmark/dist/runners/index.d.ts +0 -10
  236. package/packages/benchmark/dist/runners/index.d.ts.map +0 -1
  237. package/packages/benchmark/dist/runners/index.js +0 -10
  238. package/packages/benchmark/dist/runners/index.js.map +0 -1
  239. package/packages/benchmark/dist/runners/single.d.ts +0 -19
  240. package/packages/benchmark/dist/runners/single.d.ts.map +0 -1
  241. package/packages/benchmark/dist/runners/single.js +0 -111
  242. package/packages/benchmark/dist/runners/single.js.map +0 -1
  243. package/packages/benchmark/dist/runners/subagent.d.ts +0 -32
  244. package/packages/benchmark/dist/runners/subagent.d.ts.map +0 -1
  245. package/packages/benchmark/dist/runners/subagent.js +0 -212
  246. package/packages/benchmark/dist/runners/subagent.js.map +0 -1
  247. package/packages/benchmark/dist/runners/swarm.d.ts +0 -36
  248. package/packages/benchmark/dist/runners/swarm.d.ts.map +0 -1
  249. package/packages/benchmark/dist/runners/swarm.js +0 -273
  250. package/packages/benchmark/dist/runners/swarm.js.map +0 -1
  251. package/packages/benchmark/dist/types.d.ts +0 -178
  252. package/packages/benchmark/dist/types.d.ts.map +0 -1
  253. package/packages/benchmark/dist/types.js +0 -16
  254. package/packages/benchmark/dist/types.js.map +0 -1
  255. package/packages/benchmark/package.json +0 -80
  256. package/packages/benchmark/src/benchmark.ts +0 -298
  257. package/packages/benchmark/src/cli.ts +0 -240
  258. package/packages/benchmark/src/harbor.ts +0 -170
  259. package/packages/benchmark/src/index.ts +0 -73
  260. package/packages/benchmark/src/runners/base.ts +0 -205
  261. package/packages/benchmark/src/runners/index.ts +0 -10
  262. package/packages/benchmark/src/runners/single.ts +0 -121
  263. package/packages/benchmark/src/runners/subagent.ts +0 -240
  264. package/packages/benchmark/src/runners/swarm.ts +0 -326
  265. package/packages/benchmark/src/types.ts +0 -205
  266. package/packages/benchmark/tsconfig.json +0 -20
  267. package/packages/cli-tester/README.md +0 -277
  268. package/packages/cli-tester/dist/index.d.ts +0 -21
  269. package/packages/cli-tester/dist/index.d.ts.map +0 -1
  270. package/packages/cli-tester/dist/index.js +0 -21
  271. package/packages/cli-tester/dist/index.js.map +0 -1
  272. package/packages/cli-tester/dist/utils/credential-check.d.ts +0 -56
  273. package/packages/cli-tester/dist/utils/credential-check.d.ts.map +0 -1
  274. package/packages/cli-tester/dist/utils/credential-check.js +0 -230
  275. package/packages/cli-tester/dist/utils/credential-check.js.map +0 -1
  276. package/packages/cli-tester/dist/utils/socket-client.d.ts +0 -76
  277. package/packages/cli-tester/dist/utils/socket-client.d.ts.map +0 -1
  278. package/packages/cli-tester/dist/utils/socket-client.js +0 -153
  279. package/packages/cli-tester/dist/utils/socket-client.js.map +0 -1
  280. package/packages/cli-tester/docker/Dockerfile +0 -61
  281. package/packages/cli-tester/docker/docker-compose.yml +0 -71
  282. package/packages/cli-tester/docker/entrypoint.sh +0 -58
  283. package/packages/cli-tester/package.json +0 -32
  284. package/packages/cli-tester/scripts/clear-auth.sh +0 -101
  285. package/packages/cli-tester/scripts/inject-message.sh +0 -42
  286. package/packages/cli-tester/scripts/start.sh +0 -71
  287. package/packages/cli-tester/scripts/test-cli.sh +0 -56
  288. package/packages/cli-tester/scripts/test-full-spawn.sh +0 -238
  289. package/packages/cli-tester/scripts/test-registration.sh +0 -182
  290. package/packages/cli-tester/scripts/test-setup-flow.sh +0 -202
  291. package/packages/cli-tester/scripts/test-spawn.sh +0 -140
  292. package/packages/cli-tester/scripts/test-with-daemon.sh +0 -247
  293. package/packages/cli-tester/scripts/verify-auth.sh +0 -112
  294. package/packages/cli-tester/src/index.ts +0 -40
  295. package/packages/cli-tester/src/utils/credential-check.ts +0 -284
  296. package/packages/cli-tester/src/utils/socket-client.ts +0 -211
  297. package/packages/cli-tester/tests/credential-check.test.ts +0 -56
  298. package/packages/cli-tester/tsconfig.json +0 -11
  299. package/packages/sdk/dist/browser-client.d.ts +0 -212
  300. package/packages/sdk/dist/browser-client.d.ts.map +0 -1
  301. package/packages/sdk/dist/browser-client.js +0 -750
  302. package/packages/sdk/dist/browser-client.js.map +0 -1
  303. package/packages/sdk/dist/browser-framing.d.ts +0 -46
  304. package/packages/sdk/dist/browser-framing.d.ts.map +0 -1
  305. package/packages/sdk/dist/browser-framing.js +0 -122
  306. package/packages/sdk/dist/browser-framing.js.map +0 -1
  307. package/packages/sdk/dist/standalone.d.ts +0 -89
  308. package/packages/sdk/dist/standalone.d.ts.map +0 -1
  309. package/packages/sdk/dist/standalone.js +0 -131
  310. package/packages/sdk/dist/standalone.js.map +0 -1
  311. package/packages/sdk/dist/transports/index.d.ts +0 -92
  312. package/packages/sdk/dist/transports/index.d.ts.map +0 -1
  313. package/packages/sdk/dist/transports/index.js +0 -129
  314. package/packages/sdk/dist/transports/index.js.map +0 -1
  315. package/packages/sdk/dist/transports/socket-transport.d.ts +0 -30
  316. package/packages/sdk/dist/transports/socket-transport.d.ts.map +0 -1
  317. package/packages/sdk/dist/transports/socket-transport.js +0 -94
  318. package/packages/sdk/dist/transports/socket-transport.js.map +0 -1
  319. package/packages/sdk/dist/transports/types.d.ts +0 -69
  320. package/packages/sdk/dist/transports/types.d.ts.map +0 -1
  321. package/packages/sdk/dist/transports/types.js +0 -10
  322. package/packages/sdk/dist/transports/types.js.map +0 -1
  323. package/packages/sdk/dist/transports/websocket-transport.d.ts +0 -55
  324. package/packages/sdk/dist/transports/websocket-transport.d.ts.map +0 -1
  325. package/packages/sdk/dist/transports/websocket-transport.js +0 -180
  326. package/packages/sdk/dist/transports/websocket-transport.js.map +0 -1
  327. package/packages/sdk/src/browser-client.ts +0 -985
  328. package/packages/sdk/src/browser-framing.test.ts +0 -115
  329. package/packages/sdk/src/browser-framing.ts +0 -150
  330. package/packages/sdk/src/standalone.ts +0 -183
  331. package/packages/sdk/src/transports/index.ts +0 -197
  332. package/packages/sdk/src/transports/socket-transport.ts +0 -115
  333. package/packages/sdk/src/transports/types.ts +0 -77
  334. package/packages/sdk/src/transports/websocket-transport.ts +0 -245
@@ -0,0 +1,544 @@
1
+ import { existsSync, promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
5
+ import type { RelayYamlConfig } from './types.js';
6
+
7
+ const YAML_EXTENSIONS = ['.yaml', '.yml'] as const;
8
+
9
+ export const BUILT_IN_TEMPLATE_NAMES = [
10
+ 'feature-dev',
11
+ 'bug-fix',
12
+ 'code-review',
13
+ 'security-audit',
14
+ 'refactor',
15
+ 'documentation',
16
+ ] as const;
17
+
18
+ export type BuiltInTemplateName = (typeof BUILT_IN_TEMPLATE_NAMES)[number];
19
+
20
+ export interface TemplateRegistryOptions {
21
+ builtInTemplatesDir?: string;
22
+ customTemplatesDir?: string;
23
+ workspaceDir?: string;
24
+ fetcher?: typeof fetch;
25
+ }
26
+
27
+ export interface LoadTemplateOptions {
28
+ overrides?: Record<string, unknown>;
29
+ }
30
+
31
+ export interface TemplateShorthandConfig {
32
+ swarm: string;
33
+ overrides?: Record<string, unknown>;
34
+ }
35
+
36
+ export type TemplateReferenceInput =
37
+ | string
38
+ | RelayYamlConfig
39
+ | (Partial<Omit<RelayYamlConfig, 'swarm'>> & TemplateShorthandConfig);
40
+
41
+ function isRecord(value: unknown): value is Record<string, unknown> {
42
+ return typeof value === 'object' && value !== null;
43
+ }
44
+
45
+ function hasYamlExtension(fileName: string): boolean {
46
+ return YAML_EXTENSIONS.some((ext) => fileName.endsWith(ext));
47
+ }
48
+
49
+ export class TemplateRegistry {
50
+ private readonly builtInTemplatesDir: string;
51
+ private readonly customTemplatesDir: string;
52
+ private readonly fetcher: typeof fetch;
53
+
54
+ constructor(options: TemplateRegistryOptions = {}) {
55
+ this.builtInTemplatesDir = this.resolveBuiltInTemplatesDir(options.builtInTemplatesDir);
56
+ this.customTemplatesDir = options.customTemplatesDir
57
+ ? path.resolve(options.customTemplatesDir)
58
+ : path.resolve(options.workspaceDir ?? process.cwd(), '.relay/workflows');
59
+
60
+ this.fetcher = options.fetcher ?? fetch;
61
+ }
62
+
63
+ listBuiltInTemplates(): string[] {
64
+ return [...BUILT_IN_TEMPLATE_NAMES];
65
+ }
66
+
67
+ async listCustomTemplates(): Promise<string[]> {
68
+ const files = await this.safeReadDir(this.customTemplatesDir);
69
+ return files
70
+ .filter((fileName) => hasYamlExtension(fileName))
71
+ .map((fileName) => this.normalizeTemplateName(fileName))
72
+ .sort();
73
+ }
74
+
75
+ async listTemplates(): Promise<string[]> {
76
+ const custom = await this.listCustomTemplates();
77
+ const merged = new Set<string>([...BUILT_IN_TEMPLATE_NAMES, ...custom]);
78
+ return Array.from(merged).sort();
79
+ }
80
+
81
+ async hasTemplate(name: string): Promise<boolean> {
82
+ try {
83
+ await this.resolveTemplatePath(name);
84
+ return true;
85
+ } catch {
86
+ return false;
87
+ }
88
+ }
89
+
90
+ async loadTemplate(
91
+ name: string,
92
+ options: LoadTemplateOptions = {}
93
+ ): Promise<RelayYamlConfig> {
94
+ const templatePath = await this.resolveTemplatePath(name);
95
+ const template = await this.readTemplateFile(templatePath);
96
+
97
+ if (options.overrides && Object.keys(options.overrides).length > 0) {
98
+ return this.applyOverrides(template, options.overrides);
99
+ }
100
+
101
+ return template;
102
+ }
103
+
104
+ async resolveTemplateReference(
105
+ input: TemplateReferenceInput,
106
+ options: LoadTemplateOptions = {}
107
+ ): Promise<RelayYamlConfig> {
108
+ if (typeof input === 'string') {
109
+ return this.loadTemplate(input, options);
110
+ }
111
+
112
+ if (this.isTemplateShorthand(input)) {
113
+ const { swarm, overrides = {}, ...rest } = input;
114
+ const mergedOverrides = {
115
+ ...overrides,
116
+ ...(options.overrides ?? {}),
117
+ };
118
+ const baseTemplate = await this.loadTemplate(swarm, {
119
+ overrides: mergedOverrides,
120
+ });
121
+ return this.mergeRelayConfig(baseTemplate, rest);
122
+ }
123
+
124
+ const config = this.cloneValue(input as RelayYamlConfig);
125
+
126
+ if (options.overrides && Object.keys(options.overrides).length > 0) {
127
+ return this.applyOverrides(config, options.overrides);
128
+ }
129
+
130
+ return config;
131
+ }
132
+
133
+ applyOverrides(
134
+ config: RelayYamlConfig,
135
+ overrides: Record<string, unknown>
136
+ ): RelayYamlConfig {
137
+ const nextConfig = this.cloneValue(config);
138
+
139
+ for (const [overridePath, value] of Object.entries(overrides)) {
140
+ this.setOverride(nextConfig, overridePath, value);
141
+ }
142
+
143
+ return nextConfig;
144
+ }
145
+
146
+ async installExternalTemplate(url: string, name?: string): Promise<string> {
147
+ const response = await this.fetcher(url);
148
+ if (!response.ok) {
149
+ throw new Error(`Failed to fetch template from ${url}: ${response.status} ${response.statusText}`);
150
+ }
151
+
152
+ const raw = await response.text();
153
+ const parsed = parseYaml(raw);
154
+
155
+ if (!isRecord(parsed)) {
156
+ throw new Error(`Template from ${url} is not a YAML object`);
157
+ }
158
+
159
+ const inferredName = typeof parsed.name === 'string' ? parsed.name : '';
160
+ const templateName = this.normalizeTemplateName(name ?? inferredName);
161
+
162
+ if (!templateName) {
163
+ throw new Error(
164
+ 'Template name is required. Provide name explicitly or include a string "name" field.'
165
+ );
166
+ }
167
+
168
+ if (templateName.includes('/') || templateName.includes('\\') || templateName.includes('..') || path.isAbsolute(templateName)) {
169
+ throw new Error(`Invalid template name: "${templateName}" contains path separators or traversal sequences`);
170
+ }
171
+
172
+ this.validateRelayConfig(parsed, url);
173
+
174
+ await fs.mkdir(this.customTemplatesDir, { recursive: true });
175
+ const targetPath = path.join(this.customTemplatesDir, `${templateName}.yaml`);
176
+ await fs.writeFile(targetPath, stringifyYaml(parsed), 'utf-8');
177
+ return targetPath;
178
+ }
179
+
180
+ private isTemplateShorthand(
181
+ input: TemplateReferenceInput
182
+ ): input is Partial<Omit<RelayYamlConfig, 'swarm'>> & TemplateShorthandConfig {
183
+ return isRecord(input) && typeof input.swarm === 'string';
184
+ }
185
+
186
+ private mergeRelayConfig(
187
+ base: RelayYamlConfig,
188
+ patch: Partial<Omit<RelayYamlConfig, 'swarm'>>
189
+ ): RelayYamlConfig {
190
+ const merged = this.cloneValue(base);
191
+
192
+ for (const [key, value] of Object.entries(patch)) {
193
+ if (value === undefined) {
194
+ continue;
195
+ }
196
+ (merged as unknown as Record<string, unknown>)[key] = this.cloneValue(value);
197
+ }
198
+
199
+ return merged;
200
+ }
201
+
202
+ private normalizeTemplateName(name: string): string {
203
+ return name.replace(/\.ya?ml$/i, '').trim();
204
+ }
205
+
206
+ private resolveBuiltInTemplatesDir(explicitDir?: string): string {
207
+ if (explicitDir) {
208
+ return path.resolve(explicitDir);
209
+ }
210
+
211
+ const currentDir = path.dirname(fileURLToPath(import.meta.url));
212
+ const candidates = [
213
+ path.resolve(currentDir, 'builtin-templates'),
214
+ path.resolve(currentDir, '../workflows/builtin-templates'),
215
+ ];
216
+
217
+ for (const candidate of candidates) {
218
+ if (existsSync(candidate)) {
219
+ return candidate;
220
+ }
221
+ }
222
+
223
+ return candidates[0];
224
+ }
225
+
226
+ private async resolveTemplatePath(name: string): Promise<string> {
227
+ const normalizedName = this.normalizeTemplateName(name);
228
+
229
+ const customPath = await this.findTemplatePath(this.customTemplatesDir, normalizedName);
230
+ if (customPath) {
231
+ return customPath;
232
+ }
233
+
234
+ const builtInPath = await this.findTemplatePath(this.builtInTemplatesDir, normalizedName);
235
+ if (builtInPath) {
236
+ return builtInPath;
237
+ }
238
+
239
+ throw new Error(`Template not found: ${name}`);
240
+ }
241
+
242
+ private async findTemplatePath(
243
+ directory: string,
244
+ templateName: string
245
+ ): Promise<string | undefined> {
246
+ for (const ext of YAML_EXTENSIONS) {
247
+ const candidate = path.join(directory, `${templateName}${ext}`);
248
+ try {
249
+ const stat = await fs.stat(candidate);
250
+ if (stat.isFile()) {
251
+ return candidate;
252
+ }
253
+ } catch {
254
+ // Continue checking other extensions.
255
+ }
256
+ }
257
+
258
+ return undefined;
259
+ }
260
+
261
+ private async readTemplateFile(templatePath: string): Promise<RelayYamlConfig> {
262
+ const raw = await fs.readFile(templatePath, 'utf-8');
263
+ const parsed = parseYaml(raw);
264
+
265
+ if (!isRecord(parsed)) {
266
+ throw new Error(`Template at ${templatePath} is not a YAML object`);
267
+ }
268
+
269
+ const normalized = this.normalizeLegacyTemplate(parsed);
270
+ this.validateRelayConfig(normalized, templatePath);
271
+ return normalized;
272
+ }
273
+
274
+ private normalizeLegacyTemplate(rawTemplate: Record<string, unknown>): Record<string, unknown> {
275
+ const normalized = this.cloneValue(rawTemplate);
276
+
277
+ if (!isRecord(normalized.swarm) && typeof normalized.pattern === 'string') {
278
+ normalized.swarm = { pattern: normalized.pattern };
279
+ delete normalized.pattern;
280
+ }
281
+
282
+ if (Array.isArray(normalized.agents)) {
283
+ normalized.agents = normalized.agents.map((agent) => {
284
+ if (!isRecord(agent)) {
285
+ return agent;
286
+ }
287
+
288
+ if (typeof agent.name !== 'string' && typeof agent.id === 'string') {
289
+ return { ...agent, name: agent.id };
290
+ }
291
+
292
+ return agent;
293
+ });
294
+ }
295
+
296
+ if (!Array.isArray(normalized.workflows) && isRecord(normalized.workflow)) {
297
+ const workflowName = typeof normalized.name === 'string'
298
+ ? `${normalized.name}-workflow`
299
+ : 'default-workflow';
300
+
301
+ const workflow = normalized.workflow;
302
+ const steps = Array.isArray(workflow.steps)
303
+ ? workflow.steps.map((step) => this.normalizeLegacyStep(step)).filter((step) => step !== null)
304
+ : [];
305
+
306
+ normalized.workflows = [
307
+ {
308
+ name: workflowName,
309
+ description: typeof workflow.description === 'string' ? workflow.description : undefined,
310
+ onError: typeof workflow.onError === 'string' ? workflow.onError : undefined,
311
+ steps,
312
+ },
313
+ ];
314
+
315
+ delete normalized.workflow;
316
+ }
317
+
318
+ return normalized;
319
+ }
320
+
321
+ private normalizeLegacyStep(step: unknown): Record<string, unknown> | null {
322
+ if (!isRecord(step)) {
323
+ return null;
324
+ }
325
+
326
+ const name = typeof step.name === 'string'
327
+ ? step.name
328
+ : typeof step.id === 'string'
329
+ ? step.id
330
+ : undefined;
331
+
332
+ const task = typeof step.task === 'string'
333
+ ? step.task
334
+ : typeof step.prompt === 'string'
335
+ ? step.prompt
336
+ : undefined;
337
+
338
+ if (!name || typeof step.agent !== 'string' || !task) {
339
+ return null;
340
+ }
341
+
342
+ const normalized: Record<string, unknown> = {
343
+ name,
344
+ agent: step.agent,
345
+ task,
346
+ };
347
+
348
+ if (Array.isArray(step.dependsOn)) {
349
+ normalized.dependsOn = step.dependsOn;
350
+ }
351
+
352
+ if (typeof step.timeoutMs === 'number') {
353
+ normalized.timeoutMs = step.timeoutMs;
354
+ }
355
+
356
+ if (typeof step.retries === 'number') {
357
+ normalized.retries = step.retries;
358
+ } else if (typeof step.maxRetries === 'number') {
359
+ normalized.retries = step.maxRetries;
360
+ }
361
+
362
+ if (isRecord(step.verification)) {
363
+ normalized.verification = step.verification;
364
+ } else if (typeof step.expects === 'string') {
365
+ normalized.verification = {
366
+ type: 'output_contains',
367
+ value: step.expects,
368
+ };
369
+ }
370
+
371
+ return normalized;
372
+ }
373
+
374
+ private validateRelayConfig(rawConfig: unknown, source: string): asserts rawConfig is RelayYamlConfig {
375
+ if (!isRecord(rawConfig)) {
376
+ throw new Error(`Template at ${source} is not an object`);
377
+ }
378
+
379
+ if (typeof rawConfig.version !== 'string') {
380
+ throw new Error(`Template at ${source} is missing required string field: version`);
381
+ }
382
+
383
+ if (typeof rawConfig.name !== 'string') {
384
+ throw new Error(`Template at ${source} is missing required string field: name`);
385
+ }
386
+
387
+ if (!isRecord(rawConfig.swarm) || typeof rawConfig.swarm.pattern !== 'string') {
388
+ throw new Error(`Template at ${source} is missing required field: swarm.pattern`);
389
+ }
390
+
391
+ if (!Array.isArray(rawConfig.agents) || rawConfig.agents.length === 0) {
392
+ throw new Error(`Template at ${source} must include a non-empty agents array`);
393
+ }
394
+
395
+ for (const agent of rawConfig.agents) {
396
+ if (!isRecord(agent) || typeof agent.name !== 'string' || typeof agent.cli !== 'string') {
397
+ throw new Error(`Template at ${source} contains an invalid agent definition`);
398
+ }
399
+ }
400
+
401
+ if (rawConfig.workflows !== undefined) {
402
+ if (!Array.isArray(rawConfig.workflows)) {
403
+ throw new Error(`Template at ${source} has invalid workflows; expected an array`);
404
+ }
405
+
406
+ for (const workflow of rawConfig.workflows) {
407
+ if (!isRecord(workflow) || typeof workflow.name !== 'string' || !Array.isArray(workflow.steps)) {
408
+ throw new Error(`Template at ${source} contains an invalid workflow definition`);
409
+ }
410
+
411
+ for (const step of workflow.steps) {
412
+ if (
413
+ !isRecord(step) ||
414
+ typeof step.name !== 'string' ||
415
+ typeof step.agent !== 'string' ||
416
+ typeof step.task !== 'string'
417
+ ) {
418
+ throw new Error(`Template at ${source} contains an invalid workflow step`);
419
+ }
420
+ }
421
+ }
422
+ }
423
+ }
424
+
425
+ private setOverride(
426
+ config: RelayYamlConfig,
427
+ overridePath: string,
428
+ value: unknown
429
+ ): void {
430
+ const pathParts = overridePath
431
+ .replace(/\[(\d+)\]/g, '.$1')
432
+ .split('.')
433
+ .map((part) => part.trim())
434
+ .filter(Boolean);
435
+
436
+ if (pathParts.length === 0) {
437
+ return;
438
+ }
439
+
440
+ if (pathParts[0] === 'steps') {
441
+ const workflow = config.workflows?.[0];
442
+ if (!workflow) {
443
+ throw new Error(`Cannot apply override "${overridePath}": workflows[0] is missing`);
444
+ }
445
+ this.setOnValue(workflow.steps as unknown, pathParts.slice(1), value, overridePath);
446
+ return;
447
+ }
448
+
449
+ if (pathParts[0] === 'workflow' && pathParts[1] === 'steps') {
450
+ const workflow = config.workflows?.[0];
451
+ if (!workflow) {
452
+ throw new Error(`Cannot apply override "${overridePath}": workflows[0] is missing`);
453
+ }
454
+ this.setOnValue(workflow.steps as unknown, pathParts.slice(2), value, overridePath);
455
+ return;
456
+ }
457
+
458
+ this.setOnValue(config as unknown, pathParts, value, overridePath);
459
+ }
460
+
461
+ private setOnValue(
462
+ target: unknown,
463
+ pathParts: string[],
464
+ value: unknown,
465
+ fullPath: string
466
+ ): void {
467
+ if (pathParts.length === 0) {
468
+ throw new Error(`Invalid override path: ${fullPath}`);
469
+ }
470
+
471
+ let current: unknown = target;
472
+
473
+ for (let i = 0; i < pathParts.length - 1; i += 1) {
474
+ const part = pathParts[i];
475
+ const nextPart = pathParts[i + 1];
476
+
477
+ if (Array.isArray(current)) {
478
+ const index = this.resolveArrayItemIndex(current, part);
479
+ if (index < 0) {
480
+ throw new Error(`Cannot apply override "${fullPath}": array item "${part}" was not found`);
481
+ }
482
+ current = current[index];
483
+ continue;
484
+ }
485
+
486
+ if (!isRecord(current)) {
487
+ throw new Error(`Cannot apply override "${fullPath}": segment "${part}" is not an object`);
488
+ }
489
+
490
+ if (!(part in current) || current[part] === undefined || current[part] === null) {
491
+ current[part] = /^\d+$/.test(nextPart) ? [] : {};
492
+ }
493
+
494
+ current = current[part];
495
+ }
496
+
497
+ const finalPart = pathParts[pathParts.length - 1];
498
+
499
+ if (Array.isArray(current)) {
500
+ const index = this.resolveArrayItemIndex(current, finalPart);
501
+ if (index < 0) {
502
+ throw new Error(`Cannot apply override "${fullPath}": array item "${finalPart}" was not found`);
503
+ }
504
+ current[index] = value;
505
+ return;
506
+ }
507
+
508
+ if (!isRecord(current)) {
509
+ throw new Error(`Cannot apply override "${fullPath}": parent object is invalid`);
510
+ }
511
+
512
+ current[finalPart] = value;
513
+ }
514
+
515
+ private resolveArrayItemIndex(items: unknown[], segment: string): number {
516
+ if (/^\d+$/.test(segment)) {
517
+ const index = Number.parseInt(segment, 10);
518
+ return index >= 0 && index < items.length ? index : -1;
519
+ }
520
+
521
+ return items.findIndex(
522
+ (item) =>
523
+ isRecord(item) &&
524
+ ((typeof item.name === 'string' && item.name === segment) ||
525
+ (typeof item.id === 'string' && item.id === segment))
526
+ );
527
+ }
528
+
529
+ private async safeReadDir(directory: string): Promise<string[]> {
530
+ try {
531
+ return await fs.readdir(directory);
532
+ } catch {
533
+ return [];
534
+ }
535
+ }
536
+
537
+ private cloneValue<T>(value: T): T {
538
+ if (typeof structuredClone === 'function') {
539
+ return structuredClone(value);
540
+ }
541
+
542
+ return JSON.parse(JSON.stringify(value)) as T;
543
+ }
544
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Workflow Types for Relay Cloud Swarm Patterns
3
+ *
4
+ * Shared TypeScript types for relay.yaml configuration, workflow execution,
5
+ * and database row representations.
6
+ */
7
+
8
+ // ── relay.yaml top-level config ─────────────────────────────────────────────
9
+
10
+ /** Top-level relay.yaml configuration file structure. */
11
+ export interface RelayYamlConfig {
12
+ version: string;
13
+ name: string;
14
+ description?: string;
15
+ swarm: SwarmConfig;
16
+ agents: AgentDefinition[];
17
+ workflows?: WorkflowDefinition[];
18
+ coordination?: CoordinationConfig;
19
+ state?: StateConfig;
20
+ errorHandling?: ErrorHandlingConfig;
21
+ }
22
+
23
+ // ── Swarm configuration ─────────────────────────────────────────────────────
24
+
25
+ /** Swarm-level settings controlling the overall pattern. */
26
+ export interface SwarmConfig {
27
+ pattern: SwarmPattern;
28
+ maxConcurrency?: number;
29
+ timeoutMs?: number;
30
+ channel?: string;
31
+ }
32
+
33
+ export type SwarmPattern =
34
+ | "fan-out"
35
+ | "pipeline"
36
+ | "hub-spoke"
37
+ | "consensus"
38
+ | "mesh"
39
+ | "handoff"
40
+ | "cascade"
41
+ | "dag"
42
+ | "debate"
43
+ | "hierarchical";
44
+
45
+ // ── Agent definitions ───────────────────────────────────────────────────────
46
+
47
+ /** Definition of an agent participating in a workflow. */
48
+ export interface AgentDefinition {
49
+ name: string;
50
+ cli: AgentCli;
51
+ role?: string;
52
+ task?: string;
53
+ channels?: string[];
54
+ constraints?: AgentConstraints;
55
+ }
56
+
57
+ export type AgentCli = "claude" | "codex" | "gemini" | "aider" | "goose";
58
+
59
+ /** Resource and behavioral constraints for an agent. */
60
+ export interface AgentConstraints {
61
+ maxTokens?: number;
62
+ timeoutMs?: number;
63
+ retries?: number;
64
+ model?: string;
65
+ }
66
+
67
+ // ── Workflow definitions ────────────────────────────────────────────────────
68
+
69
+ /** A named workflow composed of sequential or parallel steps. */
70
+ export interface WorkflowDefinition {
71
+ name: string;
72
+ description?: string;
73
+ steps: WorkflowStep[];
74
+ onError?: "fail" | "skip" | "retry";
75
+ }
76
+
77
+ /** A single step within a workflow. */
78
+ export interface WorkflowStep {
79
+ name: string;
80
+ agent: string;
81
+ task: string;
82
+ dependsOn?: string[];
83
+ verification?: VerificationCheck;
84
+ timeoutMs?: number;
85
+ retries?: number;
86
+ }
87
+
88
+ /** Verification check to validate a step's output. */
89
+ export interface VerificationCheck {
90
+ type: "output_contains" | "exit_code" | "file_exists" | "custom";
91
+ value: string;
92
+ description?: string;
93
+ }
94
+
95
+ // ── Coordination ────────────────────────────────────────────────────────────
96
+
97
+ /** Coordination settings for multi-agent synchronization. */
98
+ export interface CoordinationConfig {
99
+ barriers?: Barrier[];
100
+ votingThreshold?: number;
101
+ consensusStrategy?: "majority" | "unanimous" | "quorum";
102
+ }
103
+
104
+ /** A synchronization barrier that gates downstream work. */
105
+ export interface Barrier {
106
+ name: string;
107
+ waitFor: string[];
108
+ timeoutMs?: number;
109
+ }
110
+
111
+ // ── State management ────────────────────────────────────────────────────────
112
+
113
+ /** Shared state configuration for workflows. */
114
+ export interface StateConfig {
115
+ backend: "memory" | "redis" | "database";
116
+ ttlMs?: number;
117
+ namespace?: string;
118
+ }
119
+
120
+ // ── Error handling ──────────────────────────────────────────────────────────
121
+
122
+ /** Global error handling configuration. */
123
+ export interface ErrorHandlingConfig {
124
+ strategy: "fail-fast" | "continue" | "retry";
125
+ maxRetries?: number;
126
+ retryDelayMs?: number;
127
+ notifyChannel?: string;
128
+ }
129
+
130
+ // ── Database row types ──────────────────────────────────────────────────────
131
+
132
+ export type WorkflowRunStatus =
133
+ | "pending"
134
+ | "running"
135
+ | "completed"
136
+ | "failed"
137
+ | "cancelled";
138
+
139
+ /** Database row representing a workflow run. */
140
+ export interface WorkflowRunRow {
141
+ id: string;
142
+ workspaceId: string;
143
+ workflowName: string;
144
+ pattern: SwarmPattern;
145
+ status: WorkflowRunStatus;
146
+ config: RelayYamlConfig;
147
+ stateSnapshot?: Record<string, unknown>;
148
+ startedAt: string;
149
+ completedAt?: string;
150
+ error?: string;
151
+ createdAt: string;
152
+ updatedAt: string;
153
+ }
154
+
155
+ export type WorkflowStepStatus =
156
+ | "pending"
157
+ | "running"
158
+ | "completed"
159
+ | "failed"
160
+ | "skipped";
161
+
162
+ /** Database row representing a single workflow step execution. */
163
+ export interface WorkflowStepRow {
164
+ id: string;
165
+ runId: string;
166
+ stepName: string;
167
+ agentName: string;
168
+ status: WorkflowStepStatus;
169
+ task: string;
170
+ dependsOn: string[];
171
+ output?: string;
172
+ error?: string;
173
+ startedAt?: string;
174
+ completedAt?: string;
175
+ retryCount: number;
176
+ createdAt: string;
177
+ updatedAt: string;
178
+ }