@elie-laloum/outpost 3.0.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (411) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +5 -3
  3. package/SECURITY.md +3 -1
  4. package/dist/adapters/agents/codex-adapter.js +2 -0
  5. package/dist/adapters/agents/codex-adapter.js.map +1 -1
  6. package/dist/adapters/agents/codex-provider.d.ts +2 -0
  7. package/dist/adapters/agents/codex-provider.js +32 -0
  8. package/dist/adapters/agents/codex-provider.js.map +1 -0
  9. package/dist/adapters/agents/codex-request.js +2 -1
  10. package/dist/adapters/agents/codex-request.js.map +1 -1
  11. package/dist/adapters/agents/gemini-adapter.d.ts +3 -0
  12. package/dist/adapters/agents/gemini-adapter.js +15 -0
  13. package/dist/adapters/agents/gemini-adapter.js.map +1 -0
  14. package/dist/adapters/agents/gemini-diagnostics.d.ts +2 -0
  15. package/dist/adapters/agents/gemini-diagnostics.js +15 -0
  16. package/dist/adapters/agents/gemini-diagnostics.js.map +1 -0
  17. package/dist/adapters/agents/gemini-events.d.ts +2 -0
  18. package/dist/adapters/agents/gemini-events.js +50 -0
  19. package/dist/adapters/agents/gemini-events.js.map +1 -0
  20. package/dist/adapters/agents/gemini-request.d.ts +4 -0
  21. package/dist/adapters/agents/gemini-request.js +23 -0
  22. package/dist/adapters/agents/gemini-request.js.map +1 -0
  23. package/dist/adapters/agents/gemini.types.d.ts +6 -0
  24. package/dist/adapters/agents/gemini.types.js +2 -0
  25. package/dist/adapters/agents/gemini.types.js.map +1 -0
  26. package/dist/adapters/agents/protocol-fixtures.constants.d.ts +1 -1
  27. package/dist/adapters/agents/protocol-fixtures.constants.js +37 -0
  28. package/dist/adapters/agents/protocol-fixtures.constants.js.map +1 -1
  29. package/dist/adapters/agents/settings.types.d.ts +5 -0
  30. package/dist/adapters/agents/settings.types.js.map +1 -1
  31. package/dist/application/agent-bootstrap.constants.d.ts +1 -0
  32. package/dist/application/agent-bootstrap.constants.js +1 -0
  33. package/dist/application/agent-bootstrap.constants.js.map +1 -1
  34. package/dist/application/agent-bootstrap.js +6 -2
  35. package/dist/application/agent-bootstrap.js.map +1 -1
  36. package/dist/application/agent-output.js +9 -2
  37. package/dist/application/agent-output.js.map +1 -1
  38. package/dist/application/artifact-tasks.d.ts +5 -0
  39. package/dist/application/artifact-tasks.js +31 -0
  40. package/dist/application/artifact-tasks.js.map +1 -0
  41. package/dist/application/artifact-tasks.types.d.ts +8 -0
  42. package/dist/application/artifact-tasks.types.js +2 -0
  43. package/dist/application/artifact-tasks.types.js.map +1 -0
  44. package/dist/application/dispatch-validation.js +2 -0
  45. package/dist/application/dispatch-validation.js.map +1 -1
  46. package/dist/application/doctor-agent.constants.d.ts +2 -0
  47. package/dist/application/doctor-agent.constants.js +2 -0
  48. package/dist/application/doctor-agent.constants.js.map +1 -1
  49. package/dist/application/doctor-agent.js +1 -1
  50. package/dist/application/doctor-agent.js.map +1 -1
  51. package/dist/application/doctor-protocol.js +2 -1
  52. package/dist/application/doctor-protocol.js.map +1 -1
  53. package/dist/application/doctor.constants.js +1 -1
  54. package/dist/application/doctor.constants.js.map +1 -1
  55. package/dist/application/doctor.types.d.ts +1 -1
  56. package/dist/application/doctor.types.js.map +1 -1
  57. package/dist/application/outpost.types.d.ts +2 -0
  58. package/dist/application/outpost.types.js.map +1 -1
  59. package/dist/application/queue-worker.d.ts +2 -0
  60. package/dist/application/queue-worker.js +75 -0
  61. package/dist/application/queue-worker.js.map +1 -0
  62. package/dist/application/queue-worker.types.d.ts +15 -0
  63. package/dist/application/queue-worker.types.js +2 -0
  64. package/dist/application/queue-worker.types.js.map +1 -0
  65. package/dist/application/queued-task.d.ts +3 -0
  66. package/dist/application/queued-task.js +56 -0
  67. package/dist/application/queued-task.js.map +1 -0
  68. package/dist/application/queued-task.types.d.ts +11 -0
  69. package/dist/application/queued-task.types.js +2 -0
  70. package/dist/application/queued-task.types.js.map +1 -0
  71. package/dist/application/recovery-inspection.js +5 -0
  72. package/dist/application/recovery-inspection.js.map +1 -1
  73. package/dist/application/recovery-inspection.types.d.ts +3 -0
  74. package/dist/application/recovery-inspection.types.js.map +1 -1
  75. package/dist/application/recovery-restore-snapshot.d.ts +2 -0
  76. package/dist/application/recovery-restore-snapshot.js +57 -0
  77. package/dist/application/recovery-restore-snapshot.js.map +1 -0
  78. package/dist/application/recovery-restore.d.ts +3 -0
  79. package/dist/application/recovery-restore.js +161 -0
  80. package/dist/application/recovery-restore.js.map +1 -0
  81. package/dist/application/recovery-restore.types.d.ts +28 -0
  82. package/dist/application/recovery-restore.types.js +2 -0
  83. package/dist/application/recovery-restore.types.js.map +1 -0
  84. package/dist/application/recovery-retention.js +5 -0
  85. package/dist/application/recovery-retention.js.map +1 -1
  86. package/dist/application/recovery-verification.d.ts +2 -1
  87. package/dist/application/recovery-verification.js +1 -1
  88. package/dist/application/recovery-verification.js.map +1 -1
  89. package/dist/application/remote-apply.js +6 -0
  90. package/dist/application/remote-apply.js.map +1 -1
  91. package/dist/application/remote-download.js +2 -2
  92. package/dist/application/remote-download.js.map +1 -1
  93. package/dist/application/remote-history.d.ts +6 -0
  94. package/dist/application/remote-history.js +114 -0
  95. package/dist/application/remote-history.js.map +1 -0
  96. package/dist/application/remote-upload.d.ts +2 -0
  97. package/dist/application/remote-upload.js +17 -0
  98. package/dist/application/remote-upload.js.map +1 -0
  99. package/dist/application/remote-validation.js +20 -28
  100. package/dist/application/remote-validation.js.map +1 -1
  101. package/dist/application/remote-workspace.js +4 -10
  102. package/dist/application/remote-workspace.js.map +1 -1
  103. package/dist/application/sandbox-activity.d.ts +3 -0
  104. package/dist/application/sandbox-activity.js +25 -0
  105. package/dist/application/sandbox-activity.js.map +1 -0
  106. package/dist/application/sandbox-provision.js +55 -10
  107. package/dist/application/sandbox-provision.js.map +1 -1
  108. package/dist/application/sandbox-session.types.d.ts +2 -0
  109. package/dist/application/sandbox-session.types.js.map +1 -1
  110. package/dist/application/sandbox.js +23 -11
  111. package/dist/application/sandbox.js.map +1 -1
  112. package/dist/application/speculation-host.d.ts +2 -0
  113. package/dist/application/speculation-host.js +30 -0
  114. package/dist/application/speculation-host.js.map +1 -0
  115. package/dist/application/speculation.constants.d.ts +4 -0
  116. package/dist/application/speculation.constants.js +2 -0
  117. package/dist/application/speculation.constants.js.map +1 -0
  118. package/dist/application/speculation.d.ts +2 -0
  119. package/dist/application/speculation.js +166 -0
  120. package/dist/application/speculation.js.map +1 -0
  121. package/dist/application/speculation.types.d.ts +56 -0
  122. package/dist/application/speculation.types.js +2 -0
  123. package/dist/application/speculation.types.js.map +1 -0
  124. package/dist/application/storage-reservation.d.ts +3 -0
  125. package/dist/application/storage-reservation.js +10 -0
  126. package/dist/application/storage-reservation.js.map +1 -0
  127. package/dist/application/storage-reservation.types.d.ts +4 -0
  128. package/dist/application/storage-reservation.types.js +2 -0
  129. package/dist/application/storage-reservation.types.js.map +1 -0
  130. package/dist/application/task-usage.d.ts +1 -1
  131. package/dist/application/task-usage.js.map +1 -1
  132. package/dist/application/tasks.js +1 -1
  133. package/dist/application/tasks.js.map +1 -1
  134. package/dist/application/tasks.types.d.ts +4 -3
  135. package/dist/application/tasks.types.js.map +1 -1
  136. package/dist/application/workspace-allocation.d.ts +3 -0
  137. package/dist/application/workspace-allocation.js +34 -0
  138. package/dist/application/workspace-allocation.js.map +1 -0
  139. package/dist/application/workspace.js +2 -2
  140. package/dist/application/workspace.js.map +1 -1
  141. package/dist/cli/commands.js +55 -18
  142. package/dist/cli/commands.js.map +1 -1
  143. package/dist/cli/doctor-command.js +1 -1
  144. package/dist/cli/doctor-command.js.map +1 -1
  145. package/dist/cli/init-authentication.constants.d.ts +13 -0
  146. package/dist/cli/init-authentication.constants.js +10 -0
  147. package/dist/cli/init-authentication.constants.js.map +1 -0
  148. package/dist/cli/init-authentication.d.ts +4 -0
  149. package/dist/cli/init-authentication.js +43 -0
  150. package/dist/cli/init-authentication.js.map +1 -0
  151. package/dist/cli/init-command.js +74 -15
  152. package/dist/cli/init-command.js.map +1 -1
  153. package/dist/cli/main.constants.d.ts +111 -2
  154. package/dist/cli/main.constants.js +148 -42
  155. package/dist/cli/main.constants.js.map +1 -1
  156. package/dist/cli/recovery-command.js +28 -4
  157. package/dist/cli/recovery-command.js.map +1 -1
  158. package/dist/cli/recovery-restore-command.d.ts +2 -0
  159. package/dist/cli/recovery-restore-command.js +34 -0
  160. package/dist/cli/recovery-restore-command.js.map +1 -0
  161. package/dist/cli/scaffold-files.js +3 -2
  162. package/dist/cli/scaffold-files.js.map +1 -1
  163. package/dist/cli/scaffold-validation.js +20 -1
  164. package/dist/cli/scaffold-validation.js.map +1 -1
  165. package/dist/cli/scaffold.constants.js +2 -2
  166. package/dist/cli/scaffold.constants.js.map +1 -1
  167. package/dist/cli/scaffold.js +13 -0
  168. package/dist/cli/scaffold.js.map +1 -1
  169. package/dist/cli/scaffold.types.d.ts +4 -1
  170. package/dist/cli/scaffold.types.js.map +1 -1
  171. package/dist/cli/starters.js +9 -2
  172. package/dist/cli/starters.js.map +1 -1
  173. package/dist/domain/agent.types.d.ts +2 -0
  174. package/dist/domain/agent.types.js.map +1 -1
  175. package/dist/domain/artifact-reference.d.ts +4 -0
  176. package/dist/domain/artifact-reference.js +90 -0
  177. package/dist/domain/artifact-reference.js.map +1 -0
  178. package/dist/domain/artifact.constants.d.ts +2 -0
  179. package/dist/domain/artifact.constants.js +3 -0
  180. package/dist/domain/artifact.constants.js.map +1 -0
  181. package/dist/domain/artifact.d.ts +7 -0
  182. package/dist/domain/artifact.js +104 -0
  183. package/dist/domain/artifact.js.map +1 -0
  184. package/dist/domain/artifact.types.d.ts +44 -0
  185. package/dist/domain/artifact.types.js +2 -0
  186. package/dist/domain/artifact.types.js.map +1 -0
  187. package/dist/domain/egress.constants.d.ts +1 -0
  188. package/dist/domain/egress.constants.js +7 -0
  189. package/dist/domain/egress.constants.js.map +1 -0
  190. package/dist/domain/egress.d.ts +2 -0
  191. package/dist/domain/egress.js +48 -0
  192. package/dist/domain/egress.js.map +1 -0
  193. package/dist/domain/egress.types.d.ts +8 -0
  194. package/dist/domain/egress.types.js +2 -0
  195. package/dist/domain/egress.types.js.map +1 -0
  196. package/dist/domain/sandbox.types.d.ts +1 -0
  197. package/dist/domain/sandbox.types.js.map +1 -1
  198. package/dist/domain/task-queue.constants.d.ts +8 -0
  199. package/dist/domain/task-queue.constants.js +9 -0
  200. package/dist/domain/task-queue.constants.js.map +1 -0
  201. package/dist/domain/task-queue.d.ts +11 -0
  202. package/dist/domain/task-queue.js +105 -0
  203. package/dist/domain/task-queue.js.map +1 -0
  204. package/dist/domain/task-queue.types.d.ts +41 -0
  205. package/dist/domain/task-queue.types.js +2 -0
  206. package/dist/domain/task-queue.types.js.map +1 -0
  207. package/dist/domain/workflow/budget.d.ts +2 -2
  208. package/dist/domain/workflow/budget.js +5 -3
  209. package/dist/domain/workflow/budget.js.map +1 -1
  210. package/dist/domain/workflow/checkpoint-validation.d.ts +3 -0
  211. package/dist/domain/workflow/checkpoint-validation.js +81 -0
  212. package/dist/domain/workflow/checkpoint-validation.js.map +1 -0
  213. package/dist/domain/workflow/checkpoint-value.d.ts +2 -0
  214. package/dist/domain/workflow/checkpoint-value.js +49 -0
  215. package/dist/domain/workflow/checkpoint-value.js.map +1 -0
  216. package/dist/domain/workflow/checkpoint.d.ts +3 -0
  217. package/dist/domain/workflow/checkpoint.js +70 -0
  218. package/dist/domain/workflow/checkpoint.js.map +1 -0
  219. package/dist/domain/workflow/checkpoint.types.d.ts +40 -0
  220. package/dist/domain/workflow/checkpoint.types.js +2 -0
  221. package/dist/domain/workflow/checkpoint.types.js.map +1 -0
  222. package/dist/domain/workflow/gate-validation.d.ts +4 -0
  223. package/dist/domain/workflow/gate-validation.js +71 -0
  224. package/dist/domain/workflow/gate-validation.js.map +1 -0
  225. package/dist/domain/workflow/gates.constants.d.ts +4 -0
  226. package/dist/domain/workflow/gates.constants.js +5 -0
  227. package/dist/domain/workflow/gates.constants.js.map +1 -0
  228. package/dist/domain/workflow/gates.d.ts +7 -0
  229. package/dist/domain/workflow/gates.js +85 -0
  230. package/dist/domain/workflow/gates.js.map +1 -0
  231. package/dist/domain/workflow/gates.types.d.ts +27 -0
  232. package/dist/domain/workflow/gates.types.js +2 -0
  233. package/dist/domain/workflow/gates.types.js.map +1 -0
  234. package/dist/domain/workflow/task-runner.js +14 -2
  235. package/dist/domain/workflow/task-runner.js.map +1 -1
  236. package/dist/domain/workflow/usage-receipt.constants.d.ts +2 -0
  237. package/dist/domain/workflow/usage-receipt.constants.js +3 -0
  238. package/dist/domain/workflow/usage-receipt.constants.js.map +1 -0
  239. package/dist/domain/workflow/usage-receipt.d.ts +2 -0
  240. package/dist/domain/workflow/usage-receipt.js +18 -0
  241. package/dist/domain/workflow/usage-receipt.js.map +1 -0
  242. package/dist/domain/workflow/validation.js +6 -0
  243. package/dist/domain/workflow/validation.js.map +1 -1
  244. package/dist/domain/workflow/workflow-scheduler.js +65 -32
  245. package/dist/domain/workflow/workflow-scheduler.js.map +1 -1
  246. package/dist/domain/workflow/workflow-state.d.ts +2 -1
  247. package/dist/domain/workflow/workflow-state.js +91 -16
  248. package/dist/domain/workflow/workflow-state.js.map +1 -1
  249. package/dist/domain/workflow.types.d.ts +13 -2
  250. package/dist/domain/workflow.types.js.map +1 -1
  251. package/dist/index.d.ts +32 -2
  252. package/dist/index.js +14 -1
  253. package/dist/index.js.map +1 -1
  254. package/dist/infrastructure/artifact-store.constants.d.ts +1 -0
  255. package/dist/infrastructure/artifact-store.constants.js +2 -0
  256. package/dist/infrastructure/artifact-store.constants.js.map +1 -0
  257. package/dist/infrastructure/artifact-store.d.ts +3 -0
  258. package/dist/infrastructure/artifact-store.js +100 -0
  259. package/dist/infrastructure/artifact-store.js.map +1 -0
  260. package/dist/infrastructure/artifact-store.types.d.ts +4 -0
  261. package/dist/infrastructure/artifact-store.types.js +2 -0
  262. package/dist/infrastructure/artifact-store.types.js.map +1 -0
  263. package/dist/infrastructure/file-manifest.d.ts +1 -1
  264. package/dist/infrastructure/file-manifest.js +3 -2
  265. package/dist/infrastructure/file-manifest.js.map +1 -1
  266. package/dist/infrastructure/git/verification-command.d.ts +1 -1
  267. package/dist/infrastructure/git/verification-command.js +3 -2
  268. package/dist/infrastructure/git/verification-command.js.map +1 -1
  269. package/dist/infrastructure/opentelemetry.js +1 -1
  270. package/dist/infrastructure/opentelemetry.js.map +1 -1
  271. package/dist/infrastructure/resource-activity-inspection.d.ts +2 -0
  272. package/dist/infrastructure/resource-activity-inspection.js +152 -0
  273. package/dist/infrastructure/resource-activity-inspection.js.map +1 -0
  274. package/dist/infrastructure/resource-activity.constants.d.ts +8 -0
  275. package/dist/infrastructure/resource-activity.constants.js +26 -0
  276. package/dist/infrastructure/resource-activity.constants.js.map +1 -0
  277. package/dist/infrastructure/resource-activity.d.ts +2 -0
  278. package/dist/infrastructure/resource-activity.js +166 -0
  279. package/dist/infrastructure/resource-activity.js.map +1 -0
  280. package/dist/infrastructure/resource-activity.types.d.ts +53 -0
  281. package/dist/infrastructure/resource-activity.types.js +2 -0
  282. package/dist/infrastructure/resource-activity.types.js.map +1 -0
  283. package/dist/infrastructure/storage-mutation-lock.constants.d.ts +5 -0
  284. package/dist/infrastructure/storage-mutation-lock.constants.js +6 -0
  285. package/dist/infrastructure/storage-mutation-lock.constants.js.map +1 -0
  286. package/dist/infrastructure/storage-mutation-lock.d.ts +1 -0
  287. package/dist/infrastructure/storage-mutation-lock.js +21 -0
  288. package/dist/infrastructure/storage-mutation-lock.js.map +1 -0
  289. package/dist/infrastructure/storage-reservations.constants.d.ts +4 -0
  290. package/dist/infrastructure/storage-reservations.constants.js +5 -0
  291. package/dist/infrastructure/storage-reservations.constants.js.map +1 -0
  292. package/dist/infrastructure/storage-reservations.d.ts +2 -0
  293. package/dist/infrastructure/storage-reservations.js +150 -0
  294. package/dist/infrastructure/storage-reservations.js.map +1 -0
  295. package/dist/infrastructure/storage-reservations.types.d.ts +21 -0
  296. package/dist/infrastructure/storage-reservations.types.js +2 -0
  297. package/dist/infrastructure/storage-reservations.types.js.map +1 -0
  298. package/dist/infrastructure/task-queue-http.constants.d.ts +2 -0
  299. package/dist/infrastructure/task-queue-http.constants.js +3 -0
  300. package/dist/infrastructure/task-queue-http.constants.js.map +1 -0
  301. package/dist/infrastructure/task-queue-http.d.ts +4 -0
  302. package/dist/infrastructure/task-queue-http.js +158 -0
  303. package/dist/infrastructure/task-queue-http.js.map +1 -0
  304. package/dist/infrastructure/task-queue-http.types.d.ts +16 -0
  305. package/dist/infrastructure/task-queue-http.types.js +2 -0
  306. package/dist/infrastructure/task-queue-http.types.js.map +1 -0
  307. package/dist/infrastructure/task-queue.d.ts +2 -0
  308. package/dist/infrastructure/task-queue.js +134 -0
  309. package/dist/infrastructure/task-queue.js.map +1 -0
  310. package/dist/infrastructure/transfer.js +5 -0
  311. package/dist/infrastructure/transfer.js.map +1 -1
  312. package/dist/infrastructure/workflow-checkpoint.constants.d.ts +1 -0
  313. package/dist/infrastructure/workflow-checkpoint.constants.js +2 -0
  314. package/dist/infrastructure/workflow-checkpoint.constants.js.map +1 -0
  315. package/dist/infrastructure/workflow-checkpoint.d.ts +3 -0
  316. package/dist/infrastructure/workflow-checkpoint.js +77 -0
  317. package/dist/infrastructure/workflow-checkpoint.js.map +1 -0
  318. package/dist/infrastructure/workflow-checkpoint.types.d.ts +4 -0
  319. package/dist/infrastructure/workflow-checkpoint.types.js +2 -0
  320. package/dist/infrastructure/workflow-checkpoint.types.js.map +1 -0
  321. package/dist/providers/agents.d.ts +3 -1
  322. package/dist/providers/agents.js +1 -0
  323. package/dist/providers/agents.js.map +1 -1
  324. package/dist/providers/container-isolation.d.ts +2 -0
  325. package/dist/providers/container-isolation.js +29 -0
  326. package/dist/providers/container-isolation.js.map +1 -0
  327. package/dist/providers/container-mounts.js +7 -2
  328. package/dist/providers/container-mounts.js.map +1 -1
  329. package/dist/providers/container-network.d.ts +2 -0
  330. package/dist/providers/container-network.js +14 -0
  331. package/dist/providers/container-network.js.map +1 -0
  332. package/dist/providers/container-plan.js +4 -2
  333. package/dist/providers/container-plan.js.map +1 -1
  334. package/dist/providers/container.constants.d.ts +1 -0
  335. package/dist/providers/container.constants.js +1 -0
  336. package/dist/providers/container.constants.js.map +1 -1
  337. package/dist/providers/container.js +19 -2
  338. package/dist/providers/container.js.map +1 -1
  339. package/dist/providers/container.types.d.ts +3 -0
  340. package/dist/providers/container.types.js.map +1 -1
  341. package/dist/providers/daytona-command.constants.d.ts +2 -0
  342. package/dist/providers/daytona-command.constants.js +13 -0
  343. package/dist/providers/daytona-command.constants.js.map +1 -0
  344. package/dist/providers/daytona-command.js +12 -5
  345. package/dist/providers/daytona-command.js.map +1 -1
  346. package/dist/providers/daytona-output.d.ts +4 -0
  347. package/dist/providers/daytona-output.js +37 -0
  348. package/dist/providers/daytona-output.js.map +1 -0
  349. package/dist/providers/daytona-terminal.d.ts +3 -0
  350. package/dist/providers/daytona-terminal.js +130 -0
  351. package/dist/providers/daytona-terminal.js.map +1 -0
  352. package/dist/providers/daytona.js +2 -0
  353. package/dist/providers/daytona.js.map +1 -1
  354. package/dist/providers/docker.d.ts +1 -0
  355. package/dist/providers/docker.js.map +1 -1
  356. package/dist/providers/file-batches.d.ts +1 -1
  357. package/dist/providers/file-batches.js +9 -0
  358. package/dist/providers/file-batches.js.map +1 -1
  359. package/dist/providers/file-upload.constants.d.ts +1 -0
  360. package/dist/providers/file-upload.constants.js +68 -0
  361. package/dist/providers/file-upload.constants.js.map +1 -0
  362. package/dist/providers/file-upload.d.ts +2 -0
  363. package/dist/providers/file-upload.js +146 -0
  364. package/dist/providers/file-upload.js.map +1 -0
  365. package/dist/providers/firecracker-command.d.ts +5 -0
  366. package/dist/providers/firecracker-command.js +114 -0
  367. package/dist/providers/firecracker-command.js.map +1 -0
  368. package/dist/providers/firecracker-files.constants.d.ts +1 -0
  369. package/dist/providers/firecracker-files.constants.js +21 -0
  370. package/dist/providers/firecracker-files.constants.js.map +1 -0
  371. package/dist/providers/firecracker-files.d.ts +3 -0
  372. package/dist/providers/firecracker-files.js +110 -0
  373. package/dist/providers/firecracker-files.js.map +1 -0
  374. package/dist/providers/firecracker-machine.d.ts +3 -0
  375. package/dist/providers/firecracker-machine.js +155 -0
  376. package/dist/providers/firecracker-machine.js.map +1 -0
  377. package/dist/providers/firecracker.constants.d.ts +10 -0
  378. package/dist/providers/firecracker.constants.js +11 -0
  379. package/dist/providers/firecracker.constants.js.map +1 -0
  380. package/dist/providers/firecracker.d.ts +4 -0
  381. package/dist/providers/firecracker.js +103 -0
  382. package/dist/providers/firecracker.js.map +1 -0
  383. package/dist/providers/firecracker.types.d.ts +36 -0
  384. package/dist/providers/firecracker.types.js +2 -0
  385. package/dist/providers/firecracker.types.js.map +1 -0
  386. package/dist/providers/local.js +2 -1
  387. package/dist/providers/local.js.map +1 -1
  388. package/dist/providers/podman.d.ts +1 -0
  389. package/dist/providers/podman.js.map +1 -1
  390. package/dist/providers/terminal-bridge.d.ts +14 -0
  391. package/dist/providers/terminal-bridge.js +100 -0
  392. package/dist/providers/terminal-bridge.js.map +1 -0
  393. package/dist/providers/vercel-command.js +2 -2
  394. package/dist/providers/vercel-command.js.map +1 -1
  395. package/dist/providers/vercel-directory.d.ts +2 -0
  396. package/dist/providers/vercel-directory.js +7 -0
  397. package/dist/providers/vercel-directory.js.map +1 -0
  398. package/dist/providers/vercel-files.js +3 -2
  399. package/dist/providers/vercel-files.js.map +1 -1
  400. package/dist/providers/vercel-network.d.ts +2 -0
  401. package/dist/providers/vercel-network.js +18 -0
  402. package/dist/providers/vercel-network.js.map +1 -0
  403. package/dist/providers/vercel.d.ts +1 -0
  404. package/dist/providers/vercel.js +5 -1
  405. package/dist/providers/vercel.js.map +1 -1
  406. package/dist/providers/vercel.types.d.ts +2 -0
  407. package/dist/providers/vercel.types.js.map +1 -1
  408. package/dist/providers/versions.constants.d.ts +1 -0
  409. package/dist/providers/versions.constants.js +1 -0
  410. package/dist/providers/versions.constants.js.map +1 -1
  411. package/package.json +10 -2
