@vercel/factory 0.0.13 → 0.0.15

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 (458) hide show
  1. package/README.md +307 -1
  2. package/dist/agent-routes.d.mts +69 -0
  3. package/dist/agent-routes.mjs +64 -0
  4. package/dist/agent-routes.mjs.map +1 -0
  5. package/dist/api-contracts.d.mts +1749 -0
  6. package/dist/api-contracts.mjs +118 -0
  7. package/dist/api-contracts.mjs.map +1 -0
  8. package/dist/api-images.d.mts +30 -0
  9. package/dist/api-images.mjs +28 -0
  10. package/dist/api-images.mjs.map +1 -0
  11. package/dist/api-task-graph.mjs +57 -0
  12. package/dist/api-task-graph.mjs.map +1 -0
  13. package/dist/api.d.mts +77 -0
  14. package/dist/api.mjs +1087 -0
  15. package/dist/api.mjs.map +1 -0
  16. package/dist/approval-access.d.mts +39 -0
  17. package/dist/approval-access.mjs +62 -0
  18. package/dist/approval-access.mjs.map +1 -0
  19. package/dist/approval-contracts.d.mts +692 -0
  20. package/dist/approval-contracts.mjs +27 -0
  21. package/dist/approval-contracts.mjs.map +1 -0
  22. package/dist/approval.d.mts +49 -0
  23. package/dist/approval.mjs +39 -0
  24. package/dist/approval.mjs.map +1 -0
  25. package/dist/blob/artifacts.d.mts +37 -0
  26. package/dist/blob/artifacts.mjs +45 -0
  27. package/dist/blob/artifacts.mjs.map +1 -0
  28. package/dist/blob/index.d.mts +44 -8
  29. package/dist/blob/index.mjs +159 -35
  30. package/dist/blob/index.mjs.map +1 -1
  31. package/dist/budget.d.mts +108 -0
  32. package/dist/budget.mjs +141 -0
  33. package/dist/budget.mjs.map +1 -0
  34. package/dist/budgets.d.mts +4 -0
  35. package/dist/budgets.mjs +4 -0
  36. package/dist/build-factory.d.mts +6 -4
  37. package/dist/build-factory.mjs +2 -1
  38. package/dist/build-factory.mjs.map +1 -1
  39. package/dist/change-verification/brief.d.mts +9 -0
  40. package/dist/change-verification/brief.mjs +13 -0
  41. package/dist/change-verification/brief.mjs.map +1 -0
  42. package/dist/change-verification/dispatch.d.mts +24 -0
  43. package/dist/change-verification/dispatch.mjs +45 -0
  44. package/dist/change-verification/dispatch.mjs.map +1 -0
  45. package/dist/change-verification/eve-tool.d.mts +60 -0
  46. package/dist/change-verification/eve-tool.mjs +101 -0
  47. package/dist/change-verification/eve-tool.mjs.map +1 -0
  48. package/dist/changes/eve-record-change.d.mts +56 -0
  49. package/dist/changes/eve-record-change.mjs +97 -0
  50. package/dist/changes/eve-record-change.mjs.map +1 -0
  51. package/dist/changes/presentation.d.mts +14 -0
  52. package/dist/changes.d.mts +23 -0
  53. package/dist/changes.mjs +29 -0
  54. package/dist/changes.mjs.map +1 -0
  55. package/dist/client-events.d.mts +18 -0
  56. package/dist/client-events.mjs +41 -0
  57. package/dist/client-events.mjs.map +1 -0
  58. package/dist/client-stream.d.mts +28 -0
  59. package/dist/client-stream.mjs +204 -0
  60. package/dist/client-stream.mjs.map +1 -0
  61. package/dist/client-transcript.d.mts +41 -0
  62. package/dist/client-transcript.mjs +229 -0
  63. package/dist/client-transcript.mjs.map +1 -0
  64. package/dist/client.d.mts +234 -0
  65. package/dist/client.mjs +258 -0
  66. package/dist/client.mjs.map +1 -0
  67. package/dist/code-review/contracts.d.mts +26 -0
  68. package/dist/code-review/eve-post-review.d.mts +70 -0
  69. package/dist/code-review/eve-post-review.mjs +183 -0
  70. package/dist/code-review/eve-post-review.mjs.map +1 -0
  71. package/dist/code-review/eve-review-comments.d.mts +64 -0
  72. package/dist/code-review/eve-review-comments.mjs +159 -0
  73. package/dist/code-review/eve-review-comments.mjs.map +1 -0
  74. package/dist/code-review/github-contracts.d.mts +10 -0
  75. package/dist/code-review/github-reporter.d.mts +44 -0
  76. package/dist/code-review/github-reporter.mjs +260 -0
  77. package/dist/code-review/github-reporter.mjs.map +1 -0
  78. package/dist/code-review/preparation.d.mts +34 -0
  79. package/dist/code-review/preparation.mjs +23 -0
  80. package/dist/code-review/preparation.mjs.map +1 -0
  81. package/dist/code-review/stall.d.mts +17 -0
  82. package/dist/code-review/stall.mjs +30 -0
  83. package/dist/code-review/stall.mjs.map +1 -0
  84. package/dist/code-review.d.mts +6 -0
  85. package/dist/code-review.mjs +5 -0
  86. package/dist/communication.d.mts +9 -0
  87. package/dist/communication.mjs +9 -0
  88. package/dist/connectors/github.d.mts +26 -0
  89. package/dist/connectors/github.mjs +55 -0
  90. package/dist/connectors/github.mjs.map +1 -0
  91. package/dist/connectors/index.d.mts +35 -2
  92. package/dist/connectors/index.mjs +4 -26
  93. package/dist/connectors/index.mjs.map +1 -1
  94. package/dist/connectors/outbox.d.mts +34 -0
  95. package/dist/connectors/outbox.mjs +50 -0
  96. package/dist/connectors/outbox.mjs.map +1 -0
  97. package/dist/connectors/slack-approval-blocks.mjs +136 -0
  98. package/dist/connectors/slack-approval-blocks.mjs.map +1 -0
  99. package/dist/connectors/slack-approvals.d.mts +29 -0
  100. package/dist/connectors/slack-approvals.mjs +346 -0
  101. package/dist/connectors/slack-approvals.mjs.map +1 -0
  102. package/dist/connectors/slack.d.mts +35 -41
  103. package/dist/connectors/slack.mjs +13 -69
  104. package/dist/connectors/slack.mjs.map +1 -1
  105. package/dist/deepsec/eve-tool.d.mts +110 -0
  106. package/dist/deepsec/eve-tool.mjs +164 -0
  107. package/dist/deepsec/eve-tool.mjs.map +1 -0
  108. package/dist/deepsec/finding.d.mts +84 -0
  109. package/dist/deepsec/finding.mjs +56 -0
  110. package/dist/deepsec/finding.mjs.map +1 -0
  111. package/dist/deepsec.d.mts +3 -0
  112. package/dist/delivery-metrics/metrics.d.mts +93 -0
  113. package/dist/delivery-metrics/metrics.mjs +200 -0
  114. package/dist/delivery-metrics/metrics.mjs.map +1 -0
  115. package/dist/delivery-metrics.d.mts +2 -0
  116. package/dist/delivery-metrics.mjs +2 -0
  117. package/dist/dispatch.d.mts +81 -0
  118. package/dist/dispatch.mjs +140 -0
  119. package/dist/dispatch.mjs.map +1 -0
  120. package/dist/errors.d.mts +15 -0
  121. package/dist/errors.mjs +38 -0
  122. package/dist/errors.mjs.map +1 -0
  123. package/dist/eve/index.d.mts +143 -1561
  124. package/dist/eve/index.mjs +244 -1063
  125. package/dist/eve/index.mjs.map +1 -1
  126. package/dist/eve/invoke.d.mts +144 -0
  127. package/dist/eve/invoke.mjs +241 -0
  128. package/dist/eve/invoke.mjs.map +1 -0
  129. package/dist/eve/session-client.d.mts +68 -0
  130. package/dist/eve/session-client.mjs +131 -0
  131. package/dist/eve/session-client.mjs.map +1 -0
  132. package/dist/eve/task-execution.mjs +18 -0
  133. package/dist/eve/task-execution.mjs.map +1 -0
  134. package/dist/eve/task-session.d.mts +87 -0
  135. package/dist/eve/task-session.mjs +203 -0
  136. package/dist/eve/task-session.mjs.map +1 -0
  137. package/dist/eve/transcript.d.mts +37 -0
  138. package/dist/eve/transcript.mjs +65 -0
  139. package/dist/eve/transcript.mjs.map +1 -0
  140. package/dist/execution-public.d.mts +8 -0
  141. package/dist/execution-public.mjs +7 -0
  142. package/dist/execution.d.mts +75 -0
  143. package/dist/execution.mjs +153 -0
  144. package/dist/execution.mjs.map +1 -0
  145. package/dist/finding-remediation/admission.d.mts +51 -0
  146. package/dist/finding-remediation/admission.mjs +87 -0
  147. package/dist/finding-remediation/admission.mjs.map +1 -0
  148. package/dist/finding-remediation/brief.d.mts +14 -0
  149. package/dist/finding-remediation/brief.mjs +25 -0
  150. package/dist/finding-remediation/brief.mjs.map +1 -0
  151. package/dist/finding-remediation/eve-tool.d.mts +29 -0
  152. package/dist/finding-remediation/eve-tool.mjs +34 -0
  153. package/dist/finding-remediation/eve-tool.mjs.map +1 -0
  154. package/dist/findings/fingerprint.d.mts +14 -0
  155. package/dist/findings/fingerprint.mjs +28 -0
  156. package/dist/findings/fingerprint.mjs.map +1 -0
  157. package/dist/findings.d.mts +6 -0
  158. package/dist/findings.mjs +6 -0
  159. package/dist/github-app.d.mts +54 -0
  160. package/dist/github-app.mjs +121 -0
  161. package/dist/github-app.mjs.map +1 -0
  162. package/dist/github-publication.d.mts +198 -0
  163. package/dist/github-publication.mjs +429 -0
  164. package/dist/github-publication.mjs.map +1 -0
  165. package/dist/github-transfer.d.mts +72 -0
  166. package/dist/github-transfer.mjs +125 -0
  167. package/dist/github-transfer.mjs.map +1 -0
  168. package/dist/github.d.mts +406 -2
  169. package/dist/github.mjs +250 -37
  170. package/dist/github.mjs.map +1 -1
  171. package/dist/image-input.d.mts +51 -0
  172. package/dist/image-input.mjs +63 -0
  173. package/dist/image-input.mjs.map +1 -0
  174. package/dist/index.d.mts +14 -314
  175. package/dist/index.mjs +14 -1124
  176. package/dist/intake-contracts.d.mts +56 -0
  177. package/dist/intake-contracts.mjs +33 -0
  178. package/dist/intake-contracts.mjs.map +1 -0
  179. package/dist/integrations/deepsec.d.mts +4 -0
  180. package/dist/integrations/deepsec.mjs +3 -0
  181. package/dist/integrations/github.d.mts +11 -0
  182. package/dist/integrations/github.mjs +9 -0
  183. package/dist/integrations/slack.d.mts +3 -0
  184. package/dist/integrations/slack.mjs +3 -0
  185. package/dist/integrations/vercel.d.mts +3 -0
  186. package/dist/integrations/vercel.mjs +3 -0
  187. package/dist/merge-resolution/contracts.d.mts +17 -0
  188. package/dist/merge-resolution/contracts.mjs +19 -0
  189. package/dist/merge-resolution/contracts.mjs.map +1 -0
  190. package/dist/merge-resolution/eve-tools.d.mts +46 -0
  191. package/dist/merge-resolution/eve-tools.mjs +117 -0
  192. package/dist/merge-resolution/eve-tools.mjs.map +1 -0
  193. package/dist/multi-repository-changes/coordination.d.mts +49 -0
  194. package/dist/multi-repository-changes/coordination.mjs +115 -0
  195. package/dist/multi-repository-changes/coordination.mjs.map +1 -0
  196. package/dist/planning/cancellation.mjs +82 -0
  197. package/dist/planning/cancellation.mjs.map +1 -0
  198. package/dist/planning/configuration.d.mts +23 -0
  199. package/dist/planning/configuration.mjs +56 -0
  200. package/dist/planning/configuration.mjs.map +1 -0
  201. package/dist/planning/contracts.d.mts +136 -0
  202. package/dist/planning/contracts.mjs +42 -0
  203. package/dist/planning/contracts.mjs.map +1 -0
  204. package/dist/planning/dependencies.mjs +44 -0
  205. package/dist/planning/dependencies.mjs.map +1 -0
  206. package/dist/planning/effects.mjs +122 -0
  207. package/dist/planning/effects.mjs.map +1 -0
  208. package/dist/planning/reconcile.mjs +273 -0
  209. package/dist/planning/reconcile.mjs.map +1 -0
  210. package/dist/planning/runtime.d.mts +27 -0
  211. package/dist/planning/runtime.mjs +25 -0
  212. package/dist/planning/runtime.mjs.map +1 -0
  213. package/dist/planning/state.mjs +92 -0
  214. package/dist/planning/state.mjs.map +1 -0
  215. package/dist/planning/turns.mjs +262 -0
  216. package/dist/planning/turns.mjs.map +1 -0
  217. package/dist/planning/validation.mjs +106 -0
  218. package/dist/planning/validation.mjs.map +1 -0
  219. package/dist/postgres/index.d.mts +7 -1
  220. package/dist/postgres/index.mjs +7 -3
  221. package/dist/postgres/index.mjs.map +1 -1
  222. package/dist/presets/software-development/approval.d.mts +14 -0
  223. package/dist/presets/software-development/approval.mjs +21 -0
  224. package/dist/presets/software-development/approval.mjs.map +1 -0
  225. package/dist/presets/software-development/deepsec-brief.d.mts +8 -0
  226. package/dist/presets/software-development/deepsec-brief.mjs +14 -0
  227. package/dist/presets/software-development/deepsec-brief.mjs.map +1 -0
  228. package/dist/presets/software-development/dispatch.d.mts +53 -0
  229. package/dist/presets/software-development/dispatch.mjs +66 -0
  230. package/dist/presets/software-development/dispatch.mjs.map +1 -0
  231. package/dist/presets/software-development/eve-delegation-policy.d.mts +7 -0
  232. package/dist/presets/software-development/eve-delegation-policy.mjs +34 -0
  233. package/dist/presets/software-development/eve-delegation-policy.mjs.map +1 -0
  234. package/dist/presets/software-development/eve.d.mts +18 -0
  235. package/dist/presets/software-development/eve.mjs +19 -0
  236. package/dist/presets/software-development/eve.mjs.map +1 -0
  237. package/dist/presets/software-development/finish-task-policy.d.mts +7 -0
  238. package/dist/presets/software-development/finish-task-policy.mjs +9 -0
  239. package/dist/presets/software-development/finish-task-policy.mjs.map +1 -0
  240. package/dist/presets/software-development/recovery.d.mts +32 -0
  241. package/dist/presets/software-development/recovery.mjs +120 -0
  242. package/dist/presets/software-development/recovery.mjs.map +1 -0
  243. package/dist/presets/software-development/task-communication.d.mts +23 -0
  244. package/dist/presets/software-development/task-communication.mjs +120 -0
  245. package/dist/presets/software-development/task-communication.mjs.map +1 -0
  246. package/dist/presets/software-development.d.mts +9 -0
  247. package/dist/presets/software-development.mjs +9 -0
  248. package/dist/pull-requests/contracts.d.mts +72 -0
  249. package/dist/pull-requests/eve-fetch.d.mts +57 -0
  250. package/dist/pull-requests/eve-fetch.mjs +151 -0
  251. package/dist/pull-requests/eve-fetch.mjs.map +1 -0
  252. package/dist/pull-requests/github-label-manager.d.mts +27 -0
  253. package/dist/pull-requests/github-label-manager.mjs +40 -0
  254. package/dist/pull-requests/github-label-manager.mjs.map +1 -0
  255. package/dist/pull-requests/github-publisher.d.mts +53 -0
  256. package/dist/pull-requests/github-publisher.mjs +345 -0
  257. package/dist/pull-requests/github-publisher.mjs.map +1 -0
  258. package/dist/pull-requests.d.mts +5 -0
  259. package/dist/pull-requests.mjs +4 -0
  260. package/dist/receipts.d.mts +4 -0
  261. package/dist/receipts.mjs +3 -0
  262. package/dist/repositories.d.mts +18 -0
  263. package/dist/repositories.mjs +33 -0
  264. package/dist/repositories.mjs.map +1 -0
  265. package/dist/sandbox/command.d.mts +18 -0
  266. package/dist/sandbox/execution-abort.d.mts +16 -0
  267. package/dist/sandbox/execution-abort.mjs +49 -0
  268. package/dist/sandbox/execution-abort.mjs.map +1 -0
  269. package/dist/sandbox/execution-environment.d.mts +25 -0
  270. package/dist/sandbox/execution-run-ledger.d.mts +115 -0
  271. package/dist/sandbox/execution-run-ledger.mjs +209 -0
  272. package/dist/sandbox/execution-run-ledger.mjs.map +1 -0
  273. package/dist/sandbox/execution.d.mts +54 -0
  274. package/dist/sandbox/execution.mjs +228 -0
  275. package/dist/sandbox/execution.mjs.map +1 -0
  276. package/dist/sandbox/harness-runner.d.mts +79 -0
  277. package/dist/sandbox/harness-runner.mjs +162 -0
  278. package/dist/sandbox/harness-runner.mjs.map +1 -0
  279. package/dist/sandbox/index.d.mts +9 -0
  280. package/dist/sandbox/index.mjs +7 -0
  281. package/dist/sandbox/task-environment.d.mts +50 -0
  282. package/dist/sandbox/task-environment.mjs +140 -0
  283. package/dist/sandbox/task-environment.mjs.map +1 -0
  284. package/dist/sandbox/workspace.d.mts +29 -0
  285. package/dist/sandbox/workspace.mjs +28 -0
  286. package/dist/sandbox/workspace.mjs.map +1 -0
  287. package/dist/schema/agent-route.d.mts +22 -0
  288. package/dist/schema/agent-route.mjs +15 -0
  289. package/dist/schema/agent-route.mjs.map +1 -0
  290. package/dist/schema/answer.d.mts +23 -0
  291. package/dist/schema/answer.mjs +21 -0
  292. package/dist/schema/answer.mjs.map +1 -0
  293. package/dist/schema/budget.d.mts +38 -0
  294. package/dist/schema/budget.mjs +30 -0
  295. package/dist/schema/budget.mjs.map +1 -0
  296. package/dist/schema/catalog.mjs +72 -0
  297. package/dist/schema/catalog.mjs.map +1 -0
  298. package/dist/schema/change.d.mts +117 -0
  299. package/dist/schema/change.mjs +68 -0
  300. package/dist/schema/change.mjs.map +1 -0
  301. package/dist/schema/common.d.mts +33 -0
  302. package/dist/{id-DwCihQr4.mjs → schema/common.mjs} +7 -14
  303. package/dist/schema/common.mjs.map +1 -0
  304. package/dist/schema/communication.d.mts +52 -0
  305. package/dist/schema/communication.mjs +35 -0
  306. package/dist/schema/communication.mjs.map +1 -0
  307. package/dist/schema/execution.d.mts +101 -0
  308. package/dist/schema/execution.mjs +86 -0
  309. package/dist/schema/execution.mjs.map +1 -0
  310. package/dist/schema/factory-config.d.mts +95 -0
  311. package/dist/schema/factory-config.mjs +60 -0
  312. package/dist/schema/factory-config.mjs.map +1 -0
  313. package/dist/schema/finding.d.mts +125 -0
  314. package/dist/schema/finding.mjs +67 -0
  315. package/dist/schema/finding.mjs.map +1 -0
  316. package/dist/schema/id.d.mts +43 -0
  317. package/dist/schema/id.mjs +32 -0
  318. package/dist/schema/id.mjs.map +1 -0
  319. package/dist/schema/outbox.d.mts +240 -0
  320. package/dist/schema/outbox.mjs +53 -0
  321. package/dist/schema/outbox.mjs.map +1 -0
  322. package/dist/schema/question-route.mjs +16 -0
  323. package/dist/schema/question-route.mjs.map +1 -0
  324. package/dist/schema/receipt.d.mts +81 -0
  325. package/dist/schema/receipt.mjs +94 -0
  326. package/dist/schema/receipt.mjs.map +1 -0
  327. package/dist/schema/repository.d.mts +26 -0
  328. package/dist/schema/repository.mjs +25 -0
  329. package/dist/schema/repository.mjs.map +1 -0
  330. package/dist/schema/session.d.mts +135 -0
  331. package/dist/schema/session.mjs +53 -0
  332. package/dist/schema/session.mjs.map +1 -0
  333. package/dist/schema/signal.d.mts +105 -0
  334. package/dist/schema/signal.mjs +81 -0
  335. package/dist/schema/signal.mjs.map +1 -0
  336. package/dist/schema/stored-session.mjs +10 -0
  337. package/dist/schema/stored-session.mjs.map +1 -0
  338. package/dist/schema/stored-task.mjs +20 -0
  339. package/dist/schema/stored-task.mjs.map +1 -0
  340. package/dist/schema/task-effect.d.mts +39 -0
  341. package/dist/schema/task-effect.mjs +29 -0
  342. package/dist/schema/task-effect.mjs.map +1 -0
  343. package/dist/schema/task-graph.d.mts +3134 -0
  344. package/dist/schema/task-graph.mjs +97 -0
  345. package/dist/schema/task-graph.mjs.map +1 -0
  346. package/dist/schema/task-message.d.mts +254 -0
  347. package/dist/schema/task-message.mjs +189 -0
  348. package/dist/schema/task-message.mjs.map +1 -0
  349. package/dist/schema/task.d.mts +272 -0
  350. package/dist/schema/task.mjs +199 -0
  351. package/dist/schema/task.mjs.map +1 -0
  352. package/dist/schema/transcript.d.mts +170 -0
  353. package/dist/schema/transcript.mjs +86 -0
  354. package/dist/schema/transcript.mjs.map +1 -0
  355. package/dist/schema/transitions.d.mts +50 -0
  356. package/dist/schema/transitions.mjs +303 -0
  357. package/dist/schema/transitions.mjs.map +1 -0
  358. package/dist/schema/work.d.mts +101 -0
  359. package/dist/schema/work.mjs +102 -0
  360. package/dist/schema/work.mjs.map +1 -0
  361. package/dist/signal-triage.d.mts +20 -0
  362. package/dist/signal-triage.mjs +85 -0
  363. package/dist/signal-triage.mjs.map +1 -0
  364. package/dist/signals.d.mts +19 -0
  365. package/dist/signals.mjs +19 -0
  366. package/dist/signals.mjs.map +1 -0
  367. package/dist/stall.d.mts +38 -0
  368. package/dist/stall.mjs +79 -0
  369. package/dist/stall.mjs.map +1 -0
  370. package/dist/storage.d.mts +4 -0
  371. package/dist/storage.mjs +4 -0
  372. package/dist/store/driver.d.mts +65 -0
  373. package/dist/store/driver.mjs +42 -0
  374. package/dist/store/driver.mjs.map +1 -0
  375. package/dist/store/engine.d.mts +485 -0
  376. package/dist/store/engine.mjs +2175 -0
  377. package/dist/store/engine.mjs.map +1 -0
  378. package/dist/store/memory.d.mts +7 -0
  379. package/dist/store/memory.mjs +52 -0
  380. package/dist/store/memory.mjs.map +1 -0
  381. package/dist/store/task-effects.d.mts +38 -0
  382. package/dist/store/task-effects.mjs +118 -0
  383. package/dist/store/task-effects.mjs.map +1 -0
  384. package/dist/store/task-graphs.d.mts +60 -0
  385. package/dist/store/task-graphs.mjs +212 -0
  386. package/dist/store/task-graphs.mjs.map +1 -0
  387. package/dist/store/task-messages.d.mts +136 -0
  388. package/dist/store/task-messages.mjs +475 -0
  389. package/dist/store/task-messages.mjs.map +1 -0
  390. package/dist/store/task-work.d.mts +65 -0
  391. package/dist/store/task-work.mjs +134 -0
  392. package/dist/store/task-work.mjs.map +1 -0
  393. package/dist/store/work-notifications.d.mts +19 -0
  394. package/dist/store/work-notifications.mjs +48 -0
  395. package/dist/store/work-notifications.mjs.map +1 -0
  396. package/dist/sweep.d.mts +57 -0
  397. package/dist/sweep.mjs +143 -0
  398. package/dist/sweep.mjs.map +1 -0
  399. package/dist/task-communication.d.mts +35 -0
  400. package/dist/task-communication.mjs +47 -0
  401. package/dist/task-communication.mjs.map +1 -0
  402. package/dist/task-graph-view.d.mts +264 -0
  403. package/dist/task-graph-view.mjs +17 -0
  404. package/dist/task-graph-view.mjs.map +1 -0
  405. package/dist/task-message-processing.d.mts +60 -0
  406. package/dist/task-message-processing.mjs +200 -0
  407. package/dist/task-message-processing.mjs.map +1 -0
  408. package/dist/task-protocols.d.mts +80 -0
  409. package/dist/task-protocols.mjs +47 -0
  410. package/dist/task-protocols.mjs.map +1 -0
  411. package/dist/tasks.d.mts +17 -0
  412. package/dist/tasks.mjs +17 -0
  413. package/dist/vercel-git.d.mts +21 -0
  414. package/dist/vercel-git.mjs +112 -0
  415. package/dist/vercel-git.mjs.map +1 -0
  416. package/dist/vercel.d.mts +33 -2
  417. package/dist/vercel.mjs +48 -3
  418. package/dist/vercel.mjs.map +1 -1
  419. package/dist/work-triage/eve-tool.d.mts +29 -0
  420. package/dist/work-triage/eve-tool.mjs +32 -0
  421. package/dist/work-triage/eve-tool.mjs.map +1 -0
  422. package/dist/work-triage/find-existing-work.d.mts +32 -0
  423. package/dist/work-triage/find-existing-work.mjs +31 -0
  424. package/dist/work-triage/find-existing-work.mjs.map +1 -0
  425. package/dist/work-triage/github.d.mts +15 -0
  426. package/dist/work-triage/github.mjs +14 -0
  427. package/dist/work-triage/github.mjs.map +1 -0
  428. package/dist/work-triage.d.mts +3 -0
  429. package/dist/work-triage.mjs +3 -0
  430. package/dist/workflows.d.mts +48 -0
  431. package/dist/workflows.mjs +86 -0
  432. package/dist/workflows.mjs.map +1 -0
  433. package/dist/workspace-diff-assembly.d.mts +33 -0
  434. package/dist/workspace-diff-assembly.mjs +95 -0
  435. package/dist/workspace-diff-assembly.mjs.map +1 -0
  436. package/dist/workspace-diff.d.mts +90 -0
  437. package/dist/workspace-diff.mjs +61 -0
  438. package/dist/workspace-diff.mjs.map +1 -0
  439. package/dist/workspace-snapshot.d.mts +26 -0
  440. package/dist/workspace-snapshot.mjs +80 -0
  441. package/dist/workspace-snapshot.mjs.map +1 -0
  442. package/package.json +129 -40
  443. package/dist/approval-CwhTP1XB.mjs +0 -269
  444. package/dist/approval-CwhTP1XB.mjs.map +0 -1
  445. package/dist/change-CzEAoFVE.mjs +0 -620
  446. package/dist/change-CzEAoFVE.mjs.map +0 -1
  447. package/dist/dispatch-B77cuPxh.d.mts +0 -713
  448. package/dist/driver-BJutB0PE.d.mts +0 -34
  449. package/dist/driver-Bbd25rNM.mjs +0 -23
  450. package/dist/driver-Bbd25rNM.mjs.map +0 -1
  451. package/dist/factory-config-BJcjsPKl.mjs +0 -86
  452. package/dist/factory-config-BJcjsPKl.mjs.map +0 -1
  453. package/dist/factory-config-D2yU3G0c.d.mts +0 -58
  454. package/dist/github-DXsxboUL.d.mts +0 -271
  455. package/dist/id-DwCihQr4.mjs.map +0 -1
  456. package/dist/index-Cy4jfXh5.d.mts +0 -67
  457. package/dist/index.mjs.map +0 -1
  458. package/dist/signal-CHVEmzvI.d.mts +0 -59
@@ -0,0 +1,134 @@
1
+ import { taskSchema } from "../schema/task.mjs";
2
+ import { InvalidTransitionError } from "../schema/transitions.mjs";
3
+ import { RecordNotFoundError, VersionConflictError } from "./driver.mjs";
4
+ import { assertTaskAdmission } from "./task-graphs.mjs";
5
+ import { z } from "zod";
6
+ import { isDeepStrictEqual } from "node:util";
7
+ //#region src/store/task-work.ts
8
+ /** Creates workflow-facing Task operations backed by canonical graph and Task stores. */
9
+ function createTaskWorkStore(options) {
10
+ const { driver, now, stores, workflows, update, restore } = options;
11
+ function parseTask(value) {
12
+ const task = taskSchema.parse(value);
13
+ workflows.validateStoredInput(task.work.workflow, task.work.input);
14
+ if (task.workResult) workflows.validateStoredOutput(task.work.workflow, task.workResult.output);
15
+ return task;
16
+ }
17
+ async function read(id) {
18
+ const record = await driver.get("tasks", id);
19
+ if (!record) throw new RecordNotFoundError("tasks", id);
20
+ const task = parseTask(record.value);
21
+ if (task.id !== id) throw new Error(`Task ${id} does not match its storage key`);
22
+ return {
23
+ task,
24
+ version: record.version,
25
+ work: task.work
26
+ };
27
+ }
28
+ async function recover(rootTaskId) {
29
+ const graph = await stores().graphs.get(rootTaskId);
30
+ if (!graph) throw new RecordNotFoundError("taskGraphs", rootTaskId);
31
+ const tasks = [];
32
+ for (const node of graph.nodes) {
33
+ const admission = parseTask(node.admission);
34
+ const task = parseTask(await stores().tasks.get(node.taskId) ?? await restore(admission));
35
+ assertTaskAdmission({
36
+ task,
37
+ admission
38
+ });
39
+ tasks.push(task);
40
+ }
41
+ return tasks;
42
+ }
43
+ function assertAttempt(task, expectAttempt) {
44
+ z.number().int().positive().parse(expectAttempt);
45
+ if (task.attempt !== expectAttempt) throw new Error(`Task ${task.id} is on attempt ${task.attempt}, not ${expectAttempt}`);
46
+ }
47
+ async function setWaiting(id, expectAttempt, waiting, phase) {
48
+ for (;;) {
49
+ const { task, version } = await read(id);
50
+ assertAttempt(task, expectAttempt);
51
+ if (task.state !== "running") throw new Error(`Task ${id} must be running to ${waiting ? "wait" : "resume"}`);
52
+ const next = taskSchema.parse({
53
+ ...task,
54
+ waitingForMessages: waiting,
55
+ workflowPhase: phase ?? task.workflowPhase,
56
+ lastProgressAt: waiting ? task.lastProgressAt : now(),
57
+ updatedAt: now()
58
+ });
59
+ if (task.waitingForMessages === waiting && next.workflowPhase === task.workflowPhase) return task;
60
+ await stores().receipts.append({
61
+ taskId: id,
62
+ repositoryIds: task.repositoryIds,
63
+ kind: task.kind,
64
+ state: waiting ? "waiting" : "resumed",
65
+ phase: "workflow",
66
+ attempt: task.attempt,
67
+ reason: waiting ? "Workflow is waiting for Task messages" : "Workflow resumed message processing",
68
+ dedupeKey: `work:${id}:${version}:${waiting ? "wait" : "resume"}`
69
+ });
70
+ try {
71
+ await update(next, version);
72
+ return next;
73
+ } catch (error) {
74
+ if (!(error instanceof VersionConflictError)) throw error;
75
+ }
76
+ }
77
+ }
78
+ async function complete(input, expectedWorkflow) {
79
+ const { task: { taskId: id, attempt: expectAttempt }, output: value } = input;
80
+ for (;;) {
81
+ const { task, work } = await read(id);
82
+ assertAttempt(task, expectAttempt);
83
+ if (expectedWorkflow !== void 0 && !isDeepStrictEqual(work.workflow, expectedWorkflow)) throw new Error(`Task ${id} uses workflow ${work.workflow.id}@${work.workflow.version}, not ${expectedWorkflow.id}@${expectedWorkflow.version}`);
84
+ if (task.state === "succeeded") {
85
+ const output = workflows.validateOutput(work.workflow, value);
86
+ if (!isDeepStrictEqual(task.workResult?.output, output)) throw new Error(`Task ${id} already recorded a different workflow output`);
87
+ return task;
88
+ }
89
+ try {
90
+ return await stores().tasks.transition(id, "succeeded", {
91
+ output: value,
92
+ expectAttempt,
93
+ expectFrom: task.state,
94
+ phase: "workflow"
95
+ });
96
+ } catch (error) {
97
+ if (error instanceof VersionConflictError) continue;
98
+ if (error instanceof InvalidTransitionError && (await read(id)).task.state === "succeeded") continue;
99
+ throw error;
100
+ }
101
+ }
102
+ }
103
+ return {
104
+ complete,
105
+ completeWorkflow: ({ task, workflow, output }) => complete({
106
+ task,
107
+ output
108
+ }, workflow),
109
+ waitForMessages: ({ task: { taskId, attempt }, phase }) => setWaiting(taskId, attempt, true, phase),
110
+ resume: ({ task: { taskId, attempt } }) => setWaiting(taskId, attempt, false),
111
+ recover,
112
+ async usage(rootTaskId) {
113
+ const tasks = await recover(rootTaskId);
114
+ let micros = 0;
115
+ let inputTokens = 0;
116
+ let outputTokens = 0;
117
+ for (const task of tasks) {
118
+ micros += Math.round((task.usage?.costUsd ?? task.settledUsd ?? 0) * 1e6);
119
+ inputTokens += task.usage?.inputTokens ?? 0;
120
+ outputTokens += task.usage?.outputTokens ?? 0;
121
+ }
122
+ return {
123
+ costUsd: micros / 1e6,
124
+ inputTokens,
125
+ outputTokens,
126
+ taskCount: tasks.length
127
+ };
128
+ }
129
+ };
130
+ }
131
+ //#endregion
132
+ export { createTaskWorkStore };
133
+
134
+ //# sourceMappingURL=task-work.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-work.mjs","names":[],"sources":["../../src/store/task-work.ts"],"sourcesContent":["import { isDeepStrictEqual } from \"node:util\";\nimport { z } from \"zod\";\nimport type { IsoDateTimeClock } from \"../schema/common\";\nimport type { TaskAttemptRef } from \"../schema/execution\";\nimport type { TaskId } from \"../schema/id\";\nimport { taskSchema, type Task } from \"../schema/task\";\nimport { InvalidTransitionError } from \"../schema/transitions\";\nimport type { JsonValue, WorkflowBinding } from \"../schema/work\";\nimport type { WorkflowRegistry } from \"../workflows\";\nimport { RecordNotFoundError, VersionConflictError, type StoreDriver } from \"./driver\";\nimport type { FactoryStores } from \"./engine\";\nimport { assertTaskAdmission } from \"./task-graphs\";\n\n/** Workflow-facing Task operations for completion, message waiting, recovery, and usage aggregation. */\nexport interface TaskWorkStore {\n /** Complete through the dynamic registry boundary, which validates unknown output at runtime. */\n complete(input: CompleteTaskWorkInput): Promise<Task>;\n /** Complete work while statically checking output against its exact workflow binding. */\n completeWorkflow<Output extends JsonValue>(\n input: CompleteWorkflowTaskWorkInput<Output>,\n ): Promise<Task>;\n waitForMessages(input: WaitForTaskMessagesInput): Promise<Task>;\n resume(input: ResumeTaskWorkInput): Promise<Task>;\n /** Repair admitted creation snapshots by direct graph IDs, never by scanning the bucket. */\n recover(rootTaskId: TaskId): Promise<readonly Task[]>;\n /** Each Task contributes local measured usage once; no parent roll-up is charged again. */\n usage(rootTaskId: TaskId): Promise<TaskWorkUsage>;\n}\n\n/** Exact Task attempt and candidate workflow output used to complete work. */\nexport interface CompleteTaskWorkInput {\n task: TaskAttemptRef;\n output: unknown;\n}\n\n/** Exact Task attempt, workflow contract, and statically checked output used to complete work. */\nexport interface CompleteWorkflowTaskWorkInput<Output extends JsonValue = JsonValue> {\n task: TaskAttemptRef;\n workflow: WorkflowBinding<JsonValue, Output>;\n output: NoInfer<Output>;\n}\n\n/** Aggregated measured usage across one canonical Task graph. */\nexport interface TaskWorkUsage {\n costUsd: number;\n inputTokens: number;\n outputTokens: number;\n taskCount: number;\n}\n\n/** Exact running Task attempt and optional workflow phase used to await messages. */\nexport interface WaitForTaskMessagesInput {\n task: TaskAttemptRef;\n phase?: string;\n}\n\n/** Exact running Task attempt to resume after message delivery. */\nexport interface ResumeTaskWorkInput {\n task: TaskAttemptRef;\n}\n\n/** Canonical Task graph, receipt, and Task capabilities used by workflow-facing operations. */\nexport type TaskWorkStores = Pick<FactoryStores, \"graphs\" | \"receipts\" | \"tasks\">;\n\n/** Engine-owned dependencies used to construct workflow-facing Task operations. */\nexport interface CreateTaskWorkStoreOptions {\n driver: StoreDriver;\n now: IsoDateTimeClock;\n stores: () => TaskWorkStores;\n workflows: WorkflowRegistry;\n update(task: Task, version: number): Promise<void>;\n restore(task: Task): Promise<Task>;\n}\n\n/** Creates workflow-facing Task operations backed by canonical graph and Task stores. */\nexport function createTaskWorkStore(options: CreateTaskWorkStoreOptions): TaskWorkStore {\n const { driver, now, stores, workflows, update, restore } = options;\n function parseTask(value: unknown): Task {\n const task = taskSchema.parse(value);\n workflows.validateStoredInput(task.work.workflow, task.work.input);\n if (task.workResult) workflows.validateStoredOutput(task.work.workflow, task.workResult.output);\n return task;\n }\n async function read(id: TaskId) {\n const record = await driver.get(\"tasks\", id);\n if (!record) throw new RecordNotFoundError(\"tasks\", id);\n const task = parseTask(record.value);\n if (task.id !== id) throw new Error(`Task ${id} does not match its storage key`);\n return { task, version: record.version, work: task.work };\n }\n async function recover(rootTaskId: TaskId): Promise<readonly Task[]> {\n const graph = await stores().graphs.get(rootTaskId);\n if (!graph) throw new RecordNotFoundError(\"taskGraphs\", rootTaskId);\n const tasks: Task[] = [];\n for (const node of graph.nodes) {\n const admission = parseTask(node.admission);\n const existing = await stores().tasks.get(node.taskId);\n const task = parseTask(existing ?? (await restore(admission)));\n assertTaskAdmission({ task, admission });\n tasks.push(task);\n }\n return tasks;\n }\n function assertAttempt(task: Task, expectAttempt: number) {\n z.number().int().positive().parse(expectAttempt);\n if (task.attempt !== expectAttempt)\n throw new Error(`Task ${task.id} is on attempt ${task.attempt}, not ${expectAttempt}`);\n }\n async function setWaiting(\n id: TaskId,\n expectAttempt: number,\n waiting: boolean,\n phase?: string,\n ): Promise<Task> {\n for (;;) {\n const { task, version } = await read(id);\n assertAttempt(task, expectAttempt);\n if (task.state !== \"running\")\n throw new Error(`Task ${id} must be running to ${waiting ? \"wait\" : \"resume\"}`);\n const next = taskSchema.parse({\n ...task,\n waitingForMessages: waiting,\n workflowPhase: phase ?? task.workflowPhase,\n lastProgressAt: waiting ? task.lastProgressAt : now(),\n updatedAt: now(),\n });\n if (task.waitingForMessages === waiting && next.workflowPhase === task.workflowPhase)\n return task;\n await stores().receipts.append({\n taskId: id,\n repositoryIds: task.repositoryIds,\n kind: task.kind,\n state: waiting ? \"waiting\" : \"resumed\",\n phase: \"workflow\",\n attempt: task.attempt,\n reason: waiting\n ? \"Workflow is waiting for Task messages\"\n : \"Workflow resumed message processing\",\n dedupeKey: `work:${id}:${version}:${waiting ? \"wait\" : \"resume\"}`,\n });\n try {\n await update(next, version);\n return next;\n } catch (error) {\n if (!(error instanceof VersionConflictError)) throw error;\n }\n }\n }\n async function complete(\n input: CompleteTaskWorkInput,\n expectedWorkflow?: WorkflowBinding,\n ): Promise<Task> {\n const {\n task: { taskId: id, attempt: expectAttempt },\n output: value,\n } = input;\n for (;;) {\n const { task, work } = await read(id);\n assertAttempt(task, expectAttempt);\n if (expectedWorkflow !== undefined && !isDeepStrictEqual(work.workflow, expectedWorkflow)) {\n throw new Error(\n `Task ${id} uses workflow ${work.workflow.id}@${work.workflow.version}, not ${expectedWorkflow.id}@${expectedWorkflow.version}`,\n );\n }\n if (task.state === \"succeeded\") {\n const output = workflows.validateOutput(work.workflow, value);\n if (!isDeepStrictEqual(task.workResult?.output, output)) {\n throw new Error(`Task ${id} already recorded a different workflow output`);\n }\n return task;\n }\n try {\n return await stores().tasks.transition(id, \"succeeded\", {\n output: value,\n expectAttempt,\n expectFrom: task.state,\n phase: \"workflow\",\n });\n } catch (error) {\n if (error instanceof VersionConflictError) continue;\n if (error instanceof InvalidTransitionError && (await read(id)).task.state === \"succeeded\")\n continue;\n throw error;\n }\n }\n }\n return {\n complete,\n completeWorkflow: ({ task, workflow, output }) => complete({ task, output }, workflow),\n waitForMessages: ({ task: { taskId, attempt }, phase }) =>\n setWaiting(taskId, attempt, true, phase),\n resume: ({ task: { taskId, attempt } }) => setWaiting(taskId, attempt, false),\n recover,\n async usage(rootTaskId) {\n const tasks = await recover(rootTaskId);\n let micros = 0;\n let inputTokens = 0;\n let outputTokens = 0;\n for (const task of tasks) {\n micros += Math.round((task.usage?.costUsd ?? task.settledUsd ?? 0) * 1_000_000);\n inputTokens += task.usage?.inputTokens ?? 0;\n outputTokens += task.usage?.outputTokens ?? 0;\n }\n return { costUsd: micros / 1_000_000, inputTokens, outputTokens, taskCount: tasks.length };\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import "../schema/task.mjs";
2
+ import { z } from "zod";
3
+ //#region src/store/work-notifications.d.ts
4
+ /** Validates a stable wakeup that addresses canonical work by root graph. */
5
+ declare const workNotificationSchema: z.ZodObject<{
6
+ rootTaskId: z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>;
7
+ key: z.ZodString;
8
+ }, z.core.$strict>;
9
+ /** Retry-safe notification telling a consumer to reread one canonical Task graph. */
10
+ type WorkNotification = z.infer<typeof workNotificationSchema>;
11
+ /** Application transport for post-commit work wakeups and delivery-failure reporting. */
12
+ interface WorkNotifications {
13
+ publish(event: WorkNotification): Promise<void>;
14
+ /** The source write already committed. Report transport failure without pretending it rolled back. */
15
+ onError(error: unknown, event: WorkNotification): void;
16
+ }
17
+ //#endregion
18
+ export { WorkNotification, WorkNotifications, workNotificationSchema };
19
+ //# sourceMappingURL=work-notifications.d.mts.map
@@ -0,0 +1,48 @@
1
+ import { taskIdSchema } from "../schema/id.mjs";
2
+ import { z } from "zod";
3
+ import { isDeepStrictEqual } from "node:util";
4
+ //#region src/store/work-notifications.ts
5
+ /** Validates a stable wakeup that addresses canonical work by root graph. */
6
+ const workNotificationSchema = z.strictObject({
7
+ rootTaskId: taskIdSchema.describe("Canonical graph to reconcile; never an execution authorization."),
8
+ key: z.string().min(1).max(256).describe("Stable identity of the committed source change.")
9
+ }).describe("Durable work wakeup. Consumers reread canonical state and tolerate duplicate delivery.");
10
+ /** Creates a best-effort post-commit notifier whose failures never roll back source writes. */
11
+ function createWorkNotifier(options) {
12
+ async function publish(event) {
13
+ if (!options) return;
14
+ try {
15
+ await options.publish(event);
16
+ } catch (error) {
17
+ try {
18
+ options.onError(error, event);
19
+ } catch {}
20
+ }
21
+ }
22
+ function schedulingState(task) {
23
+ return [
24
+ task.state,
25
+ task.attempt,
26
+ task.approval,
27
+ task.waitingForMessages,
28
+ task.workflowPhase,
29
+ task.changeId,
30
+ task.questionTaskId,
31
+ task.answerEventIds
32
+ ];
33
+ }
34
+ return {
35
+ publish,
36
+ async task(task, previous, version) {
37
+ if (previous && isDeepStrictEqual(schedulingState(task), schedulingState(previous))) return;
38
+ await publish({
39
+ rootTaskId: task.rootTaskId,
40
+ key: `task:${task.id}:${version}`
41
+ });
42
+ }
43
+ };
44
+ }
45
+ //#endregion
46
+ export { createWorkNotifier, workNotificationSchema };
47
+
48
+ //# sourceMappingURL=work-notifications.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"work-notifications.mjs","names":[],"sources":["../../src/store/work-notifications.ts"],"sourcesContent":["import { isDeepStrictEqual } from \"node:util\";\nimport { z } from \"zod\";\nimport { taskIdSchema } from \"../schema/id\";\nimport type { Task } from \"../schema/task\";\n\n/** Validates a stable wakeup that addresses canonical work by root graph. */\nexport const workNotificationSchema = z\n .strictObject({\n rootTaskId: taskIdSchema.describe(\n \"Canonical graph to reconcile; never an execution authorization.\",\n ),\n key: z.string().min(1).max(256).describe(\"Stable identity of the committed source change.\"),\n })\n .describe(\n \"Durable work wakeup. Consumers reread canonical state and tolerate duplicate delivery.\",\n );\n/** Retry-safe notification telling a consumer to reread one canonical Task graph. */\nexport type WorkNotification = z.infer<typeof workNotificationSchema>;\n/** Application transport for post-commit work wakeups and delivery-failure reporting. */\nexport interface WorkNotifications {\n publish(event: WorkNotification): Promise<void>;\n /** The source write already committed. Report transport failure without pretending it rolled back. */\n onError(error: unknown, event: WorkNotification): void;\n}\n\n/** Creates a best-effort post-commit notifier whose failures never roll back source writes. */\nexport function createWorkNotifier(options?: WorkNotifications) {\n async function publish(event: WorkNotification): Promise<void> {\n if (!options) return;\n try {\n await options.publish(event);\n } catch (error) {\n // Reporting must not turn a committed CAS write into an apparent write failure.\n try {\n options.onError(error, event);\n } catch {\n /* Recovery rediscovers canonical work. */\n }\n }\n }\n function schedulingState(task: Task) {\n return [\n task.state,\n task.attempt,\n task.approval,\n task.waitingForMessages,\n task.workflowPhase,\n task.changeId,\n task.questionTaskId,\n task.answerEventIds,\n ];\n }\n return {\n publish,\n async task(task: Task, previous: Task | null, version: number) {\n if (previous && isDeepStrictEqual(schedulingState(task), schedulingState(previous))) return;\n await publish({ rootTaskId: task.rootTaskId, key: `task:${task.id}:${version}` });\n },\n };\n}\n"],"mappings":";;;;;AAMA,MAAa,yBAAyB,EACnC,aAAa;CACZ,YAAY,aAAa,SACvB,iEACF;CACA,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS,iDAAiD;AAC5F,CAAC,CAAC,CACD,SACC,wFACF;;AAWF,SAAgB,mBAAmB,SAA6B;CAC9D,eAAe,QAAQ,OAAwC;EAC7D,IAAI,CAAC,SAAS;EACd,IAAI;GACF,MAAM,QAAQ,QAAQ,KAAK;EAC7B,SAAS,OAAO;GAEd,IAAI;IACF,QAAQ,QAAQ,OAAO,KAAK;GAC9B,QAAQ,CAER;EACF;CACF;CACA,SAAS,gBAAgB,MAAY;EACnC,OAAO;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;EACP;CACF;CACA,OAAO;EACL;EACA,MAAM,KAAK,MAAY,UAAuB,SAAiB;GAC7D,IAAI,YAAY,kBAAkB,gBAAgB,IAAI,GAAG,gBAAgB,QAAQ,CAAC,GAAG;GACrF,MAAM,QAAQ;IAAE,YAAY,KAAK;IAAY,KAAK,QAAQ,KAAK,GAAG,GAAG;GAAU,CAAC;EAClF;CACF;AACF"}
@@ -0,0 +1,57 @@
1
+ import { TaskId } from "./schema/id.mjs";
2
+ import { Repository } from "./schema/repository.mjs";
3
+ import { ExecutionReference, Task } from "./schema/task.mjs";
4
+ import { AgentRouteKey } from "./agent-routes.mjs";
5
+ import { FactoryStores } from "./store/engine.mjs";
6
+ import { DispatchBudget, DispatchRefusalCode } from "./dispatch.mjs";
7
+ //#region src/sweep.d.ts
8
+ /** Graph, receipt, repository, and Task capabilities required by queued-work dispatch. */
9
+ type SweepQueuedStores = Pick<FactoryStores, "graphs" | "receipts" | "repositories" | "tasks">;
10
+ /**
11
+ * Single-repository adapter for an exact agent route. Supplied by the app, which knows its
12
+ * agents' addresses. Returns the provider's execution reference when it has one.
13
+ */
14
+ type TaskLauncher = (task: Task, repository: Repository) => Promise<ExecutionReference>;
15
+ /** Exact-route launchers, budget gate, and pass bounds for queued Task dispatch. */
16
+ interface SweepQueuedOptions {
17
+ /** Single-repository agent adapters keyed by routeKey(binding), e.g. code-change@1. */
18
+ launchers: Readonly<Partial<Record<AgentRouteKey, TaskLauncher>>>;
19
+ /** Reserve-before-execution limits, passed through to every dispatch. */
20
+ budget?: DispatchBudget;
21
+ /** Maximum task launches attempted in one pass; omitted means no limit. */
22
+ maxDispatches?: number;
23
+ /** A dispatcher-wide snapshot avoids another complete task read. */
24
+ tasks?: readonly Task[];
25
+ }
26
+ /** Tasks dispatched, deferred by a gate, or failed by one queued-work pass. */
27
+ interface SweepQueuedResult {
28
+ readonly dispatched: readonly TaskId[];
29
+ /** Tasks left in the queue because a declared gate may become eligible later. */
30
+ readonly skipped: readonly {
31
+ readonly taskId: TaskId;
32
+ readonly reasonCode: SweepSkipReasonCode;
33
+ readonly reason: string;
34
+ }[];
35
+ /** Tasks whose routing is invalid or whose launch threw. */
36
+ readonly failed: readonly {
37
+ readonly taskId: TaskId;
38
+ readonly reasonCode: SweepFailureReasonCode;
39
+ readonly reason: string;
40
+ }[];
41
+ }
42
+ /** Stable reason a queued Task remained eligible for a later dispatch pass. */
43
+ type SweepSkipReasonCode = DispatchRefusalCode | "workflow_owned" | "awaiting_approval" | "dispatch_limit" | "task_changed";
44
+ /** Stable reason a queued Task could not be routed or launched. */
45
+ type SweepFailureReasonCode = "invalid_repository_scope" | "repository_not_found" | "launcher_not_registered" | "launch_failed";
46
+ /**
47
+ * One pass of the factory's dispatcher, meant to run on a schedule inside the
48
+ * deployment: every queued task that is allowed to run is started, in
49
+ * creation order. Nothing outside the factory ever starts an agent; the CLI
50
+ * only writes tasks and approvals, and this picks them up.
51
+ * Idempotent by construction: dispatchTask's single-winner transition means
52
+ * two overlapping sweeps cannot start the same task twice.
53
+ */
54
+ declare function sweepQueued(stores: SweepQueuedStores, options: SweepQueuedOptions): Promise<SweepQueuedResult>;
55
+ //#endregion
56
+ export { SweepFailureReasonCode, SweepQueuedOptions, SweepQueuedResult, SweepQueuedStores, SweepSkipReasonCode, TaskLauncher, sweepQueued };
57
+ //# sourceMappingURL=sweep.d.mts.map
package/dist/sweep.mjs ADDED
@@ -0,0 +1,143 @@
1
+ import { InvalidTransitionError } from "./schema/transitions.mjs";
2
+ import { routeKey } from "./agent-routes.mjs";
3
+ import { VersionConflictError } from "./store/driver.mjs";
4
+ import { DispatchRefusedError, dispatchTask } from "./dispatch.mjs";
5
+ //#region src/sweep.ts
6
+ async function failUnrouteable(stores, task, reasonCode, reason, result) {
7
+ try {
8
+ await stores.tasks.transition(task.id, "failed", {
9
+ reason,
10
+ expectFrom: "queued"
11
+ });
12
+ result.failed.push({
13
+ taskId: task.id,
14
+ reasonCode,
15
+ reason
16
+ });
17
+ } catch (error) {
18
+ if (error instanceof InvalidTransitionError || error instanceof VersionConflictError) {
19
+ result.skipped.push({
20
+ taskId: task.id,
21
+ reasonCode: "task_changed",
22
+ reason: "task changed during routing"
23
+ });
24
+ return;
25
+ }
26
+ throw error;
27
+ }
28
+ }
29
+ /**
30
+ * One pass of the factory's dispatcher, meant to run on a schedule inside the
31
+ * deployment: every queued task that is allowed to run is started, in
32
+ * creation order. Nothing outside the factory ever starts an agent; the CLI
33
+ * only writes tasks and approvals, and this picks them up.
34
+ * Idempotent by construction: dispatchTask's single-winner transition means
35
+ * two overlapping sweeps cannot start the same task twice.
36
+ */
37
+ async function sweepQueued(stores, options) {
38
+ const result = {
39
+ dispatched: [],
40
+ skipped: [],
41
+ failed: []
42
+ };
43
+ const maxDispatches = options.maxDispatches ?? Number.POSITIVE_INFINITY;
44
+ if (!(Number.isInteger(maxDispatches) || maxDispatches === Number.POSITIVE_INFINITY) || maxDispatches < 1) throw new Error("maxDispatches must be a positive integer");
45
+ let attempted = 0;
46
+ const taskSnapshot = options.tasks ?? await stores.tasks.list();
47
+ const budgetSnapshot = options.budget?.tasks ?? (options.budget && options.tasks ? await stores.tasks.list() : taskSnapshot);
48
+ const budgetTasks = new Map(budgetSnapshot.map((task) => [task.id, task]));
49
+ const queued = taskSnapshot.filter((task) => task.state === "queued").sort((a, b) => b.attempt - a.attempt || a.createdAt.localeCompare(b.createdAt));
50
+ for (const task of queued) {
51
+ const route = task.work.route;
52
+ if (route === void 0) {
53
+ result.skipped.push({
54
+ taskId: task.id,
55
+ reasonCode: "workflow_owned",
56
+ reason: "no agent route; workflow owns execution"
57
+ });
58
+ continue;
59
+ }
60
+ const [repositoryId] = task.repositoryIds;
61
+ if (task.repositoryIds.length !== 1 || repositoryId === void 0) {
62
+ await failUnrouteable(stores, task, "invalid_repository_scope", "sweep launcher adapter requires exactly one repository", result);
63
+ continue;
64
+ }
65
+ if (task.approval === "required") {
66
+ result.skipped.push({
67
+ taskId: task.id,
68
+ reasonCode: "awaiting_approval",
69
+ reason: "awaiting human approval"
70
+ });
71
+ continue;
72
+ }
73
+ const key = routeKey(route);
74
+ const launcher = Object.hasOwn(options.launchers, key) ? options.launchers[key] : void 0;
75
+ if (launcher === void 0) {
76
+ await failUnrouteable(stores, task, "launcher_not_registered", `no registered launcher handles agent route ${key}`, result);
77
+ continue;
78
+ }
79
+ if (!await stores.graphs.dependenciesSatisfied({
80
+ rootTaskId: task.rootTaskId,
81
+ taskId: task.id
82
+ })) {
83
+ result.skipped.push({
84
+ taskId: task.id,
85
+ reasonCode: "dependencies_unsatisfied",
86
+ reason: "graph dependencies must all be succeeded before dispatch"
87
+ });
88
+ continue;
89
+ }
90
+ if (attempted >= maxDispatches) {
91
+ result.skipped.push({
92
+ taskId: task.id,
93
+ reasonCode: "dispatch_limit",
94
+ reason: "per-sweep dispatch limit reached"
95
+ });
96
+ continue;
97
+ }
98
+ const repository = await stores.repositories.get(repositoryId);
99
+ if (repository === null) {
100
+ await failUnrouteable(stores, task, "repository_not_found", "task has no repository", result);
101
+ continue;
102
+ }
103
+ try {
104
+ const dispatched = await dispatchTask(stores, {
105
+ taskId: task.id,
106
+ route,
107
+ launch: (dispatched) => {
108
+ attempted += 1;
109
+ return launcher(dispatched, repository);
110
+ },
111
+ budget: options.budget === void 0 ? void 0 : {
112
+ ...options.budget,
113
+ tasks: [...budgetTasks.values()]
114
+ }
115
+ });
116
+ budgetTasks.set(dispatched.id, dispatched);
117
+ result.dispatched.push(task.id);
118
+ } catch (error) {
119
+ if (options.budget !== void 0) {
120
+ const current = await stores.tasks.get(task.id).catch(() => null);
121
+ if (current !== null) budgetTasks.set(current.id, current);
122
+ }
123
+ if (error instanceof DispatchRefusedError) {
124
+ result.skipped.push({
125
+ taskId: task.id,
126
+ reasonCode: error.code,
127
+ reason: error.reason
128
+ });
129
+ continue;
130
+ }
131
+ result.failed.push({
132
+ taskId: task.id,
133
+ reasonCode: "launch_failed",
134
+ reason: error instanceof Error ? error.message : String(error)
135
+ });
136
+ }
137
+ }
138
+ return result;
139
+ }
140
+ //#endregion
141
+ export { sweepQueued };
142
+
143
+ //# sourceMappingURL=sweep.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sweep.mjs","names":[],"sources":["../src/sweep.ts"],"sourcesContent":["import { routeKey, type AgentRouteKey } from \"./agent-routes\";\nimport { dispatchTask, DispatchRefusedError, type DispatchBudget } from \"./dispatch\";\nimport type { DispatchRefusalCode } from \"./dispatch\";\nimport type { TaskId } from \"./schema/id\";\nimport type { Repository } from \"./schema/repository\";\nimport type { ExecutionReference, Task } from \"./schema/task\";\nimport { InvalidTransitionError } from \"./schema/transitions\";\nimport { VersionConflictError } from \"./store/driver\";\nimport type { FactoryStores } from \"./store/engine\";\n\n/** Graph, receipt, repository, and Task capabilities required by queued-work dispatch. */\nexport type SweepQueuedStores = Pick<\n FactoryStores,\n \"graphs\" | \"receipts\" | \"repositories\" | \"tasks\"\n>;\n\n/**\n * Single-repository adapter for an exact agent route. Supplied by the app, which knows its\n * agents' addresses. Returns the provider's execution reference when it has one.\n */\nexport type TaskLauncher = (task: Task, repository: Repository) => Promise<ExecutionReference>;\n\n/** Exact-route launchers, budget gate, and pass bounds for queued Task dispatch. */\nexport interface SweepQueuedOptions {\n /** Single-repository agent adapters keyed by routeKey(binding), e.g. code-change@1. */\n launchers: Readonly<Partial<Record<AgentRouteKey, TaskLauncher>>>;\n /** Reserve-before-execution limits, passed through to every dispatch. */\n budget?: DispatchBudget;\n /** Maximum task launches attempted in one pass; omitted means no limit. */\n maxDispatches?: number;\n /** A dispatcher-wide snapshot avoids another complete task read. */\n tasks?: readonly Task[];\n}\n\n/** Tasks dispatched, deferred by a gate, or failed by one queued-work pass. */\nexport interface SweepQueuedResult {\n readonly dispatched: readonly TaskId[];\n /** Tasks left in the queue because a declared gate may become eligible later. */\n readonly skipped: readonly {\n readonly taskId: TaskId;\n readonly reasonCode: SweepSkipReasonCode;\n readonly reason: string;\n }[];\n /** Tasks whose routing is invalid or whose launch threw. */\n readonly failed: readonly {\n readonly taskId: TaskId;\n readonly reasonCode: SweepFailureReasonCode;\n readonly reason: string;\n }[];\n}\n\n/** Stable reason a queued Task remained eligible for a later dispatch pass. */\nexport type SweepSkipReasonCode =\n | DispatchRefusalCode\n | \"workflow_owned\"\n | \"awaiting_approval\"\n | \"dispatch_limit\"\n | \"task_changed\";\n\n/** Stable reason a queued Task could not be routed or launched. */\nexport type SweepFailureReasonCode =\n | \"invalid_repository_scope\"\n | \"repository_not_found\"\n | \"launcher_not_registered\"\n | \"launch_failed\";\n\ntype MutableSweepQueuedResult = {\n dispatched: TaskId[];\n skipped: { taskId: TaskId; reasonCode: SweepSkipReasonCode; reason: string }[];\n failed: { taskId: TaskId; reasonCode: SweepFailureReasonCode; reason: string }[];\n};\n\nasync function failUnrouteable(\n stores: SweepQueuedStores,\n task: Task,\n reasonCode: SweepFailureReasonCode,\n reason: string,\n result: MutableSweepQueuedResult,\n): Promise<void> {\n try {\n await stores.tasks.transition(task.id, \"failed\", { reason, expectFrom: \"queued\" });\n result.failed.push({ taskId: task.id, reasonCode, reason });\n } catch (error) {\n if (error instanceof InvalidTransitionError || error instanceof VersionConflictError) {\n result.skipped.push({\n taskId: task.id,\n reasonCode: \"task_changed\",\n reason: \"task changed during routing\",\n });\n return;\n }\n throw error;\n }\n}\n\n/**\n * One pass of the factory's dispatcher, meant to run on a schedule inside the\n * deployment: every queued task that is allowed to run is started, in\n * creation order. Nothing outside the factory ever starts an agent; the CLI\n * only writes tasks and approvals, and this picks them up.\n * Idempotent by construction: dispatchTask's single-winner transition means\n * two overlapping sweeps cannot start the same task twice.\n */\nexport async function sweepQueued(\n stores: SweepQueuedStores,\n options: SweepQueuedOptions,\n): Promise<SweepQueuedResult> {\n const result: MutableSweepQueuedResult = { dispatched: [], skipped: [], failed: [] };\n const maxDispatches = options.maxDispatches ?? Number.POSITIVE_INFINITY;\n if (\n !(Number.isInteger(maxDispatches) || maxDispatches === Number.POSITIVE_INFINITY) ||\n maxDispatches < 1\n ) {\n throw new Error(\"maxDispatches must be a positive integer\");\n }\n let attempted = 0;\n const taskSnapshot = options.tasks ?? (await stores.tasks.list());\n const budgetSnapshot =\n options.budget?.tasks ??\n (options.budget && options.tasks ? await stores.tasks.list() : taskSnapshot);\n const budgetTasks = new Map(budgetSnapshot.map((task) => [task.id, task]));\n const queued = taskSnapshot\n .filter((task) => task.state === \"queued\")\n .sort((a, b) => b.attempt - a.attempt || a.createdAt.localeCompare(b.createdAt));\n\n for (const task of queued) {\n const route = task.work.route;\n if (route === undefined) {\n result.skipped.push({\n taskId: task.id,\n reasonCode: \"workflow_owned\",\n reason: \"no agent route; workflow owns execution\",\n });\n continue;\n }\n const [repositoryId] = task.repositoryIds;\n if (task.repositoryIds.length !== 1 || repositoryId === undefined) {\n await failUnrouteable(\n stores,\n task,\n \"invalid_repository_scope\",\n \"sweep launcher adapter requires exactly one repository\",\n result,\n );\n continue;\n }\n if (task.approval === \"required\") {\n result.skipped.push({\n taskId: task.id,\n reasonCode: \"awaiting_approval\",\n reason: \"awaiting human approval\",\n });\n continue;\n }\n const key = routeKey(route);\n const launcher = Object.hasOwn(options.launchers, key) ? options.launchers[key] : undefined;\n if (launcher === undefined) {\n await failUnrouteable(\n stores,\n task,\n \"launcher_not_registered\",\n `no registered launcher handles agent route ${key}`,\n result,\n );\n continue;\n }\n if (\n !(await stores.graphs.dependenciesSatisfied({\n rootTaskId: task.rootTaskId,\n taskId: task.id,\n }))\n ) {\n result.skipped.push({\n taskId: task.id,\n reasonCode: \"dependencies_unsatisfied\",\n reason: \"graph dependencies must all be succeeded before dispatch\",\n });\n continue;\n }\n if (attempted >= maxDispatches) {\n result.skipped.push({\n taskId: task.id,\n reasonCode: \"dispatch_limit\",\n reason: \"per-sweep dispatch limit reached\",\n });\n continue;\n }\n const repository = await stores.repositories.get(repositoryId);\n if (repository === null) {\n await failUnrouteable(stores, task, \"repository_not_found\", \"task has no repository\", result);\n continue;\n }\n try {\n const dispatched = await dispatchTask(stores, {\n taskId: task.id,\n route,\n launch: (dispatched) => {\n attempted += 1;\n return launcher(dispatched, repository);\n },\n budget:\n options.budget === undefined\n ? undefined\n : { ...options.budget, tasks: [...budgetTasks.values()] },\n });\n budgetTasks.set(dispatched.id, dispatched);\n result.dispatched.push(task.id);\n } catch (error) {\n if (options.budget !== undefined) {\n const current = await stores.tasks.get(task.id).catch(() => null);\n if (current !== null) budgetTasks.set(current.id, current);\n }\n if (error instanceof DispatchRefusedError) {\n // Dependencies not ready, or another sweep won the race. Leave it.\n result.skipped.push({ taskId: task.id, reasonCode: error.code, reason: error.reason });\n continue;\n }\n result.failed.push({\n taskId: task.id,\n reasonCode: \"launch_failed\",\n reason: error instanceof Error ? error.message : String(error),\n });\n }\n }\n return result;\n}\n"],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { Task } from "./schema/task.mjs";
2
+ import { MaybePromise } from "./schema/common.mjs";
3
+ import { CommunicationEvent } from "./schema/communication.mjs";
4
+ import { Receipt } from "./schema/receipt.mjs";
5
+ import { FactoryStores } from "./store/engine.mjs";
6
+ //#region src/task-communication.d.ts
7
+ /** Outbox, receipt, and Task capabilities required by communication reconciliation. */
8
+ type TaskCommunicationStores = Pick<FactoryStores, "outbox" | "receipts" | "tasks">;
9
+ /** Number of connector-neutral events newly enqueued during reconciliation. */
10
+ interface TaskCommunicationResult {
11
+ enqueued: number;
12
+ }
13
+ /** Repairs pending Task communication projections against the durable outbox. */
14
+ type TaskCommunicationReconciler<Stores extends TaskCommunicationStores = TaskCommunicationStores> = (stores: Stores, snapshot?: readonly Task[]) => Promise<TaskCommunicationResult>;
15
+ /** Durable Task and receipt context supplied to a lifecycle event projection. */
16
+ interface TaskLifecycleProjectionInput<Stores extends TaskCommunicationStores = TaskCommunicationStores> {
17
+ stores: Stores;
18
+ tasks: readonly Task[];
19
+ task: Task;
20
+ receipt: Receipt;
21
+ }
22
+ /** Application policy for projecting durable task state into connector-neutral events. */
23
+ interface TaskCommunicationProjection<Stores extends TaskCommunicationStores = TaskCommunicationStores> {
24
+ question(task: Task): MaybePromise<readonly CommunicationEvent[]>;
25
+ lifecycle(input: TaskLifecycleProjectionInput<Stores>): MaybePromise<readonly CommunicationEvent[]>;
26
+ }
27
+ /**
28
+ * Build the generic durable receipt reconciler around an application's event
29
+ * projection. Events are acknowledged only after every projected event has
30
+ * reached the outbox.
31
+ */
32
+ declare function createTaskCommunicationReconciler<Stores extends TaskCommunicationStores>(projection: TaskCommunicationProjection<Stores>): TaskCommunicationReconciler<Stores>;
33
+ //#endregion
34
+ export { TaskCommunicationProjection, TaskCommunicationReconciler, TaskCommunicationResult, TaskCommunicationStores, TaskLifecycleProjectionInput, createTaskCommunicationReconciler };
35
+ //# sourceMappingURL=task-communication.d.mts.map
@@ -0,0 +1,47 @@
1
+ //#region src/task-communication.ts
2
+ /**
3
+ * Build the generic durable receipt reconciler around an application's event
4
+ * projection. Events are acknowledged only after every projected event has
5
+ * reached the outbox.
6
+ */
7
+ function createTaskCommunicationReconciler(projection) {
8
+ return async function reconcileTaskCommunications(stores, snapshot) {
9
+ const tasks = snapshot ?? await stores.tasks.list();
10
+ let enqueued = 0;
11
+ for (const task of tasks) {
12
+ const presentsQuestion = task.question !== void 0;
13
+ if (presentsQuestion && task.state === "needs_human" && task.needsHumanNotifiedAt !== void 0) await stores.tasks.recordNeedsHumanDelivery(task.id, { attempt: task.attempt });
14
+ if (presentsQuestion && task.state === "needs_human" && task.needsHumanNotifiedAt === void 0 && !task.pendingCommunicationReceiptIds?.length) for (const event of await projection.question(task)) {
15
+ await stores.outbox.enqueue(event);
16
+ enqueued += 1;
17
+ }
18
+ for (const receiptId of task.pendingCommunicationReceiptIds ?? []) {
19
+ const receipt = await stores.receipts.get(receiptId);
20
+ if (receipt === null || receipt.taskId !== task.id) throw new Error(`Task ${task.id} references missing lifecycle receipt ${receiptId}.`);
21
+ if (receipt.state === "needs_human" && presentsQuestion) {
22
+ if (task.state === "needs_human" && task.attempt === receipt.attempt) for (const event of await projection.question(task)) {
23
+ await stores.outbox.enqueue(event);
24
+ enqueued += 1;
25
+ }
26
+ await stores.tasks.acknowledgeCommunication(task.id, receiptId);
27
+ continue;
28
+ }
29
+ for (const event of await projection.lifecycle({
30
+ stores,
31
+ tasks,
32
+ task,
33
+ receipt
34
+ })) {
35
+ await stores.outbox.enqueue(event);
36
+ enqueued += 1;
37
+ }
38
+ await stores.tasks.acknowledgeCommunication(task.id, receiptId);
39
+ }
40
+ }
41
+ return { enqueued };
42
+ };
43
+ }
44
+ //#endregion
45
+ export { createTaskCommunicationReconciler };
46
+
47
+ //# sourceMappingURL=task-communication.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-communication.mjs","names":[],"sources":["../src/task-communication.ts"],"sourcesContent":["import type { CommunicationEvent } from \"./schema/communication\";\nimport type { MaybePromise } from \"./schema/common\";\nimport type { Receipt } from \"./schema/receipt\";\nimport type { Task } from \"./schema/task\";\nimport type { FactoryStores } from \"./store/engine\";\n\n/** Outbox, receipt, and Task capabilities required by communication reconciliation. */\nexport type TaskCommunicationStores = Pick<FactoryStores, \"outbox\" | \"receipts\" | \"tasks\">;\n\n/** Number of connector-neutral events newly enqueued during reconciliation. */\nexport interface TaskCommunicationResult {\n enqueued: number;\n}\n\n/** Repairs pending Task communication projections against the durable outbox. */\nexport type TaskCommunicationReconciler<\n Stores extends TaskCommunicationStores = TaskCommunicationStores,\n> = (stores: Stores, snapshot?: readonly Task[]) => Promise<TaskCommunicationResult>;\n\n/** Durable Task and receipt context supplied to a lifecycle event projection. */\nexport interface TaskLifecycleProjectionInput<\n Stores extends TaskCommunicationStores = TaskCommunicationStores,\n> {\n stores: Stores;\n tasks: readonly Task[];\n task: Task;\n receipt: Receipt;\n}\n\n/** Application policy for projecting durable task state into connector-neutral events. */\nexport interface TaskCommunicationProjection<\n Stores extends TaskCommunicationStores = TaskCommunicationStores,\n> {\n question(task: Task): MaybePromise<readonly CommunicationEvent[]>;\n lifecycle(\n input: TaskLifecycleProjectionInput<Stores>,\n ): MaybePromise<readonly CommunicationEvent[]>;\n}\n\n/**\n * Build the generic durable receipt reconciler around an application's event\n * projection. Events are acknowledged only after every projected event has\n * reached the outbox.\n */\nexport function createTaskCommunicationReconciler<Stores extends TaskCommunicationStores>(\n projection: TaskCommunicationProjection<Stores>,\n): TaskCommunicationReconciler<Stores> {\n return async function reconcileTaskCommunications(\n stores: Stores,\n snapshot?: readonly Task[],\n ): Promise<TaskCommunicationResult> {\n const tasks = snapshot ?? (await stores.tasks.list());\n let enqueued = 0;\n for (const task of tasks) {\n const presentsQuestion = task.question !== undefined;\n // A connector may confirm before the parent starts waiting, or before\n // its delivery stamp is persisted.\n if (\n presentsQuestion &&\n task.state === \"needs_human\" &&\n task.needsHumanNotifiedAt !== undefined\n ) {\n await stores.tasks.recordNeedsHumanDelivery(task.id, { attempt: task.attempt });\n }\n if (\n presentsQuestion &&\n task.state === \"needs_human\" &&\n task.needsHumanNotifiedAt === undefined &&\n !task.pendingCommunicationReceiptIds?.length\n ) {\n for (const event of await projection.question(task)) {\n await stores.outbox.enqueue(event);\n enqueued += 1;\n }\n }\n for (const receiptId of task.pendingCommunicationReceiptIds ?? []) {\n const receipt = await stores.receipts.get(receiptId);\n if (receipt === null || receipt.taskId !== task.id) {\n throw new Error(`Task ${task.id} references missing lifecycle receipt ${receiptId}.`);\n }\n if (receipt.state === \"needs_human\" && presentsQuestion) {\n if (task.state === \"needs_human\" && task.attempt === receipt.attempt) {\n for (const event of await projection.question(task)) {\n await stores.outbox.enqueue(event);\n enqueued += 1;\n }\n }\n await stores.tasks.acknowledgeCommunication(task.id, receiptId);\n continue;\n }\n for (const event of await projection.lifecycle({ stores, tasks, task, receipt })) {\n await stores.outbox.enqueue(event);\n enqueued += 1;\n }\n await stores.tasks.acknowledgeCommunication(task.id, receiptId);\n }\n }\n return { enqueued };\n };\n}\n"],"mappings":";;;;;;AA4CA,SAAgB,kCACd,YACqC;CACrC,OAAO,eAAe,4BACpB,QACA,UACkC;EAClC,MAAM,QAAQ,YAAa,MAAM,OAAO,MAAM,KAAK;EACnD,IAAI,WAAW;EACf,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,mBAAmB,KAAK,aAAa,KAAA;GAG3C,IACE,oBACA,KAAK,UAAU,iBACf,KAAK,yBAAyB,KAAA,GAE9B,MAAM,OAAO,MAAM,yBAAyB,KAAK,IAAI,EAAE,SAAS,KAAK,QAAQ,CAAC;GAEhF,IACE,oBACA,KAAK,UAAU,iBACf,KAAK,yBAAyB,KAAA,KAC9B,CAAC,KAAK,gCAAgC,QAEtC,KAAK,MAAM,SAAS,MAAM,WAAW,SAAS,IAAI,GAAG;IACnD,MAAM,OAAO,OAAO,QAAQ,KAAK;IACjC,YAAY;GACd;GAEF,KAAK,MAAM,aAAa,KAAK,kCAAkC,CAAC,GAAG;IACjE,MAAM,UAAU,MAAM,OAAO,SAAS,IAAI,SAAS;IACnD,IAAI,YAAY,QAAQ,QAAQ,WAAW,KAAK,IAC9C,MAAM,IAAI,MAAM,QAAQ,KAAK,GAAG,wCAAwC,UAAU,EAAE;IAEtF,IAAI,QAAQ,UAAU,iBAAiB,kBAAkB;KACvD,IAAI,KAAK,UAAU,iBAAiB,KAAK,YAAY,QAAQ,SAC3D,KAAK,MAAM,SAAS,MAAM,WAAW,SAAS,IAAI,GAAG;MACnD,MAAM,OAAO,OAAO,QAAQ,KAAK;MACjC,YAAY;KACd;KAEF,MAAM,OAAO,MAAM,yBAAyB,KAAK,IAAI,SAAS;KAC9D;IACF;IACA,KAAK,MAAM,SAAS,MAAM,WAAW,UAAU;KAAE;KAAQ;KAAO;KAAM;IAAQ,CAAC,GAAG;KAChF,MAAM,OAAO,OAAO,QAAQ,KAAK;KACjC,YAAY;IACd;IACA,MAAM,OAAO,MAAM,yBAAyB,KAAK,IAAI,SAAS;GAChE;EACF;EACA,OAAO,EAAE,SAAS;CACpB;AACF"}