@@ -0,0 +1,70 @@
1
+ import { createHash } from "node:crypto";
2
+ import { checkpointValue } from "./checkpoint-value.js";
3
+ import { validateCheckpoint } from "./checkpoint-validation.js";
4
+ export async function openCheckpoint(name, tasks, options) {
5
+ if (!options.runId.trim() || !options.version.trim())
6
+ throw new Error("Checkpoint runId and version must not be empty");
7
+ const graph = tasks
8
+ .map((item) => ({
9
+ key: item.key,
10
+ ...(item.gate ? { gate: item.gate } : {}),
11
+ after: item.after.map((dependency) => dependency.key).sort(),
12
+ timeoutMs: item.timeoutMs,
13
+ retry: item.retry?.attempts,
14
+ delayMs: item.retry?.delayMs,
15
+ condition: !!item.condition,
16
+ accepts: !!item.retry?.accepts,
17
+ }))
18
+ .sort((a, b) => {
19
+ if (a.key === b.key)
20
+ return 0;
21
+ return a.key < b.key ? -1 : 1;
22
+ });
23
+ const identity = createHash("sha256")
24
+ .update(JSON.stringify({ name, version: options.version, graph }))
25
+ .digest("hex");
26
+ const lease = await options.store.acquire(options.runId);
27
+ try {
28
+ const saved = await lease.read();
29
+ let initial;
30
+ if (saved !== undefined) {
31
+ validateCheckpoint(saved, identity, tasks);
32
+ initial = saved;
33
+ const settledGate = saved.records.some((record) => ["paused", "rejected"].includes(record.status));
34
+ if (saved.records.some((record) => !["done", "skipped", "paused", "rejected"].includes(record.status) &&
35
+ !(settledGate &&
36
+ record.status === "waiting" &&
37
+ record.attempts === 0)) &&
38
+ options.resume !== "retry-incomplete")
39
+ throw new Error("Incomplete workflow checkpoint: resume retry-incomplete must explicitly authorize replay");
40
+ }
41
+ let writes = Promise.resolve();
42
+ return {
43
+ initial,
44
+ save(state) {
45
+ const snapshot = {
46
+ format: 1,
47
+ identity,
48
+ executionId: state.executionId,
49
+ records: [...state.records.values()].map((record) => ({ ...record })),
50
+ values: Object.fromEntries([...state.values].map(([item, value]) => [
51
+ item.key,
52
+ checkpointValue(value),
53
+ ])),
54
+ usage: state.accounting.snapshot(),
55
+ };
56
+ writes = writes.then(() => lease.write(snapshot));
57
+ return writes;
58
+ },
59
+ async release() {
60
+ await writes.catch(() => { });
61
+ await lease.release();
62
+ },
63
+ };
64
+ }
65
+ catch (error) {
66
+ await lease.release();
67
+ throw error;
68
+ }
69
+ }
70
+ //# sourceMappingURL=checkpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint.js","sourceRoot":"","sources":["../../../src/domain/workflow/checkpoint.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { Task, WorkflowExecutionState } from \"../workflow.types.ts\";\nimport type {\n WorkflowCheckpoint,\n WorkflowCheckpointOptions,\n WorkflowCheckpointSession,\n} from \"./checkpoint.types.ts\";\nimport { checkpointValue } from \"./checkpoint-value.ts\";\nimport { validateCheckpoint } from \"./checkpoint-validation.ts\";\n\nexport async function openCheckpoint(\n name: string,\n tasks: readonly Task[],\n options: WorkflowCheckpointOptions,\n): Promise<WorkflowCheckpointSession> {\n if (!options.runId.trim() || !options.version.trim())\n throw new Error(\"Checkpoint runId and version must not be empty\");\n const graph = tasks\n .map((item) => ({\n key: item.key,\n ...(item.gate ? { gate: item.gate } : {}),\n after: item.after.map((dependency) => dependency.key).sort(),\n timeoutMs: item.timeoutMs,\n retry: item.retry?.attempts,\n delayMs: item.retry?.delayMs,\n condition: !!item.condition,\n accepts: !!item.retry?.accepts,\n }))\n .sort((a, b) => {\n if (a.key === b.key) return 0;\n return a.key < b.key ? -1 : 1;\n });\n const identity = createHash(\"sha256\")\n .update(JSON.stringify({ name, version: options.version, graph }))\n .digest(\"hex\");\n const lease = await options.store.acquire(options.runId);\n try {\n const saved = await lease.read();\n let initial: WorkflowCheckpoint | undefined;\n if (saved !== undefined) {\n validateCheckpoint(saved, identity, tasks);\n initial = saved;\n const settledGate = saved.records.some((record) =>\n [\"paused\", \"rejected\"].includes(record.status),\n );\n if (\n saved.records.some(\n (record) =>\n ![\"done\", \"skipped\", \"paused\", \"rejected\"].includes(\n record.status,\n ) &&\n !(\n settledGate &&\n record.status === \"waiting\" &&\n record.attempts === 0\n ),\n ) &&\n options.resume !== \"retry-incomplete\"\n )\n throw new Error(\n \"Incomplete workflow checkpoint: resume retry-incomplete must explicitly authorize replay\",\n );\n }\n let writes = Promise.resolve();\n return {\n initial,\n save(state: WorkflowExecutionState) {\n const snapshot: WorkflowCheckpoint = {\n format: 1,\n identity,\n executionId: state.executionId,\n records: [...state.records.values()].map((record) => ({ ...record })),\n values: Object.fromEntries(\n [...state.values].map(([item, value]) => [\n item.key,\n checkpointValue(value),\n ]),\n ),\n usage: state.accounting.snapshot(),\n };\n writes = writes.then(() => lease.write(snapshot));\n return writes;\n },\n async release() {\n await writes.catch(() => {});\n await lease.release();\n },\n };\n } catch (error) {\n await lease.release();\n throw error;\n }\n}\n"]}
@@ -0,0 +1,40 @@
1
+ import type { TaskRecord, WorkflowExecutionState } from "../workflow.types.ts";
2
+ import type { WorkflowUsage } from "./budget.types.ts";
3
+ export type WorkflowJson = null | boolean | number | string | readonly WorkflowJson[] | {
4
+ readonly [key: string]: WorkflowJson;
5
+ };
6
+ export type WorkflowCheckpointValue = {
7
+ readonly kind: "undefined";
8
+ } | {
9
+ readonly kind: "json";
10
+ readonly value: WorkflowJson;
11
+ };
12
+ export interface WorkflowCheckpoint {
13
+ readonly format: 1;
14
+ readonly identity: string;
15
+ readonly executionId: string;
16
+ readonly records: readonly Readonly<TaskRecord>[];
17
+ readonly values: Readonly<Record<string, WorkflowCheckpointValue>>;
18
+ readonly usage: WorkflowUsage;
19
+ }
20
+ export interface WorkflowCheckpointLease {
21
+ read(): Promise<unknown>;
22
+ write(checkpoint: WorkflowCheckpoint): Promise<void>;
23
+ release(): Promise<void>;
24
+ }
25
+ export interface WorkflowCheckpointStore {
26
+ acquire(runId: string): Promise<WorkflowCheckpointLease>;
27
+ }
28
+ export interface WorkflowCheckpointOptions {
29
+ readonly store: WorkflowCheckpointStore;
30
+ readonly runId: string;
31
+ /** Change when task implementations or workflow inputs change. */
32
+ readonly version: string;
33
+ /** Explicitly authorize replay of incomplete tasks and their side effects. */
34
+ readonly resume?: "retry-incomplete";
35
+ }
36
+ export interface WorkflowCheckpointSession {
37
+ readonly initial: WorkflowCheckpoint | undefined;
38
+ save(state: WorkflowExecutionState): Promise<void>;
39
+ release(): Promise<void>;
40
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=checkpoint.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint.types.js","sourceRoot":"","sources":["../../../src/domain/workflow/checkpoint.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { TaskRecord, WorkflowExecutionState } from \"../workflow.types.ts\";\nimport type { WorkflowUsage } from \"./budget.types.ts\";\n\nexport type WorkflowJson =\n | null\n | boolean\n | number\n | string\n | readonly WorkflowJson[]\n | { readonly [key: string]: WorkflowJson };\nexport type WorkflowCheckpointValue =\n | { readonly kind: \"undefined\" }\n | { readonly kind: \"json\"; readonly value: WorkflowJson };\n\nexport interface WorkflowCheckpoint {\n readonly format: 1;\n readonly identity: string;\n readonly executionId: string;\n readonly records: readonly Readonly<TaskRecord>[];\n readonly values: Readonly<Record<string, WorkflowCheckpointValue>>;\n readonly usage: WorkflowUsage;\n}\n\nexport interface WorkflowCheckpointLease {\n read(): Promise<unknown>;\n write(checkpoint: WorkflowCheckpoint): Promise<void>;\n release(): Promise<void>;\n}\n\nexport interface WorkflowCheckpointStore {\n acquire(runId: string): Promise<WorkflowCheckpointLease>;\n}\n\nexport interface WorkflowCheckpointOptions {\n readonly store: WorkflowCheckpointStore;\n readonly runId: string;\n /** Change when task implementations or workflow inputs change. */\n readonly version: string;\n /** Explicitly authorize replay of incomplete tasks and their side effects. */\n readonly resume?: \"retry-incomplete\";\n}\n\nexport interface WorkflowCheckpointSession {\n readonly initial: WorkflowCheckpoint | undefined;\n save(state: WorkflowExecutionState): Promise<void>;\n release(): Promise<void>;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { Task } from "../workflow.types.ts";
2
+ import type { WorkflowGate } from "./gates.types.ts";
3
+ export declare function validateGate(gate: WorkflowGate): void;
4
+ export declare function validateGateRecord(record: Record<string, unknown>, item: Task, executionId: string, output: unknown): void;
@@ -0,0 +1,71 @@
1
+ import { gateActions } from "./gates.constants.js";
2
+ function object(value) {
3
+ return value !== null && typeof value === "object" && !Array.isArray(value);
4
+ }
5
+ export function validateGate(gate) {
6
+ if (!["approval", "pause"].includes(gate.kind))
7
+ throw new Error("Invalid workflow gate kind");
8
+ if (!gate.prompt.trim())
9
+ throw new Error("Gate prompt cannot be empty");
10
+ if (!gate.actors.length ||
11
+ gate.actors.some((actor) => !actor.trim()) ||
12
+ new Set(gate.actors).size !== gate.actors.length)
13
+ throw new Error("Gate actors must be nonempty and unique");
14
+ }
15
+ export function validateGateRecord(record, item, executionId, output) {
16
+ const invalid = () => new Error("Invalid workflow checkpoint gate record");
17
+ const gate = item.gate;
18
+ const request = record.pause;
19
+ const decision = record.decision;
20
+ if (!gate) {
21
+ if (request !== undefined ||
22
+ decision !== undefined ||
23
+ ["paused", "rejected"].includes(String(record.status)))
24
+ throw invalid();
25
+ return;
26
+ }
27
+ if (record.attempts !== 0)
28
+ throw invalid();
29
+ if (!["paused", "done", "rejected"].includes(String(record.status))) {
30
+ if (!["waiting", "skipped", "cancelled"].includes(String(record.status)) ||
31
+ request !== undefined ||
32
+ decision !== undefined)
33
+ throw invalid();
34
+ return;
35
+ }
36
+ if (!object(request) ||
37
+ typeof request.id !== "string" ||
38
+ !request.id.trim() ||
39
+ typeof request.requestedAt !== "string" ||
40
+ !Number.isFinite(Date.parse(request.requestedAt)) ||
41
+ request.kind !== gate.kind ||
42
+ request.prompt !== gate.prompt ||
43
+ JSON.stringify(request.actors) !== JSON.stringify(gate.actors))
44
+ throw invalid();
45
+ if (record.status === "paused") {
46
+ if (decision !== undefined)
47
+ throw invalid();
48
+ return;
49
+ }
50
+ const action = record.status === "rejected" ? "reject" : gateActions[gate.kind];
51
+ if (!object(decision) ||
52
+ decision.executionId !== executionId ||
53
+ decision.key !== item.key ||
54
+ decision.requestId !== request.id ||
55
+ decision.action !== action ||
56
+ typeof decision.actor !== "string" ||
57
+ !gate.actors.includes(decision.actor) ||
58
+ typeof decision.reason !== "string" ||
59
+ !decision.reason.trim() ||
60
+ typeof decision.decidedAt !== "string" ||
61
+ !Number.isFinite(Date.parse(decision.decidedAt)))
62
+ throw invalid();
63
+ if (record.status === "done" &&
64
+ (!object(output) ||
65
+ output.kind !== "json" ||
66
+ !object(output.value) ||
67
+ Object.keys(output.value).length !== Object.keys(decision).length ||
68
+ !Object.entries(decision).every(([key, value]) => object(output.value) && output.value[key] === value)))
69
+ throw invalid();
70
+ }
71
+ //# sourceMappingURL=gate-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-validation.js","sourceRoot":"","sources":["../../../src/domain/workflow/gate-validation.ts"],"names":[],"mappings":"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","sourcesContent":["import { gateActions } from \"./gates.constants.ts\";\nimport type { Task } from \"../workflow.types.ts\";\nimport type { WorkflowGate } from \"./gates.types.ts\";\n\nfunction object(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function validateGate(gate: WorkflowGate): void {\n if (![\"approval\", \"pause\"].includes(gate.kind))\n throw new Error(\"Invalid workflow gate kind\");\n if (!gate.prompt.trim()) throw new Error(\"Gate prompt cannot be empty\");\n if (\n !gate.actors.length ||\n gate.actors.some((actor) => !actor.trim()) ||\n new Set(gate.actors).size !== gate.actors.length\n )\n throw new Error(\"Gate actors must be nonempty and unique\");\n}\n\nexport function validateGateRecord(\n record: Record<string, unknown>,\n item: Task,\n executionId: string,\n output: unknown,\n): void {\n const invalid = () => new Error(\"Invalid workflow checkpoint gate record\");\n const gate = item.gate;\n const request = record.pause;\n const decision = record.decision;\n if (!gate) {\n if (\n request !== undefined ||\n decision !== undefined ||\n [\"paused\", \"rejected\"].includes(String(record.status))\n )\n throw invalid();\n return;\n }\n if (record.attempts !== 0) throw invalid();\n if (![\"paused\", \"done\", \"rejected\"].includes(String(record.status))) {\n if (\n ![\"waiting\", \"skipped\", \"cancelled\"].includes(String(record.status)) ||\n request !== undefined ||\n decision !== undefined\n )\n throw invalid();\n return;\n }\n if (\n !object(request) ||\n typeof request.id !== \"string\" ||\n !request.id.trim() ||\n typeof request.requestedAt !== \"string\" ||\n !Number.isFinite(Date.parse(request.requestedAt)) ||\n request.kind !== gate.kind ||\n request.prompt !== gate.prompt ||\n JSON.stringify(request.actors) !== JSON.stringify(gate.actors)\n )\n throw invalid();\n if (record.status === \"paused\") {\n if (decision !== undefined) throw invalid();\n return;\n }\n const action =\n record.status === \"rejected\" ? \"reject\" : gateActions[gate.kind];\n if (\n !object(decision) ||\n decision.executionId !== executionId ||\n decision.key !== item.key ||\n decision.requestId !== request.id ||\n decision.action !== action ||\n typeof decision.actor !== \"string\" ||\n !gate.actors.includes(decision.actor) ||\n typeof decision.reason !== \"string\" ||\n !decision.reason.trim() ||\n typeof decision.decidedAt !== \"string\" ||\n !Number.isFinite(Date.parse(decision.decidedAt))\n )\n throw invalid();\n if (\n record.status === \"done\" &&\n (!object(output) ||\n output.kind !== \"json\" ||\n !object(output.value) ||\n Object.keys(output.value).length !== Object.keys(decision).length ||\n !Object.entries(decision).every(\n ([key, value]) => object(output.value) && output.value[key] === value,\n ))\n )\n throw invalid();\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export declare const gateActions: {
2
+ readonly approval: "approve";
3
+ readonly pause: "resume";
4
+ };
@@ -0,0 +1,5 @@
1
+ export const gateActions = {
2
+ approval: "approve",
3
+ pause: "resume",
4
+ };
5
+ //# sourceMappingURL=gates.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gates.constants.js","sourceRoot":"","sources":["../../../src/domain/workflow/gates.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,QAAQ,EAAE,SAAS;IACnB,KAAK,EAAE,QAAQ;CACP,CAAC","sourcesContent":["export const gateActions = {\n approval: \"approve\",\n pause: \"resume\",\n} as const;\n"]}
@@ -0,0 +1,7 @@
1
+ import type { Task, WorkflowExecutionState } from "../workflow.types.ts";
2
+ import type { WorkflowDecisionRecord, WorkflowGateOptions } from "./gates.types.ts";
3
+ export declare function approvalTask(options: WorkflowGateOptions): Task<WorkflowDecisionRecord>;
4
+ export declare function pauseTask(options: WorkflowGateOptions): Task<WorkflowDecisionRecord>;
5
+ export declare function pauseGate(item: Task, runtime: WorkflowExecutionState): Promise<void>;
6
+ export declare function prepareDecisions(runtime: WorkflowExecutionState): readonly WorkflowDecisionRecord[];
7
+ export declare function applyDecisions(runtime: WorkflowExecutionState, decisions: readonly WorkflowDecisionRecord[]): void;
@@ -0,0 +1,85 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { task } from "./task.js";
3
+ import { gateActions } from "./gates.constants.js";
4
+ import { validateGate } from "./gate-validation.js";
5
+ function gateTask(kind, options) {
6
+ validateGate({ kind, prompt: options.prompt, actors: options.actors });
7
+ return task({
8
+ key: options.key,
9
+ after: options.after ?? [],
10
+ gate: Object.freeze({
11
+ kind,
12
+ prompt: options.prompt,
13
+ actors: Object.freeze([...options.actors]),
14
+ }),
15
+ perform() {
16
+ throw new Error("Workflow gates must be scheduled with a checkpoint");
17
+ },
18
+ });
19
+ }
20
+ export function approvalTask(options) {
21
+ return gateTask("approval", options);
22
+ }
23
+ export function pauseTask(options) {
24
+ return gateTask("pause", options);
25
+ }
26
+ export async function pauseGate(item, runtime) {
27
+ const gate = item.gate;
28
+ runtime.record(item).pause = Object.freeze({
29
+ ...gate,
30
+ id: randomUUID(),
31
+ requestedAt: new Date().toISOString(),
32
+ });
33
+ runtime.finish(item, "paused");
34
+ await runtime.persist();
35
+ }
36
+ export function prepareDecisions(runtime) {
37
+ const decisions = (runtime.options.decisions ?? []).map((decision) => Object.freeze({
38
+ executionId: decision.executionId,
39
+ key: decision.key,
40
+ requestId: decision.requestId,
41
+ action: decision.action,
42
+ actor: decision.actor,
43
+ reason: decision.reason,
44
+ decidedAt: new Date().toISOString(),
45
+ }));
46
+ const pending = new Map([...runtime.records.keys()].map((item) => [item.key, item]));
47
+ const seen = new Set();
48
+ for (const decision of decisions) {
49
+ const item = pending.get(decision.key);
50
+ const record = item && runtime.record(item);
51
+ const request = record?.pause;
52
+ if (!record ||
53
+ !request ||
54
+ record.status !== "paused" ||
55
+ record.decision ||
56
+ decision.executionId !== runtime.executionId ||
57
+ decision.requestId !== request.id ||
58
+ seen.has(decision.key) ||
59
+ typeof decision.actor !== "string" ||
60
+ !request.actors.includes(decision.actor) ||
61
+ typeof decision.reason !== "string" ||
62
+ !decision.reason.trim() ||
63
+ ![gateActions[request.kind], "reject"].includes(decision.action))
64
+ throw new Error(`Invalid or unauthorized workflow decision: ${decision.key}`);
65
+ seen.add(decision.key);
66
+ }
67
+ return decisions;
68
+ }
69
+ export function applyDecisions(runtime, decisions) {
70
+ const pending = new Map([...runtime.records.keys()].map((item) => [item.key, item]));
71
+ for (const decision of decisions) {
72
+ const item = pending.get(decision.key);
73
+ const record = runtime.record(item);
74
+ record.decision = decision;
75
+ if (decision.action === "reject") {
76
+ record.error = `${item.key} rejected by ${decision.actor}: ${decision.reason}`;
77
+ runtime.errors.push(new Error(record.error));
78
+ runtime.finish(item, "rejected");
79
+ continue;
80
+ }
81
+ runtime.values.set(item, decision);
82
+ runtime.finish(item, "done");
83
+ }
84
+ }
85
+ //# sourceMappingURL=gates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gates.js","sourceRoot":"","sources":["../../../src/domain/workflow/gates.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { Task, WorkflowExecutionState } from \"../workflow.types.ts\";\nimport type {\n WorkflowDecisionRecord,\n WorkflowGate,\n WorkflowGateOptions,\n} from \"./gates.types.ts\";\nimport { task } from \"./task.ts\";\nimport { gateActions } from \"./gates.constants.ts\";\nimport { validateGate } from \"./gate-validation.ts\";\n\nfunction gateTask(\n kind: WorkflowGate[\"kind\"],\n options: WorkflowGateOptions,\n): Task<WorkflowDecisionRecord> {\n validateGate({ kind, prompt: options.prompt, actors: options.actors });\n return task({\n key: options.key,\n after: options.after ?? [],\n gate: Object.freeze({\n kind,\n prompt: options.prompt,\n actors: Object.freeze([...options.actors]),\n }),\n perform() {\n throw new Error(\"Workflow gates must be scheduled with a checkpoint\");\n },\n });\n}\n\nexport function approvalTask(\n options: WorkflowGateOptions,\n): Task<WorkflowDecisionRecord> {\n return gateTask(\"approval\", options);\n}\n\nexport function pauseTask(\n options: WorkflowGateOptions,\n): Task<WorkflowDecisionRecord> {\n return gateTask(\"pause\", options);\n}\n\nexport async function pauseGate(\n item: Task,\n runtime: WorkflowExecutionState,\n): Promise<void> {\n const gate = item.gate!;\n runtime.record(item).pause = Object.freeze({\n ...gate,\n id: randomUUID(),\n requestedAt: new Date().toISOString(),\n });\n runtime.finish(item, \"paused\");\n await runtime.persist();\n}\n\nexport function prepareDecisions(\n runtime: WorkflowExecutionState,\n): readonly WorkflowDecisionRecord[] {\n const decisions = (runtime.options.decisions ?? []).map((decision) =>\n Object.freeze({\n executionId: decision.executionId,\n key: decision.key,\n requestId: decision.requestId,\n action: decision.action,\n actor: decision.actor,\n reason: decision.reason,\n decidedAt: new Date().toISOString(),\n }),\n );\n const pending = new Map(\n [...runtime.records.keys()].map((item) => [item.key, item]),\n );\n const seen = new Set<string>();\n for (const decision of decisions) {\n const item = pending.get(decision.key);\n const record = item && runtime.record(item);\n const request = record?.pause;\n if (\n !record ||\n !request ||\n record.status !== \"paused\" ||\n record.decision ||\n decision.executionId !== runtime.executionId ||\n decision.requestId !== request.id ||\n seen.has(decision.key) ||\n typeof decision.actor !== \"string\" ||\n !request.actors.includes(decision.actor) ||\n typeof decision.reason !== \"string\" ||\n !decision.reason.trim() ||\n ![gateActions[request.kind], \"reject\"].includes(decision.action)\n )\n throw new Error(\n `Invalid or unauthorized workflow decision: ${decision.key}`,\n );\n seen.add(decision.key);\n }\n return decisions;\n}\n\nexport function applyDecisions(\n runtime: WorkflowExecutionState,\n decisions: readonly WorkflowDecisionRecord[],\n): void {\n const pending = new Map(\n [...runtime.records.keys()].map((item) => [item.key, item]),\n );\n for (const decision of decisions) {\n const item = pending.get(decision.key)!;\n const record = runtime.record(item);\n record.decision = decision;\n if (decision.action === \"reject\") {\n record.error = `${item.key} rejected by ${decision.actor}: ${decision.reason}`;\n runtime.errors.push(new Error(record.error));\n runtime.finish(item, \"rejected\");\n continue;\n }\n runtime.values.set(item, decision);\n runtime.finish(item, \"done\");\n }\n}\n"]}
@@ -0,0 +1,27 @@
1
+ import type { Task } from "../workflow.types.ts";
2
+ export interface WorkflowGate {
3
+ readonly kind: "approval" | "pause";
4
+ readonly prompt: string;
5
+ readonly actors: readonly string[];
6
+ }
7
+ export interface WorkflowGateOptions {
8
+ readonly key: string;
9
+ readonly after?: readonly Task[];
10
+ readonly prompt: string;
11
+ readonly actors: readonly string[];
12
+ }
13
+ export interface WorkflowPauseRequest extends WorkflowGate {
14
+ readonly id: string;
15
+ readonly requestedAt: string;
16
+ }
17
+ export interface WorkflowDecision {
18
+ readonly executionId: string;
19
+ readonly key: string;
20
+ readonly requestId: string;
21
+ readonly action: "approve" | "resume" | "reject";
22
+ readonly actor: string;
23
+ readonly reason: string;
24
+ }
25
+ export interface WorkflowDecisionRecord extends WorkflowDecision {
26
+ readonly decidedAt: string;
27
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=gates.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gates.types.js","sourceRoot":"","sources":["../../../src/domain/workflow/gates.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Task } from \"../workflow.types.ts\";\n\nexport interface WorkflowGate {\n readonly kind: \"approval\" | \"pause\";\n readonly prompt: string;\n readonly actors: readonly string[];\n}\n\nexport interface WorkflowGateOptions {\n readonly key: string;\n readonly after?: readonly Task[];\n readonly prompt: string;\n readonly actors: readonly string[];\n}\n\nexport interface WorkflowPauseRequest extends WorkflowGate {\n readonly id: string;\n readonly requestedAt: string;\n}\n\nexport interface WorkflowDecision {\n readonly executionId: string;\n readonly key: string;\n readonly requestId: string;\n readonly action: \"approve\" | \"resume\" | \"reject\";\n readonly actor: string;\n readonly reason: string;\n}\n\nexport interface WorkflowDecisionRecord extends WorkflowDecision {\n readonly decidedAt: string;\n}\n"]}
@@ -1,12 +1,16 @@
1
+ import { checkpointValue } from "./checkpoint-value.js";
1
2
  import { WorkflowBudgetExceeded } from "./budget.js";
2
3
  import { setTimeout as delay } from "node:timers/promises";
3
4
  export async function runTask(item, runtime) {
4
5
  const { record, signal, context, emit, finish, values, errors, options, stop, } = runtime;
5
6
  const state = record(item);
6
7
  state.status = "active";
8
+ delete state.error;
9
+ delete state.finishedAt;
7
10
  state.startedAt = new Date().toISOString();
8
11
  emit({ type: "task", key: item.key, status: "active", attempt: 0 });
9
12
  try {
13
+ await runtime.persist();
10
14
  signal.throwIfAborted();
11
15
  if (item.condition && !(await item.condition(context(item, 0, signal)))) {
12
16
  signal.throwIfAborted();
@@ -14,11 +18,14 @@ export async function runTask(item, runtime) {
14
18
  return;
15
19
  }
16
20
  const limit = item.retry?.attempts ?? 1;
17
- for (let attempt = 1; attempt <= limit; attempt++) {
21
+ const priorAttempts = state.attempts;
22
+ for (let cycle = 1; cycle <= limit; cycle++) {
23
+ const attempt = priorAttempts + cycle;
18
24
  signal.throwIfAborted();
19
25
  runtime.accounting.admit();
20
26
  state.attempts = attempt;
21
27
  emit({ type: "attempt", key: item.key, attempt });
28
+ await runtime.persist();
22
29
  const deadline = new AbortController();
23
30
  const timer = item.timeoutMs === undefined
24
31
  ? undefined
@@ -28,6 +35,8 @@ export async function runTask(item, runtime) {
28
35
  taskSignal.throwIfAborted();
29
36
  const value = await item.perform(context(item, attempt, taskSignal));
30
37
  taskSignal.throwIfAborted();
38
+ if (options.checkpoint)
39
+ checkpointValue(value);
31
40
  values.set(item, value);
32
41
  finish(item, "done");
33
42
  return;
@@ -35,7 +44,7 @@ export async function runTask(item, runtime) {
35
44
  catch (error) {
36
45
  runtime.closeAttempt(item);
37
46
  if (signal.aborted ||
38
- attempt === limit ||
47
+ cycle === limit ||
39
48
  item.retry?.accepts?.(error, attempt) === false)
40
49
  throw error;
41
50
  emit({ type: "retry", key: item.key, attempt });
@@ -59,5 +68,8 @@ export async function runTask(item, runtime) {
59
68
  stop.abort(error);
60
69
  }
61
70
  }
71
+ finally {
72
+ await runtime.persist();
73
+ }
62
74
  }
63
75
  //# sourceMappingURL=task-runner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"task-runner.js","sourceRoot":"","sources":["../../../src/domain/workflow/task-runner.ts"],"names":[],"mappings":"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","sourcesContent":["import { WorkflowBudgetExceeded } from \"./budget.ts\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport type { Task, WorkflowExecutionState } from \"../workflow.types.ts\";\n\nexport async function runTask(\n item: Task,\n runtime: WorkflowExecutionState,\n): Promise<void> {\n const {\n record,\n signal,\n context,\n emit,\n finish,\n values,\n errors,\n options,\n stop,\n } = runtime;\n const state = record(item);\n state.status = \"active\";\n state.startedAt = new Date().toISOString();\n emit({ type: \"task\", key: item.key, status: \"active\", attempt: 0 });\n try {\n signal.throwIfAborted();\n if (item.condition && !(await item.condition(context(item, 0, signal)))) {\n signal.throwIfAborted();\n finish(item, \"skipped\");\n return;\n }\n const limit = item.retry?.attempts ?? 1;\n for (let attempt = 1; attempt <= limit; attempt++) {\n signal.throwIfAborted();\n runtime.accounting.admit();\n state.attempts = attempt;\n emit({ type: \"attempt\", key: item.key, attempt });\n const deadline = new AbortController();\n const timer =\n item.timeoutMs === undefined\n ? undefined\n : setTimeout(\n () => deadline.abort(new Error(`${item.key} timed out`)),\n item.timeoutMs,\n );\n const taskSignal = AbortSignal.any([signal, deadline.signal]);\n try {\n taskSignal.throwIfAborted();\n const value = await item.perform(context(item, attempt, taskSignal));\n taskSignal.throwIfAborted();\n values.set(item, value);\n finish(item, \"done\");\n return;\n } catch (error) {\n runtime.closeAttempt(item);\n if (\n signal.aborted ||\n attempt === limit ||\n item.retry?.accepts?.(error, attempt) === false\n )\n throw error;\n emit({ type: \"retry\", key: item.key, attempt });\n } finally {\n runtime.closeAttempt(item);\n clearTimeout(timer);\n }\n await delay(item.retry?.delayMs ?? 0, undefined, { signal });\n }\n } catch (error) {\n state.error = error instanceof Error ? error.message : String(error);\n if (\n signal.aborted ||\n (error instanceof WorkflowBudgetExceeded && runtime.accounting.exhausted)\n )\n finish(item, \"cancelled\");\n else {\n errors.push(error);\n finish(item, \"failed\");\n if (options.stopOnError !== false) stop.abort(error);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"task-runner.js","sourceRoot":"","sources":["../../../src/domain/workflow/task-runner.ts"],"names":[],"mappings":"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","sourcesContent":["import { checkpointValue } from \"./checkpoint-value.ts\";\nimport { WorkflowBudgetExceeded } from \"./budget.ts\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport type { Task, WorkflowExecutionState } from \"../workflow.types.ts\";\n\nexport async function runTask(\n item: Task,\n runtime: WorkflowExecutionState,\n): Promise<void> {\n const {\n record,\n signal,\n context,\n emit,\n finish,\n values,\n errors,\n options,\n stop,\n } = runtime;\n const state = record(item);\n state.status = \"active\";\n delete state.error;\n delete state.finishedAt;\n state.startedAt = new Date().toISOString();\n emit({ type: \"task\", key: item.key, status: \"active\", attempt: 0 });\n try {\n await runtime.persist();\n signal.throwIfAborted();\n if (item.condition && !(await item.condition(context(item, 0, signal)))) {\n signal.throwIfAborted();\n finish(item, \"skipped\");\n return;\n }\n const limit = item.retry?.attempts ?? 1;\n const priorAttempts = state.attempts;\n for (let cycle = 1; cycle <= limit; cycle++) {\n const attempt = priorAttempts + cycle;\n signal.throwIfAborted();\n runtime.accounting.admit();\n state.attempts = attempt;\n emit({ type: \"attempt\", key: item.key, attempt });\n await runtime.persist();\n const deadline = new AbortController();\n const timer =\n item.timeoutMs === undefined\n ? undefined\n : setTimeout(\n () => deadline.abort(new Error(`${item.key} timed out`)),\n item.timeoutMs,\n );\n const taskSignal = AbortSignal.any([signal, deadline.signal]);\n try {\n taskSignal.throwIfAborted();\n const value = await item.perform(context(item, attempt, taskSignal));\n taskSignal.throwIfAborted();\n if (options.checkpoint) checkpointValue(value);\n values.set(item, value);\n finish(item, \"done\");\n return;\n } catch (error) {\n runtime.closeAttempt(item);\n if (\n signal.aborted ||\n cycle === limit ||\n item.retry?.accepts?.(error, attempt) === false\n )\n throw error;\n emit({ type: \"retry\", key: item.key, attempt });\n } finally {\n runtime.closeAttempt(item);\n clearTimeout(timer);\n }\n await delay(item.retry?.delayMs ?? 0, undefined, { signal });\n }\n } catch (error) {\n state.error = error instanceof Error ? error.message : String(error);\n if (\n signal.aborted ||\n (error instanceof WorkflowBudgetExceeded && runtime.accounting.exhausted)\n )\n finish(item, \"cancelled\");\n else {\n errors.push(error);\n finish(item, \"failed\");\n if (options.stopOnError !== false) stop.abort(error);\n }\n } finally {\n await runtime.persist();\n }\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare const maxUsageReceiptsPerTask = 65536;
2
+ export declare const maxUsageReceiptLength = 512;
@@ -0,0 +1,3 @@
1
+ export const maxUsageReceiptsPerTask = 65_536;
2
+ export const maxUsageReceiptLength = 512;
3
+ //# sourceMappingURL=usage-receipt.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-receipt.constants.js","sourceRoot":"","sources":["../../../src/domain/workflow/usage-receipt.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAC9C,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC","sourcesContent":["export const maxUsageReceiptsPerTask = 65_536;\nexport const maxUsageReceiptLength = 512;\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function validateUsageReceipt(receipt: unknown): asserts receipt is string;
2
+ export declare function validateUsageReceipts(receipts: unknown): void;
@@ -0,0 +1,18 @@
1
+ import { maxUsageReceiptLength, maxUsageReceiptsPerTask, } from "./usage-receipt.constants.js";
2
+ export function validateUsageReceipt(receipt) {
3
+ if (typeof receipt !== "string" ||
4
+ !receipt.length ||
5
+ receipt.length > maxUsageReceiptLength)
6
+ throw new Error("Invalid workflow usage receipt");
7
+ }
8
+ export function validateUsageReceipts(receipts) {
9
+ if (receipts === undefined)
10
+ return;
11
+ if (!Array.isArray(receipts) || receipts.length > maxUsageReceiptsPerTask)
12
+ throw new Error("Invalid workflow usage receipts");
13
+ for (const receipt of receipts)
14
+ validateUsageReceipt(receipt);
15
+ if (new Set(receipts).size !== receipts.length)
16
+ throw new Error("Duplicate workflow usage receipts");
17
+ }
18
+ //# sourceMappingURL=usage-receipt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-receipt.js","sourceRoot":"","sources":["../../../src/domain/workflow/usage-receipt.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,8BAA8B,CAAC;AAEtC,MAAM,UAAU,oBAAoB,CAClC,OAAgB;IAEhB,IACE,OAAO,OAAO,KAAK,QAAQ;QAC3B,CAAC,OAAO,CAAC,MAAM;QACf,OAAO,CAAC,MAAM,GAAG,qBAAqB;QAEtC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;AACtD,CAAC;AACD,MAAM,UAAU,qBAAqB,CAAC,QAAiB;IACrD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO;IACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,uBAAuB;QACvE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,KAAK,MAAM,OAAO,IAAI,QAAQ;QAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9D,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,MAAM;QAC5C,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;AACzD,CAAC","sourcesContent":["import {\n maxUsageReceiptLength,\n maxUsageReceiptsPerTask,\n} from \"./usage-receipt.constants.ts\";\n\nexport function validateUsageReceipt(\n receipt: unknown,\n): asserts receipt is string {\n if (\n typeof receipt !== \"string\" ||\n !receipt.length ||\n receipt.length > maxUsageReceiptLength\n )\n throw new Error(\"Invalid workflow usage receipt\");\n}\nexport function validateUsageReceipts(receipts: unknown): void {\n if (receipts === undefined) return;\n if (!Array.isArray(receipts) || receipts.length > maxUsageReceiptsPerTask)\n throw new Error(\"Invalid workflow usage receipts\");\n for (const receipt of receipts) validateUsageReceipt(receipt);\n if (new Set(receipts).size !== receipts.length)\n throw new Error(\"Duplicate workflow usage receipts\");\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { validateGate } from "./gate-validation.js";
1
2
  export function positive(value, label) {
2
3
  if (!Number.isSafeInteger(value) || value < 1)
3
4
  throw new Error(`${label} must be a positive integer`);
@@ -8,6 +9,11 @@ export function validate(tasks) {
8
9
  const visiting = new Set();
9
10
  const visited = new Set();
10
11
  for (const item of tasks) {
12
+ if (item.gate) {
13
+ validateGate(item.gate);
14
+ if (item.condition || item.retry || item.timeoutMs !== undefined)
15
+ throw new Error("Workflow gates cannot have conditions, retries or timeouts");
16
+ }
11
17
  if (keys.has(item.key))
12
18
  throw new Error(`Duplicate task: ${item.key}`);
13
19
  keys.add(item.key);
@@ -1 +1 @@
1
- {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/domain/workflow/validation.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,QAAQ,CAAC,KAAa,EAAE,KAAa;IACnD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,6BAA6B,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAsB;IAC7C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAQ,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAQ,CAAC;IAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,KAAK;YACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,wBAAwB,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,SAAS,KAAK,CAAC,IAAU;QACvB,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC3E,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO;QAC9B,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1B,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC","sourcesContent":["import type { Task } from \"../workflow.types.ts\";\n\nexport function positive(value: number, label: string): void {\n if (!Number.isSafeInteger(value) || value < 1)\n throw new Error(`${label} must be a positive integer`);\n}\n\nexport function validate(tasks: readonly Task[]): void {\n const keys = new Set<string>();\n const members = new Set(tasks);\n const visiting = new Set<Task>();\n const visited = new Set<Task>();\n for (const item of tasks) {\n if (keys.has(item.key)) throw new Error(`Duplicate task: ${item.key}`);\n keys.add(item.key);\n for (const dependency of item.after)\n if (!members.has(dependency))\n throw new Error(`${item.key}: missing dependency ${dependency.key}`);\n }\n function visit(item: Task): void {\n if (visiting.has(item)) throw new Error(`Dependency cycle at ${item.key}`);\n if (visited.has(item)) return;\n visiting.add(item);\n item.after.forEach(visit);\n visiting.delete(item);\n visited.add(item);\n }\n tasks.forEach(visit);\n}\n"]}
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/domain/workflow/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,MAAM,UAAU,QAAQ,CAAC,KAAa,EAAE,KAAa;IACnD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,6BAA6B,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAsB;IAC7C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAQ,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAQ,CAAC;IAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;gBAC9D,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;QACN,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,KAAK;YACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,wBAAwB,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,SAAS,KAAK,CAAC,IAAU;QACvB,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC3E,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO;QAC9B,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1B,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC","sourcesContent":["import { validateGate } from \"./gate-validation.ts\";\nimport type { Task } from \"../workflow.types.ts\";\n\nexport function positive(value: number, label: string): void {\n if (!Number.isSafeInteger(value) || value < 1)\n throw new Error(`${label} must be a positive integer`);\n}\n\nexport function validate(tasks: readonly Task[]): void {\n const keys = new Set<string>();\n const members = new Set(tasks);\n const visiting = new Set<Task>();\n const visited = new Set<Task>();\n for (const item of tasks) {\n if (item.gate) {\n validateGate(item.gate);\n if (item.condition || item.retry || item.timeoutMs !== undefined)\n throw new Error(\n \"Workflow gates cannot have conditions, retries or timeouts\",\n );\n }\n if (keys.has(item.key)) throw new Error(`Duplicate task: ${item.key}`);\n keys.add(item.key);\n for (const dependency of item.after)\n if (!members.has(dependency))\n throw new Error(`${item.key}: missing dependency ${dependency.key}`);\n }\n function visit(item: Task): void {\n if (visiting.has(item)) throw new Error(`Dependency cycle at ${item.key}`);\n if (visited.has(item)) return;\n visiting.add(item);\n item.after.forEach(visit);\n visiting.delete(item);\n visited.add(item);\n }\n tasks.forEach(visit);\n}\n"]}