@vercel/factory 0.0.14 → 0.0.16

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 (510) hide show
  1. package/CHANGELOG.md +356 -0
  2. package/README.md +96 -2
  3. package/dist/agent-routes.d.mts +113 -0
  4. package/dist/agent-routes.mjs +91 -0
  5. package/dist/agent-routes.mjs.map +1 -0
  6. package/dist/api-contracts.d.mts +1768 -0
  7. package/dist/api-contracts.mjs +119 -0
  8. package/dist/api-contracts.mjs.map +1 -0
  9. package/dist/api-images.d.mts +30 -0
  10. package/dist/api-images.mjs +28 -0
  11. package/dist/api-images.mjs.map +1 -0
  12. package/dist/api-task-graph.mjs +57 -0
  13. package/dist/api-task-graph.mjs.map +1 -0
  14. package/dist/api.d.mts +111 -216
  15. package/dist/api.mjs +1063 -99
  16. package/dist/api.mjs.map +1 -1
  17. package/dist/approval-access.d.mts +39 -0
  18. package/dist/approval-access.mjs +62 -0
  19. package/dist/approval-access.mjs.map +1 -0
  20. package/dist/approval-contracts.d.mts +698 -0
  21. package/dist/approval-contracts.mjs +27 -0
  22. package/dist/approval-contracts.mjs.map +1 -0
  23. package/dist/approval.d.mts +49 -0
  24. package/dist/approval.mjs +39 -0
  25. package/dist/approval.mjs.map +1 -0
  26. package/dist/blob/artifacts.d.mts +37 -0
  27. package/dist/blob/artifacts.mjs +45 -0
  28. package/dist/blob/artifacts.mjs.map +1 -0
  29. package/dist/blob/index.d.mts +84 -12
  30. package/dist/blob/index.mjs +179 -45
  31. package/dist/blob/index.mjs.map +1 -1
  32. package/dist/budget.d.mts +115 -0
  33. package/dist/budget.mjs +147 -0
  34. package/dist/budget.mjs.map +1 -0
  35. package/dist/budgets.d.mts +4 -0
  36. package/dist/budgets.mjs +4 -0
  37. package/dist/build-factory.d.mts +7 -4
  38. package/dist/build-factory.mjs +2 -1
  39. package/dist/build-factory.mjs.map +1 -1
  40. package/dist/change-verification/brief.d.mts +9 -0
  41. package/dist/change-verification/brief.mjs +13 -0
  42. package/dist/change-verification/brief.mjs.map +1 -0
  43. package/dist/change-verification/dispatch.d.mts +37 -0
  44. package/dist/change-verification/dispatch.mjs +83 -0
  45. package/dist/change-verification/dispatch.mjs.map +1 -0
  46. package/dist/change-verification/eve-tool.d.mts +61 -0
  47. package/dist/change-verification/eve-tool.mjs +89 -0
  48. package/dist/change-verification/eve-tool.mjs.map +1 -0
  49. package/dist/change-verification/result.mjs +130 -0
  50. package/dist/change-verification/result.mjs.map +1 -0
  51. package/dist/changes/eve-record-change.d.mts +56 -0
  52. package/dist/changes/eve-record-change.mjs +131 -0
  53. package/dist/changes/eve-record-change.mjs.map +1 -0
  54. package/dist/changes/presentation.d.mts +14 -0
  55. package/dist/changes.d.mts +24 -0
  56. package/dist/changes.mjs +29 -0
  57. package/dist/changes.mjs.map +1 -0
  58. package/dist/client-events.d.mts +25 -0
  59. package/dist/client-events.mjs +45 -0
  60. package/dist/client-events.mjs.map +1 -0
  61. package/dist/client-stream.d.mts +28 -0
  62. package/dist/client-stream.mjs +210 -0
  63. package/dist/client-stream.mjs.map +1 -0
  64. package/dist/client-transcript.d.mts +41 -0
  65. package/dist/client-transcript.mjs +233 -0
  66. package/dist/client-transcript.mjs.map +1 -0
  67. package/dist/client.d.mts +343 -0
  68. package/dist/client.mjs +366 -0
  69. package/dist/client.mjs.map +1 -0
  70. package/dist/code-review/contracts.d.mts +27 -0
  71. package/dist/code-review/eve-post-review.d.mts +70 -0
  72. package/dist/code-review/eve-post-review.mjs +195 -0
  73. package/dist/code-review/eve-post-review.mjs.map +1 -0
  74. package/dist/code-review/eve-review-comments.d.mts +75 -0
  75. package/dist/code-review/eve-review-comments.mjs +193 -0
  76. package/dist/code-review/eve-review-comments.mjs.map +1 -0
  77. package/dist/code-review/github-contracts.d.mts +10 -0
  78. package/dist/code-review/github-reporter.d.mts +46 -0
  79. package/dist/code-review/github-reporter.mjs +262 -0
  80. package/dist/code-review/github-reporter.mjs.map +1 -0
  81. package/dist/code-review/preparation.d.mts +34 -0
  82. package/dist/code-review/preparation.mjs +23 -0
  83. package/dist/code-review/preparation.mjs.map +1 -0
  84. package/dist/code-review/stall.d.mts +17 -0
  85. package/dist/code-review/stall.mjs +30 -0
  86. package/dist/code-review/stall.mjs.map +1 -0
  87. package/dist/code-review.d.mts +7 -0
  88. package/dist/code-review.mjs +5 -0
  89. package/dist/communication.d.mts +9 -0
  90. package/dist/communication.mjs +9 -0
  91. package/dist/connectors/github.d.mts +26 -0
  92. package/dist/connectors/github.mjs +55 -0
  93. package/dist/connectors/github.mjs.map +1 -0
  94. package/dist/connectors/index.d.mts +35 -3
  95. package/dist/connectors/index.mjs +3 -52
  96. package/dist/connectors/index.mjs.map +1 -1
  97. package/dist/connectors/outbox.d.mts +34 -0
  98. package/dist/connectors/outbox.mjs +50 -0
  99. package/dist/connectors/outbox.mjs.map +1 -0
  100. package/dist/connectors/slack-approval-blocks.mjs +136 -0
  101. package/dist/connectors/slack-approval-blocks.mjs.map +1 -0
  102. package/dist/connectors/slack-approvals.d.mts +29 -0
  103. package/dist/connectors/slack-approvals.mjs +346 -0
  104. package/dist/connectors/slack-approvals.mjs.map +1 -0
  105. package/dist/connectors/slack.d.mts +35 -52
  106. package/dist/connectors/slack.mjs +13 -85
  107. package/dist/connectors/slack.mjs.map +1 -1
  108. package/dist/deepsec/eve-tool.d.mts +110 -0
  109. package/dist/deepsec/eve-tool.mjs +166 -0
  110. package/dist/deepsec/eve-tool.mjs.map +1 -0
  111. package/dist/deepsec/finding.d.mts +84 -0
  112. package/dist/deepsec/finding.mjs +56 -0
  113. package/dist/deepsec/finding.mjs.map +1 -0
  114. package/dist/deepsec.d.mts +3 -0
  115. package/dist/delivery-metrics/metrics.d.mts +93 -0
  116. package/dist/delivery-metrics/metrics.mjs +200 -0
  117. package/dist/delivery-metrics/metrics.mjs.map +1 -0
  118. package/dist/delivery-metrics.d.mts +2 -0
  119. package/dist/delivery-metrics.mjs +2 -0
  120. package/dist/dispatch.d.mts +152 -0
  121. package/dist/dispatch.mjs +199 -0
  122. package/dist/dispatch.mjs.map +1 -0
  123. package/dist/errors.d.mts +15 -0
  124. package/dist/errors.mjs +38 -0
  125. package/dist/errors.mjs.map +1 -0
  126. package/dist/eve/index.d.mts +209 -1277
  127. package/dist/eve/index.mjs +312 -1073
  128. package/dist/eve/index.mjs.map +1 -1
  129. package/dist/eve/invoke.d.mts +144 -0
  130. package/dist/eve/invoke.mjs +254 -0
  131. package/dist/eve/invoke.mjs.map +1 -0
  132. package/dist/eve/session-client.d.mts +186 -0
  133. package/dist/eve/session-client.mjs +245 -0
  134. package/dist/eve/session-client.mjs.map +1 -0
  135. package/dist/eve/task-execution.d.mts +380 -0
  136. package/dist/eve/task-execution.mjs +73 -0
  137. package/dist/eve/task-execution.mjs.map +1 -0
  138. package/dist/eve/task-session.d.mts +129 -0
  139. package/dist/eve/task-session.mjs +245 -0
  140. package/dist/eve/task-session.mjs.map +1 -0
  141. package/dist/eve/transcript.d.mts +37 -0
  142. package/dist/eve/transcript.mjs +69 -0
  143. package/dist/eve/transcript.mjs.map +1 -0
  144. package/dist/execution-public.d.mts +8 -0
  145. package/dist/execution-public.mjs +7 -0
  146. package/dist/execution.d.mts +183 -0
  147. package/dist/execution.mjs +223 -0
  148. package/dist/execution.mjs.map +1 -0
  149. package/dist/finding-remediation/admission.d.mts +53 -0
  150. package/dist/finding-remediation/admission.mjs +90 -0
  151. package/dist/finding-remediation/admission.mjs.map +1 -0
  152. package/dist/finding-remediation/brief.d.mts +14 -0
  153. package/dist/finding-remediation/brief.mjs +25 -0
  154. package/dist/finding-remediation/brief.mjs.map +1 -0
  155. package/dist/finding-remediation/eve-tool.d.mts +29 -0
  156. package/dist/finding-remediation/eve-tool.mjs +34 -0
  157. package/dist/finding-remediation/eve-tool.mjs.map +1 -0
  158. package/dist/findings/fingerprint.d.mts +14 -0
  159. package/dist/findings/fingerprint.mjs +28 -0
  160. package/dist/findings/fingerprint.mjs.map +1 -0
  161. package/dist/findings.d.mts +7 -0
  162. package/dist/findings.mjs +6 -0
  163. package/dist/github-app.d.mts +54 -0
  164. package/dist/github-app.mjs +121 -0
  165. package/dist/github-app.mjs.map +1 -0
  166. package/dist/github-publication.d.mts +199 -0
  167. package/dist/github-publication.mjs +442 -0
  168. package/dist/github-publication.mjs.map +1 -0
  169. package/dist/github-transfer.d.mts +81 -0
  170. package/dist/github-transfer.mjs +273 -0
  171. package/dist/github-transfer.mjs.map +1 -0
  172. package/dist/github.d.mts +446 -2
  173. package/dist/github.mjs +357 -56
  174. package/dist/github.mjs.map +1 -1
  175. package/dist/image-input.d.mts +51 -0
  176. package/dist/image-input.mjs +63 -0
  177. package/dist/image-input.mjs.map +1 -0
  178. package/dist/inbox-activity.d.mts +53 -0
  179. package/dist/inbox-activity.mjs +41 -0
  180. package/dist/inbox-activity.mjs.map +1 -0
  181. package/dist/index.d.mts +16 -484
  182. package/dist/index.mjs +15 -522
  183. package/dist/intake-contracts.d.mts +55 -0
  184. package/dist/intake-contracts.mjs +33 -0
  185. package/dist/intake-contracts.mjs.map +1 -0
  186. package/dist/integrations/deepsec.d.mts +5 -0
  187. package/dist/integrations/deepsec.mjs +3 -0
  188. package/dist/integrations/github.d.mts +11 -0
  189. package/dist/integrations/github.mjs +9 -0
  190. package/dist/integrations/slack.d.mts +5 -0
  191. package/dist/integrations/slack.mjs +5 -0
  192. package/dist/integrations/vercel.d.mts +5 -0
  193. package/dist/integrations/vercel.mjs +4 -0
  194. package/dist/merge-resolution/contracts.d.mts +17 -0
  195. package/dist/merge-resolution/contracts.mjs +19 -0
  196. package/dist/merge-resolution/contracts.mjs.map +1 -0
  197. package/dist/merge-resolution/eve-tools.d.mts +47 -0
  198. package/dist/merge-resolution/eve-tools.mjs +122 -0
  199. package/dist/merge-resolution/eve-tools.mjs.map +1 -0
  200. package/dist/model-settings.d.mts +41 -0
  201. package/dist/model-settings.mjs +35 -0
  202. package/dist/model-settings.mjs.map +1 -0
  203. package/dist/multi-repository-changes/coordination.d.mts +49 -0
  204. package/dist/multi-repository-changes/coordination.mjs +115 -0
  205. package/dist/multi-repository-changes/coordination.mjs.map +1 -0
  206. package/dist/planning/cancellation.mjs +82 -0
  207. package/dist/planning/cancellation.mjs.map +1 -0
  208. package/dist/planning/configuration.d.mts +23 -0
  209. package/dist/planning/configuration.mjs +56 -0
  210. package/dist/planning/configuration.mjs.map +1 -0
  211. package/dist/planning/contracts.d.mts +136 -0
  212. package/dist/planning/contracts.mjs +42 -0
  213. package/dist/planning/contracts.mjs.map +1 -0
  214. package/dist/planning/dependencies.mjs +44 -0
  215. package/dist/planning/dependencies.mjs.map +1 -0
  216. package/dist/planning/effects.mjs +122 -0
  217. package/dist/planning/effects.mjs.map +1 -0
  218. package/dist/planning/reconcile.mjs +279 -0
  219. package/dist/planning/reconcile.mjs.map +1 -0
  220. package/dist/planning/runtime.d.mts +27 -0
  221. package/dist/planning/runtime.mjs +25 -0
  222. package/dist/planning/runtime.mjs.map +1 -0
  223. package/dist/planning/state.mjs +92 -0
  224. package/dist/planning/state.mjs.map +1 -0
  225. package/dist/planning/turns.mjs +262 -0
  226. package/dist/planning/turns.mjs.map +1 -0
  227. package/dist/planning/validation.mjs +106 -0
  228. package/dist/planning/validation.mjs.map +1 -0
  229. package/dist/postgres/index.d.mts +48 -1
  230. package/dist/postgres/index.mjs +45 -3
  231. package/dist/postgres/index.mjs.map +1 -1
  232. package/dist/presets/software-development/approval.d.mts +14 -0
  233. package/dist/presets/software-development/approval.mjs +21 -0
  234. package/dist/presets/software-development/approval.mjs.map +1 -0
  235. package/dist/presets/software-development/deepsec-brief.d.mts +8 -0
  236. package/dist/presets/software-development/deepsec-brief.mjs +14 -0
  237. package/dist/presets/software-development/deepsec-brief.mjs.map +1 -0
  238. package/dist/presets/software-development/dispatch.d.mts +56 -0
  239. package/dist/presets/software-development/dispatch.mjs +67 -0
  240. package/dist/presets/software-development/dispatch.mjs.map +1 -0
  241. package/dist/presets/software-development/eve-delegation-policy.d.mts +7 -0
  242. package/dist/presets/software-development/eve-delegation-policy.mjs +34 -0
  243. package/dist/presets/software-development/eve-delegation-policy.mjs.map +1 -0
  244. package/dist/presets/software-development/eve.d.mts +18 -0
  245. package/dist/presets/software-development/eve.mjs +19 -0
  246. package/dist/presets/software-development/eve.mjs.map +1 -0
  247. package/dist/presets/software-development/finish-task-policy.d.mts +7 -0
  248. package/dist/presets/software-development/finish-task-policy.mjs +9 -0
  249. package/dist/presets/software-development/finish-task-policy.mjs.map +1 -0
  250. package/dist/presets/software-development/recovery.d.mts +32 -0
  251. package/dist/presets/software-development/recovery.mjs +120 -0
  252. package/dist/presets/software-development/recovery.mjs.map +1 -0
  253. package/dist/presets/software-development/task-communication.d.mts +24 -0
  254. package/dist/presets/software-development/task-communication.mjs +157 -0
  255. package/dist/presets/software-development/task-communication.mjs.map +1 -0
  256. package/dist/presets/software-development.d.mts +10 -0
  257. package/dist/presets/software-development.mjs +9 -0
  258. package/dist/pull-requests/contracts.d.mts +72 -0
  259. package/dist/pull-requests/eve-fetch.d.mts +57 -0
  260. package/dist/pull-requests/eve-fetch.mjs +151 -0
  261. package/dist/pull-requests/eve-fetch.mjs.map +1 -0
  262. package/dist/pull-requests/github-label-manager.d.mts +27 -0
  263. package/dist/pull-requests/github-label-manager.mjs +40 -0
  264. package/dist/pull-requests/github-label-manager.mjs.map +1 -0
  265. package/dist/pull-requests/github-publisher.d.mts +67 -0
  266. package/dist/pull-requests/github-publisher.mjs +405 -0
  267. package/dist/pull-requests/github-publisher.mjs.map +1 -0
  268. package/dist/pull-requests.d.mts +6 -0
  269. package/dist/pull-requests.mjs +4 -0
  270. package/dist/receipts.d.mts +4 -0
  271. package/dist/receipts.mjs +3 -0
  272. package/dist/repositories.d.mts +18 -0
  273. package/dist/repositories.mjs +33 -0
  274. package/dist/repositories.mjs.map +1 -0
  275. package/dist/sandbox/command.d.mts +18 -0
  276. package/dist/sandbox/execution-abort.d.mts +16 -0
  277. package/dist/sandbox/execution-abort.mjs +49 -0
  278. package/dist/sandbox/execution-abort.mjs.map +1 -0
  279. package/dist/sandbox/execution-environment.d.mts +25 -0
  280. package/dist/sandbox/execution-run-ledger.d.mts +115 -0
  281. package/dist/sandbox/execution-run-ledger.mjs +209 -0
  282. package/dist/sandbox/execution-run-ledger.mjs.map +1 -0
  283. package/dist/sandbox/execution.d.mts +54 -0
  284. package/dist/sandbox/execution.mjs +228 -0
  285. package/dist/sandbox/execution.mjs.map +1 -0
  286. package/dist/sandbox/harness-runner.d.mts +79 -0
  287. package/dist/sandbox/harness-runner.mjs +162 -0
  288. package/dist/sandbox/harness-runner.mjs.map +1 -0
  289. package/dist/sandbox/index.d.mts +10 -0
  290. package/dist/sandbox/index.mjs +7 -0
  291. package/dist/sandbox/task-environment.d.mts +50 -0
  292. package/dist/sandbox/task-environment.mjs +140 -0
  293. package/dist/sandbox/task-environment.mjs.map +1 -0
  294. package/dist/sandbox/workspace.d.mts +29 -0
  295. package/dist/sandbox/workspace.mjs +28 -0
  296. package/dist/sandbox/workspace.mjs.map +1 -0
  297. package/dist/schema/agent-route.d.mts +40 -0
  298. package/dist/schema/agent-route.mjs +33 -0
  299. package/dist/schema/agent-route.mjs.map +1 -0
  300. package/dist/schema/answer.d.mts +23 -0
  301. package/dist/schema/answer.mjs +21 -0
  302. package/dist/schema/answer.mjs.map +1 -0
  303. package/dist/schema/budget.d.mts +38 -0
  304. package/dist/schema/budget.mjs +30 -0
  305. package/dist/schema/budget.mjs.map +1 -0
  306. package/dist/schema/catalog.mjs +72 -0
  307. package/dist/schema/catalog.mjs.map +1 -0
  308. package/dist/schema/change.d.mts +117 -0
  309. package/dist/schema/change.mjs +68 -0
  310. package/dist/schema/change.mjs.map +1 -0
  311. package/dist/schema/common.d.mts +33 -0
  312. package/dist/{id-BLIkCVue.mjs → schema/common.mjs} +7 -16
  313. package/dist/schema/common.mjs.map +1 -0
  314. package/dist/schema/communication.d.mts +52 -0
  315. package/dist/{communication-Kd9nU5RP.mjs → schema/communication.mjs} +8 -3
  316. package/dist/schema/communication.mjs.map +1 -0
  317. package/dist/schema/execution.d.mts +101 -0
  318. package/dist/schema/execution.mjs +86 -0
  319. package/dist/schema/execution.mjs.map +1 -0
  320. package/dist/schema/factory-config.d.mts +122 -0
  321. package/dist/schema/factory-config.mjs +90 -0
  322. package/dist/schema/factory-config.mjs.map +1 -0
  323. package/dist/schema/finding.d.mts +125 -0
  324. package/dist/schema/finding.mjs +67 -0
  325. package/dist/schema/finding.mjs.map +1 -0
  326. package/dist/schema/id.d.mts +43 -0
  327. package/dist/schema/id.mjs +32 -0
  328. package/dist/schema/id.mjs.map +1 -0
  329. package/dist/schema/outbox.d.mts +240 -0
  330. package/dist/schema/outbox.mjs +53 -0
  331. package/dist/schema/outbox.mjs.map +1 -0
  332. package/dist/schema/question-route.mjs +16 -0
  333. package/dist/schema/question-route.mjs.map +1 -0
  334. package/dist/schema/receipt.d.mts +81 -0
  335. package/dist/schema/receipt.mjs +94 -0
  336. package/dist/schema/receipt.mjs.map +1 -0
  337. package/dist/schema/repository.d.mts +30 -0
  338. package/dist/schema/repository.mjs +29 -0
  339. package/dist/schema/repository.mjs.map +1 -0
  340. package/dist/schema/session.d.mts +136 -0
  341. package/dist/schema/session.mjs +54 -0
  342. package/dist/schema/session.mjs.map +1 -0
  343. package/dist/schema/signal.d.mts +105 -0
  344. package/dist/schema/signal.mjs +81 -0
  345. package/dist/schema/signal.mjs.map +1 -0
  346. package/dist/schema/slack-pr-notifications.d.mts +12 -0
  347. package/dist/schema/slack-pr-notifications.mjs +11 -0
  348. package/dist/schema/slack-pr-notifications.mjs.map +1 -0
  349. package/dist/schema/stored-session.mjs +10 -0
  350. package/dist/schema/stored-session.mjs.map +1 -0
  351. package/dist/schema/stored-task.mjs +20 -0
  352. package/dist/schema/stored-task.mjs.map +1 -0
  353. package/dist/schema/task-effect.d.mts +39 -0
  354. package/dist/schema/task-effect.mjs +29 -0
  355. package/dist/schema/task-effect.mjs.map +1 -0
  356. package/dist/schema/task-graph.d.mts +3173 -0
  357. package/dist/schema/task-graph.mjs +97 -0
  358. package/dist/schema/task-graph.mjs.map +1 -0
  359. package/dist/schema/task-message.d.mts +254 -0
  360. package/dist/schema/task-message.mjs +189 -0
  361. package/dist/schema/task-message.mjs.map +1 -0
  362. package/dist/schema/task.d.mts +273 -0
  363. package/dist/schema/task.mjs +200 -0
  364. package/dist/schema/task.mjs.map +1 -0
  365. package/dist/schema/transcript.d.mts +176 -0
  366. package/dist/schema/transcript.mjs +87 -0
  367. package/dist/schema/transcript.mjs.map +1 -0
  368. package/dist/schema/transitions.d.mts +50 -0
  369. package/dist/schema/transitions.mjs +303 -0
  370. package/dist/schema/transitions.mjs.map +1 -0
  371. package/dist/schema/work.d.mts +150 -0
  372. package/dist/schema/work.mjs +102 -0
  373. package/dist/schema/work.mjs.map +1 -0
  374. package/dist/session-previews.d.mts +76 -0
  375. package/dist/session-previews.mjs +55 -0
  376. package/dist/session-previews.mjs.map +1 -0
  377. package/dist/session-review.d.mts +120 -0
  378. package/dist/session-review.mjs +79 -0
  379. package/dist/session-review.mjs.map +1 -0
  380. package/dist/signal-triage.d.mts +20 -0
  381. package/dist/signal-triage.mjs +85 -0
  382. package/dist/signal-triage.mjs.map +1 -0
  383. package/dist/signals.d.mts +20 -0
  384. package/dist/signals.mjs +19 -0
  385. package/dist/signals.mjs.map +1 -0
  386. package/dist/stall.d.mts +41 -0
  387. package/dist/stall.mjs +83 -0
  388. package/dist/stall.mjs.map +1 -0
  389. package/dist/storage.d.mts +4 -0
  390. package/dist/storage.mjs +4 -0
  391. package/dist/store/driver.d.mts +65 -0
  392. package/dist/store/driver.mjs +42 -0
  393. package/dist/store/driver.mjs.map +1 -0
  394. package/dist/store/engine.d.mts +683 -0
  395. package/dist/store/engine.mjs +2309 -0
  396. package/dist/store/engine.mjs.map +1 -0
  397. package/dist/store/memory.d.mts +24 -0
  398. package/dist/store/memory.mjs +69 -0
  399. package/dist/store/memory.mjs.map +1 -0
  400. package/dist/store/slack-pr-notifications.d.mts +44 -0
  401. package/dist/store/slack-pr-notifications.mjs +121 -0
  402. package/dist/store/slack-pr-notifications.mjs.map +1 -0
  403. package/dist/store/task-effects.d.mts +38 -0
  404. package/dist/store/task-effects.mjs +118 -0
  405. package/dist/store/task-effects.mjs.map +1 -0
  406. package/dist/store/task-graphs.d.mts +60 -0
  407. package/dist/store/task-graphs.mjs +212 -0
  408. package/dist/store/task-graphs.mjs.map +1 -0
  409. package/dist/store/task-messages.d.mts +136 -0
  410. package/dist/store/task-messages.mjs +475 -0
  411. package/dist/store/task-messages.mjs.map +1 -0
  412. package/dist/store/task-work.d.mts +180 -0
  413. package/dist/store/task-work.mjs +137 -0
  414. package/dist/store/task-work.mjs.map +1 -0
  415. package/dist/store/work-notifications.d.mts +19 -0
  416. package/dist/store/work-notifications.mjs +48 -0
  417. package/dist/store/work-notifications.mjs.map +1 -0
  418. package/dist/sweep.d.mts +79 -0
  419. package/dist/sweep.mjs +171 -0
  420. package/dist/sweep.mjs.map +1 -0
  421. package/dist/task-communication.d.mts +35 -0
  422. package/dist/task-communication.mjs +47 -0
  423. package/dist/task-communication.mjs.map +1 -0
  424. package/dist/task-graph-view.d.mts +267 -0
  425. package/dist/task-graph-view.mjs +17 -0
  426. package/dist/task-graph-view.mjs.map +1 -0
  427. package/dist/task-message-processing.d.mts +60 -0
  428. package/dist/task-message-processing.mjs +200 -0
  429. package/dist/task-message-processing.mjs.map +1 -0
  430. package/dist/task-protocols.d.mts +80 -0
  431. package/dist/task-protocols.mjs +47 -0
  432. package/dist/task-protocols.mjs.map +1 -0
  433. package/dist/tasks.d.mts +17 -0
  434. package/dist/tasks.mjs +17 -0
  435. package/dist/vercel-git.d.mts +53 -0
  436. package/dist/vercel-git.mjs +344 -0
  437. package/dist/vercel-git.mjs.map +1 -0
  438. package/dist/vercel-github-api.d.mts +103 -0
  439. package/dist/vercel-github-api.mjs +363 -0
  440. package/dist/vercel-github-api.mjs.map +1 -0
  441. package/dist/vercel.d.mts +34 -2
  442. package/dist/vercel.mjs +49 -3
  443. package/dist/vercel.mjs.map +1 -1
  444. package/dist/work-triage/eve-tool.d.mts +29 -0
  445. package/dist/work-triage/eve-tool.mjs +32 -0
  446. package/dist/work-triage/eve-tool.mjs.map +1 -0
  447. package/dist/work-triage/find-existing-work.d.mts +32 -0
  448. package/dist/work-triage/find-existing-work.mjs +31 -0
  449. package/dist/work-triage/find-existing-work.mjs.map +1 -0
  450. package/dist/work-triage/github.d.mts +15 -0
  451. package/dist/work-triage/github.mjs +14 -0
  452. package/dist/work-triage/github.mjs.map +1 -0
  453. package/dist/work-triage.d.mts +4 -0
  454. package/dist/work-triage.mjs +3 -0
  455. package/dist/workflows.d.mts +146 -0
  456. package/dist/workflows.mjs +139 -0
  457. package/dist/workflows.mjs.map +1 -0
  458. package/dist/workspace-diff-assembly.d.mts +33 -0
  459. package/dist/workspace-diff-assembly.mjs +95 -0
  460. package/dist/workspace-diff-assembly.mjs.map +1 -0
  461. package/dist/workspace-diff.d.mts +90 -0
  462. package/dist/workspace-diff.mjs +61 -0
  463. package/dist/workspace-diff.mjs.map +1 -0
  464. package/dist/workspace-files-git.d.mts +15 -0
  465. package/dist/workspace-files-git.mjs +61 -0
  466. package/dist/workspace-files-git.mjs.map +1 -0
  467. package/dist/workspace-files.d.mts +107 -0
  468. package/dist/workspace-files.mjs +74 -0
  469. package/dist/workspace-files.mjs.map +1 -0
  470. package/dist/workspace-snapshot.d.mts +26 -0
  471. package/dist/workspace-snapshot.mjs +80 -0
  472. package/dist/workspace-snapshot.mjs.map +1 -0
  473. package/docs/getting-started.md +104 -0
  474. package/docs/index.md +100 -0
  475. package/docs/recipes/cancellation.md +215 -0
  476. package/docs/recipes/custom-workflow.md +153 -0
  477. package/docs/recipes/dependent-tasks.md +207 -0
  478. package/docs/recipes/eve-agent.md +277 -0
  479. package/docs/recipes/human-input.md +204 -0
  480. package/docs/recipes/persistence-recovery.md +268 -0
  481. package/docs/recipes/retry-recovery.md +241 -0
  482. package/docs/recipes/task-messaging.md +215 -0
  483. package/docs/recipes/typed-eve-result.md +161 -0
  484. package/docs/runtime-integration.md +137 -0
  485. package/package.json +142 -46
  486. package/dist/approval-JX2Px9IC.mjs +0 -132
  487. package/dist/approval-JX2Px9IC.mjs.map +0 -1
  488. package/dist/budget-DzSiIA4t.mjs +0 -42
  489. package/dist/budget-DzSiIA4t.mjs.map +0 -1
  490. package/dist/change-D2U6v7Ek.mjs +0 -554
  491. package/dist/change-D2U6v7Ek.mjs.map +0 -1
  492. package/dist/communication-Kd9nU5RP.mjs.map +0 -1
  493. package/dist/coordination-Cq08hb1l.mjs +0 -76
  494. package/dist/coordination-Cq08hb1l.mjs.map +0 -1
  495. package/dist/dispatch-BaZS3PT8.d.mts +0 -76
  496. package/dist/driver-BC0Mt5KG.d.mts +0 -34
  497. package/dist/driver-Bbd25rNM.mjs +0 -23
  498. package/dist/driver-Bbd25rNM.mjs.map +0 -1
  499. package/dist/engine-DFHU2Pe-.d.mts +0 -781
  500. package/dist/engine-WaUM2cGA.mjs +0 -1068
  501. package/dist/engine-WaUM2cGA.mjs.map +0 -1
  502. package/dist/factory-config-BoRXOw43.mjs +0 -50
  503. package/dist/factory-config-BoRXOw43.mjs.map +0 -1
  504. package/dist/factory-config-D2yU3G0c.d.mts +0 -58
  505. package/dist/github-C5HNBN6p.d.mts +0 -279
  506. package/dist/id-BLIkCVue.mjs.map +0 -1
  507. package/dist/index-Bw6hggoH.d.mts +0 -40
  508. package/dist/index.mjs.map +0 -1
  509. package/dist/task-CcOyOJ3k.mjs +0 -154
  510. package/dist/task-CcOyOJ3k.mjs.map +0 -1
@@ -0,0 +1,73 @@
1
+ import { factoryTaskAttemptAttribute, factoryTaskAttribute, taskBindingForSession } from "./task-session.mjs";
2
+ //#region src/eve/task-execution.ts
3
+ /**
4
+ * Requires the authenticated session's current running Eve Task execution and attempt.
5
+ *
6
+ * @remarks
7
+ * `requestedTaskId` is a consistency check, not an authority source. This function reads the Task
8
+ * and attempt established by `withFactoryTask`, rejects conflicting current-auth attributes, and
9
+ * verifies that durable state still points to the same Eve session and attempt. Use it immediately
10
+ * before a mutating tool applies effects or completes workflow output. A cancellation, retry, or
11
+ * replacement session fences the stale caller out.
12
+ *
13
+ * The check does not complete the Task and does not make a following external side effect atomic
14
+ * with Factory state. Pass the returned attempt and execution as the completion fence when writing
15
+ * output.
16
+ *
17
+ * @param stores - Task store used to reread canonical execution state.
18
+ * @param ctx - Eve tool or hook context containing initiator and current authentication.
19
+ * @param requestedTaskId - Task ID from the tool input, required to match the authenticated binding.
20
+ * @returns The currently running Task bound to this exact Eve session and attempt.
21
+ * @throws When authentication is missing or malformed, the requested Task differs, or durable execution was replaced or stopped.
22
+ * @see The shipped `docs/recipes/typed-eve-result.md` recipe for a complete typed tool.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { requireTaskExecution } from "@vercel/factory";
27
+ * import type { FactoryStores } from "@vercel/factory/storage";
28
+ * import type { TaskId } from "@vercel/factory/tasks";
29
+ * import { defineWorkflow } from "@vercel/factory/workflows";
30
+ * import type { ToolContext } from "eve/tools";
31
+ * import { z } from "zod";
32
+ *
33
+ * declare const stores: FactoryStores;
34
+ * declare const ctx: ToolContext;
35
+ * declare const taskId: TaskId;
36
+ * const workflow = defineWorkflow({
37
+ * id: "greeting",
38
+ * version: 1,
39
+ * input: z.object({ name: z.string() }),
40
+ * output: z.object({ message: z.string() }),
41
+ * });
42
+ *
43
+ * const task = await requireTaskExecution(stores, ctx, taskId);
44
+ * if (task.execution?.provider !== "eve") throw new Error("Expected Eve execution");
45
+ * await stores.work.completeWorkflow({
46
+ * task: { taskId: task.id, attempt: task.attempt },
47
+ * workflow: workflow.binding,
48
+ * output: { message: "Hello" },
49
+ * fence: { from: "running", execution: task.execution },
50
+ * });
51
+ * ```
52
+ */
53
+ async function requireTaskExecution(stores, ctx, requestedTaskId) {
54
+ const task = await requireTaskExecutionIdentity(stores, ctx, requestedTaskId);
55
+ if (task.state !== "running") throw new Error("Task execution is missing, inactive, or replaced");
56
+ return task;
57
+ }
58
+ async function requireTaskExecutionIdentity(stores, ctx, requestedTaskId) {
59
+ const auth = ctx.session?.auth;
60
+ const binding = taskBindingForSession(auth?.initiator);
61
+ if (binding.taskId !== requestedTaskId) throw new Error("Task does not match the authenticated session");
62
+ for (const key of [factoryTaskAttribute, factoryTaskAttemptAttribute]) {
63
+ const current = auth?.current?.attributes[key];
64
+ if (current !== void 0 && current !== auth?.initiator?.attributes[key]) throw new Error("Task binding does not match the current authentication");
65
+ }
66
+ const task = await stores.tasks.get(binding.taskId);
67
+ if (task === null || task.attempt !== binding.attempt || task.execution?.provider !== "eve" || task.execution.sessionId !== ctx.session.id) throw new Error("Task execution is missing, inactive, or replaced");
68
+ return task;
69
+ }
70
+ //#endregion
71
+ export { requireTaskExecution, requireTaskExecutionIdentity };
72
+
73
+ //# sourceMappingURL=task-execution.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-execution.mjs","names":[],"sources":["../../src/eve/task-execution.ts"],"sourcesContent":["import type { SessionContext } from \"eve/context\";\nimport type { TaskId } from \"../schema/id\";\nimport type { FactoryStores } from \"../store/engine\";\nimport {\n factoryTaskAttribute,\n factoryTaskAttemptAttribute,\n taskBindingForSession,\n} from \"./task-session\";\n\n/**\n * Requires the authenticated session's current running Eve Task execution and attempt.\n *\n * @remarks\n * `requestedTaskId` is a consistency check, not an authority source. This function reads the Task\n * and attempt established by `withFactoryTask`, rejects conflicting current-auth attributes, and\n * verifies that durable state still points to the same Eve session and attempt. Use it immediately\n * before a mutating tool applies effects or completes workflow output. A cancellation, retry, or\n * replacement session fences the stale caller out.\n *\n * The check does not complete the Task and does not make a following external side effect atomic\n * with Factory state. Pass the returned attempt and execution as the completion fence when writing\n * output.\n *\n * @param stores - Task store used to reread canonical execution state.\n * @param ctx - Eve tool or hook context containing initiator and current authentication.\n * @param requestedTaskId - Task ID from the tool input, required to match the authenticated binding.\n * @returns The currently running Task bound to this exact Eve session and attempt.\n * @throws When authentication is missing or malformed, the requested Task differs, or durable execution was replaced or stopped.\n * @see The shipped `docs/recipes/typed-eve-result.md` recipe for a complete typed tool.\n *\n * @example\n * ```ts\n * import { requireTaskExecution } from \"@vercel/factory\";\n * import type { FactoryStores } from \"@vercel/factory/storage\";\n * import type { TaskId } from \"@vercel/factory/tasks\";\n * import { defineWorkflow } from \"@vercel/factory/workflows\";\n * import type { ToolContext } from \"eve/tools\";\n * import { z } from \"zod\";\n *\n * declare const stores: FactoryStores;\n * declare const ctx: ToolContext;\n * declare const taskId: TaskId;\n * const workflow = defineWorkflow({\n * id: \"greeting\",\n * version: 1,\n * input: z.object({ name: z.string() }),\n * output: z.object({ message: z.string() }),\n * });\n *\n * const task = await requireTaskExecution(stores, ctx, taskId);\n * if (task.execution?.provider !== \"eve\") throw new Error(\"Expected Eve execution\");\n * await stores.work.completeWorkflow({\n * task: { taskId: task.id, attempt: task.attempt },\n * workflow: workflow.binding,\n * output: { message: \"Hello\" },\n * fence: { from: \"running\", execution: task.execution },\n * });\n * ```\n */\nexport async function requireTaskExecution(\n stores: Pick<FactoryStores, \"tasks\">,\n ctx: { session: Pick<SessionContext[\"session\"], \"id\" | \"auth\"> },\n requestedTaskId: TaskId,\n) {\n const task = await requireTaskExecutionIdentity(stores, ctx, requestedTaskId);\n if (task.state !== \"running\") {\n throw new Error(\"Task execution is missing, inactive, or replaced\");\n }\n return task;\n}\n\n// Completion replay also checks identity; its caller must restrict lifecycle states and effects.\nexport async function requireTaskExecutionIdentity(\n stores: Pick<FactoryStores, \"tasks\">,\n ctx: { session: Pick<SessionContext[\"session\"], \"id\" | \"auth\"> },\n requestedTaskId: TaskId,\n) {\n const auth = ctx.session?.auth;\n const binding = taskBindingForSession(auth?.initiator);\n if (binding.taskId !== requestedTaskId) {\n throw new Error(\"Task does not match the authenticated session\");\n }\n for (const key of [factoryTaskAttribute, factoryTaskAttemptAttribute]) {\n const current = auth?.current?.attributes[key];\n if (current !== undefined && current !== auth?.initiator?.attributes[key]) {\n throw new Error(\"Task binding does not match the current authentication\");\n }\n }\n const task = await stores.tasks.get(binding.taskId);\n if (\n task === null ||\n task.attempt !== binding.attempt ||\n task.execution?.provider !== \"eve\" ||\n task.execution.sessionId !== ctx.session.id\n ) {\n throw new Error(\"Task execution is missing, inactive, or replaced\");\n }\n return task;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DA,eAAsB,qBACpB,QACA,KACA,iBACA;CACA,MAAM,OAAO,MAAM,6BAA6B,QAAQ,KAAK,eAAe;CAC5E,IAAI,KAAK,UAAU,WACjB,MAAM,IAAI,MAAM,kDAAkD;CAEpE,OAAO;AACT;AAGA,eAAsB,6BACpB,QACA,KACA,iBACA;CACA,MAAM,OAAO,IAAI,SAAS;CAC1B,MAAM,UAAU,sBAAsB,MAAM,SAAS;CACrD,IAAI,QAAQ,WAAW,iBACrB,MAAM,IAAI,MAAM,+CAA+C;CAEjE,KAAK,MAAM,OAAO,CAAC,sBAAsB,2BAA2B,GAAG;EACrE,MAAM,UAAU,MAAM,SAAS,WAAW;EAC1C,IAAI,YAAY,KAAA,KAAa,YAAY,MAAM,WAAW,WAAW,MACnE,MAAM,IAAI,MAAM,wDAAwD;CAE5E;CACA,MAAM,OAAO,MAAM,OAAO,MAAM,IAAI,QAAQ,MAAM;CAClD,IACE,SAAS,QACT,KAAK,YAAY,QAAQ,WACzB,KAAK,WAAW,aAAa,SAC7B,KAAK,UAAU,cAAc,IAAI,QAAQ,IAEzC,MAAM,IAAI,MAAM,kDAAkD;CAEpE,OAAO;AACT"}
@@ -0,0 +1,129 @@
1
+ import { RepositoryId, TaskId } from "../schema/id.mjs";
2
+ import { ReplyTo } from "../schema/common.mjs";
3
+ import { TaskAttemptRef } from "../schema/execution.mjs";
4
+ import { AuthFn } from "eve/channels/auth";
5
+ import { SessionContext } from "eve/context";
6
+ //#region src/eve/task-session.d.ts
7
+ /** HTTP header that carries the authenticated Factory Task ID into an Eve session. */
8
+ declare const factoryTaskHeader = "x-factory-task-id";
9
+ /** Eve authentication attribute that stores the bound Factory Task ID. */
10
+ declare const factoryTaskAttribute = "factoryTaskId";
11
+ /** HTTP header that carries the Task attempt fence into an Eve session. */
12
+ declare const factoryTaskAttemptHeader = "x-factory-task-attempt";
13
+ /** Eve authentication attribute that stores the bound Task attempt fence. */
14
+ declare const factoryTaskAttemptAttribute = "factoryTaskAttempt";
15
+ /** HTTP header that carries the authenticated repository authorization envelope. */
16
+ declare const factoryRepositoryIdsHeader = "x-factory-repository-ids";
17
+ /** HTTP header that carries the authenticated conversation reply channel. */
18
+ declare const factoryReplyChannelHeader = "x-factory-reply-channel";
19
+ /** HTTP header that carries the authenticated conversation reply address. */
20
+ declare const factoryReplyAddressHeader = "x-factory-reply-address";
21
+ /** Eve authentication attribute that stores the authorized repository IDs. */
22
+ declare const factoryRepositoryIdsAttribute = "factoryRepositoryIds";
23
+ /** Eve authentication attribute that stores the conversation reply channel. */
24
+ declare const factoryReplyChannelAttribute = "factoryReplyChannel";
25
+ /** Eve authentication attribute that stores the conversation reply address. */
26
+ declare const factoryReplyAddressAttribute = "factoryReplyAddress";
27
+ type SessionInitiator = SessionContext["session"]["auth"]["initiator"];
28
+ type AuthenticatedSessionInitiator = NonNullable<SessionInitiator>;
29
+ /** The repository authorization envelope and reply destination bound to a conversation. */
30
+ interface FactoryConversationSessionBinding {
31
+ repositoryIds: readonly RepositoryId[];
32
+ replyTo: ReplyTo;
33
+ }
34
+ /** Test whether authenticated Eve session state declares a Factory Task binding. */
35
+ declare function hasFactoryTaskBinding(auth: SessionInitiator): boolean;
36
+ /**
37
+ * Encodes a Task ID and attempt fence as headers for a trusted Eve session request.
38
+ *
39
+ * @remarks
40
+ * These headers are a transport envelope, not standalone authorization. The receiving Eve route
41
+ * must authenticate the trusted caller and wrap that authentication with `withFactoryTask`.
42
+ *
43
+ * @param task - Exact Task and attempt claimed by dispatch.
44
+ * @returns Headers consumed by `withFactoryTask` on the target Eve channel.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * import { taskHeaders } from "@vercel/factory";
49
+ * import type { TaskAttemptRef } from "@vercel/factory/execution";
50
+ *
51
+ * declare const task: TaskAttemptRef;
52
+ * const headers = taskHeaders(task);
53
+ * ```
54
+ */
55
+ declare function taskHeaders(task: TaskAttemptRef): Record<string, string>;
56
+ /** Encode a conversation's repository scope and reply destination as Eve request headers. */
57
+ declare function conversationHeaders(input: {
58
+ repositoryIds: readonly RepositoryId[];
59
+ replyTo: ReplyTo;
60
+ }): Record<string, string>;
61
+ /** Add a validated Task ID and attempt fence to an authenticated Eve initiator. */
62
+ declare function taskSessionAuth(auth: AuthenticatedSessionInitiator, task: TaskAttemptRef): AuthenticatedSessionInitiator;
63
+ /**
64
+ * Requires valid Factory Task headers and binds them into an authenticated Eve initiator.
65
+ *
66
+ * @remarks
67
+ * The wrapped authenticator runs first. If it returns no identity, that result is preserved. For
68
+ * an authenticated caller, both Factory headers are mandatory and validated before their Task ID
69
+ * and attempt are copied into session attributes. This records claimed identity; mutating tools
70
+ * call `requireTaskExecution` to recheck it against current durable Task state.
71
+ *
72
+ * Mount this wrapper only on routes reached through a trusted launcher that supplies
73
+ * `taskHeaders`. It does not independently verify that the caller may claim an arbitrary Task.
74
+ *
75
+ * @param authenticate - Existing Eve request authenticator for the trusted launcher.
76
+ * @returns An authenticator that adds the validated Factory Task binding.
77
+ * @throws `ForbiddenError` when either Task header is absent or malformed.
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * import { withFactoryTask } from "@vercel/factory";
82
+ * import { localDev } from "eve/channels/auth";
83
+ * import { eveChannel } from "eve/channels/eve";
84
+ *
85
+ * export default eveChannel({ auth: [withFactoryTask(localDev())] });
86
+ * ```
87
+ */
88
+ declare function withFactoryTask(authenticate: AuthFn<Request>): AuthFn<Request>;
89
+ /** Bind optional Task and conversation headers while rejecting partial or malformed context. */
90
+ declare function withOptionalFactoryTask(authenticate: AuthFn<Request>): AuthFn<Request>;
91
+ /** Read the required Factory Task ID from authenticated Eve session state. */
92
+ declare function requireTaskIdForSession(auth: SessionInitiator): TaskId;
93
+ /** Read an optional Task ID from authenticated session state, rejecting malformed values. */
94
+ declare function optionalTaskIdForSession(auth: SessionInitiator): TaskId | null;
95
+ /** Read the complete, attempt-fenced Task binding established by Factory authentication. */
96
+ declare function taskBindingForSession(auth: SessionInitiator): TaskAttemptRef;
97
+ /** Read the repository authorization envelope, or null when the session has none. */
98
+ declare function repositoryIdsForSession(auth: SessionInitiator): readonly RepositoryId[] | null;
99
+ /** Read the authenticated reply destination, or null when the session has none. */
100
+ declare function replyToForSession(auth: SessionInitiator): ReplyTo | null;
101
+ /** Read the complete conversation binding, rejecting partial authentication state. */
102
+ declare function conversationBindingForSession(auth: SessionInitiator): FactoryConversationSessionBinding | null;
103
+ /** Authenticated conversation authority assembled from both initiator and current session state. */
104
+ interface ConversationBinding {
105
+ replyTo: ReplyTo;
106
+ /**
107
+ * Repository envelopes the binding carries: the initiator's, plus the current
108
+ * auth's when it restates one. Admitted work must sit inside every envelope.
109
+ */
110
+ repositoryEnvelopes: readonly (readonly RepositoryId[])[];
111
+ parentTask?: TaskAttemptRef;
112
+ }
113
+ /**
114
+ * Read and validate the conversation binding carried on a session's auth pair.
115
+ * The initiator's attributes are authoritative; any binding attribute the
116
+ * current auth restates must agree with them. This is the only reader of the
117
+ * binding attribute encoding; callers never touch `attributes` themselves.
118
+ *
119
+ * Distinct from `conversationBindingForSession`, which reads the initiator
120
+ * alone: admission needs every envelope the pair carries, so that work cannot
121
+ * be admitted into a repository only one side of the pair authorizes.
122
+ */
123
+ declare function conversationBinding(auth: {
124
+ initiator: AuthenticatedSessionInitiator;
125
+ current: AuthenticatedSessionInitiator;
126
+ }): ConversationBinding;
127
+ //#endregion
128
+ export { ConversationBinding, FactoryConversationSessionBinding, conversationBinding, conversationBindingForSession, conversationHeaders, factoryReplyAddressAttribute, factoryReplyAddressHeader, factoryReplyChannelAttribute, factoryReplyChannelHeader, factoryRepositoryIdsAttribute, factoryRepositoryIdsHeader, factoryTaskAttemptAttribute, factoryTaskAttemptHeader, factoryTaskAttribute, factoryTaskHeader, hasFactoryTaskBinding, optionalTaskIdForSession, replyToForSession, repositoryIdsForSession, requireTaskIdForSession, taskBindingForSession, taskHeaders, taskSessionAuth, withFactoryTask, withOptionalFactoryTask };
129
+ //# sourceMappingURL=task-session.d.mts.map
@@ -0,0 +1,245 @@
1
+ import { repositoryIdSchema, taskIdSchema } from "../schema/id.mjs";
2
+ import { replyToSchema } from "../schema/common.mjs";
3
+ import { taskAttemptRef } from "../schema/execution.mjs";
4
+ import { ForbiddenError } from "eve/channels/auth";
5
+ //#region src/eve/task-session.ts
6
+ /** HTTP header that carries the authenticated Factory Task ID into an Eve session. */
7
+ const factoryTaskHeader = "x-factory-task-id";
8
+ /** Eve authentication attribute that stores the bound Factory Task ID. */
9
+ const factoryTaskAttribute = "factoryTaskId";
10
+ /** HTTP header that carries the Task attempt fence into an Eve session. */
11
+ const factoryTaskAttemptHeader = "x-factory-task-attempt";
12
+ /** Eve authentication attribute that stores the bound Task attempt fence. */
13
+ const factoryTaskAttemptAttribute = "factoryTaskAttempt";
14
+ /** HTTP header that carries the authenticated repository authorization envelope. */
15
+ const factoryRepositoryIdsHeader = "x-factory-repository-ids";
16
+ /** HTTP header that carries the authenticated conversation reply channel. */
17
+ const factoryReplyChannelHeader = "x-factory-reply-channel";
18
+ /** HTTP header that carries the authenticated conversation reply address. */
19
+ const factoryReplyAddressHeader = "x-factory-reply-address";
20
+ /** Eve authentication attribute that stores the authorized repository IDs. */
21
+ const factoryRepositoryIdsAttribute = "factoryRepositoryIds";
22
+ /** Eve authentication attribute that stores the conversation reply channel. */
23
+ const factoryReplyChannelAttribute = "factoryReplyChannel";
24
+ /** Eve authentication attribute that stores the conversation reply address. */
25
+ const factoryReplyAddressAttribute = "factoryReplyAddress";
26
+ /** Test whether authenticated Eve session state declares a Factory Task binding. */
27
+ function hasFactoryTaskBinding(auth) {
28
+ return auth?.attributes[factoryTaskAttribute] !== void 0;
29
+ }
30
+ /**
31
+ * Encodes a Task ID and attempt fence as headers for a trusted Eve session request.
32
+ *
33
+ * @remarks
34
+ * These headers are a transport envelope, not standalone authorization. The receiving Eve route
35
+ * must authenticate the trusted caller and wrap that authentication with `withFactoryTask`.
36
+ *
37
+ * @param task - Exact Task and attempt claimed by dispatch.
38
+ * @returns Headers consumed by `withFactoryTask` on the target Eve channel.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * import { taskHeaders } from "@vercel/factory";
43
+ * import type { TaskAttemptRef } from "@vercel/factory/execution";
44
+ *
45
+ * declare const task: TaskAttemptRef;
46
+ * const headers = taskHeaders(task);
47
+ * ```
48
+ */
49
+ function taskHeaders(task) {
50
+ return {
51
+ [factoryTaskHeader]: task.taskId,
52
+ [factoryTaskAttemptHeader]: String(task.attempt)
53
+ };
54
+ }
55
+ /** Encode a conversation's repository scope and reply destination as Eve request headers. */
56
+ function conversationHeaders(input) {
57
+ return {
58
+ [factoryRepositoryIdsHeader]: input.repositoryIds.join(","),
59
+ [factoryReplyChannelHeader]: input.replyTo.channel,
60
+ [factoryReplyAddressHeader]: input.replyTo.address
61
+ };
62
+ }
63
+ /** Add a validated Task ID and attempt fence to an authenticated Eve initiator. */
64
+ function taskSessionAuth(auth, task) {
65
+ return {
66
+ ...auth,
67
+ attributes: {
68
+ ...auth.attributes,
69
+ [factoryTaskAttribute]: task.taskId,
70
+ [factoryTaskAttemptAttribute]: String(task.attempt)
71
+ }
72
+ };
73
+ }
74
+ /**
75
+ * Requires valid Factory Task headers and binds them into an authenticated Eve initiator.
76
+ *
77
+ * @remarks
78
+ * The wrapped authenticator runs first. If it returns no identity, that result is preserved. For
79
+ * an authenticated caller, both Factory headers are mandatory and validated before their Task ID
80
+ * and attempt are copied into session attributes. This records claimed identity; mutating tools
81
+ * call `requireTaskExecution` to recheck it against current durable Task state.
82
+ *
83
+ * Mount this wrapper only on routes reached through a trusted launcher that supplies
84
+ * `taskHeaders`. It does not independently verify that the caller may claim an arbitrary Task.
85
+ *
86
+ * @param authenticate - Existing Eve request authenticator for the trusted launcher.
87
+ * @returns An authenticator that adds the validated Factory Task binding.
88
+ * @throws `ForbiddenError` when either Task header is absent or malformed.
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * import { withFactoryTask } from "@vercel/factory";
93
+ * import { localDev } from "eve/channels/auth";
94
+ * import { eveChannel } from "eve/channels/eve";
95
+ *
96
+ * export default eveChannel({ auth: [withFactoryTask(localDev())] });
97
+ * ```
98
+ */
99
+ function withFactoryTask(authenticate) {
100
+ return async (request) => {
101
+ const auth = await authenticate(request);
102
+ if (auth == null) return auth;
103
+ const parsedTask = taskIdSchema.safeParse(request.headers.get(factoryTaskHeader));
104
+ const parsedAttempt = parseTaskAttempt(request.headers.get(factoryTaskAttemptHeader));
105
+ if (!parsedTask.success || parsedAttempt === null) throw new ForbiddenError();
106
+ return taskSessionAuth(auth, taskAttemptRef(parsedTask.data, parsedAttempt));
107
+ };
108
+ }
109
+ /** Bind optional Task and conversation headers while rejecting partial or malformed context. */
110
+ function withOptionalFactoryTask(authenticate) {
111
+ return async (request) => {
112
+ const auth = await authenticate(request);
113
+ if (auth == null) return auth;
114
+ const taskId = request.headers.get(factoryTaskHeader);
115
+ const taskAttempt = request.headers.get(factoryTaskAttemptHeader);
116
+ const repositoryIds = request.headers.get(factoryRepositoryIdsHeader);
117
+ const replyChannel = request.headers.get(factoryReplyChannelHeader);
118
+ const replyAddress = request.headers.get(factoryReplyAddressHeader);
119
+ const hasConversationBinding = repositoryIds !== null || replyChannel !== null || replyAddress !== null;
120
+ if (taskId === null && taskAttempt === null && !hasConversationBinding) return auth;
121
+ const parsedTask = taskId === null ? null : taskIdSchema.safeParse(taskId);
122
+ const parsedAttempt = parseTaskAttempt(taskAttempt);
123
+ const parsedRepositories = repositoryIds === null ? null : repositoryIdSchema.array().min(1).safeParse(repositoryIds.split(",").filter(Boolean));
124
+ const parsedReplyTo = replyChannel === null || replyAddress === null ? null : replyToSchema.safeParse({
125
+ channel: replyChannel,
126
+ address: replyAddress
127
+ });
128
+ if (parsedTask !== null && !parsedTask.success || parsedTask === null !== (parsedAttempt === null) || hasConversationBinding && (parsedRepositories === null || !parsedRepositories.success || parsedReplyTo === null || !parsedReplyTo.success)) throw new ForbiddenError();
129
+ const conversationAttributes = parsedRepositories?.success === true && parsedReplyTo?.success === true ? {
130
+ [factoryRepositoryIdsAttribute]: parsedRepositories.data.join(","),
131
+ [factoryReplyChannelAttribute]: parsedReplyTo.data.channel,
132
+ [factoryReplyAddressAttribute]: parsedReplyTo.data.address
133
+ } : {};
134
+ return {
135
+ ...auth,
136
+ attributes: {
137
+ ...auth.attributes,
138
+ ...parsedTask === null || parsedAttempt === null ? {} : {
139
+ [factoryTaskAttribute]: parsedTask.data,
140
+ [factoryTaskAttemptAttribute]: String(parsedAttempt)
141
+ },
142
+ ...conversationAttributes
143
+ }
144
+ };
145
+ };
146
+ }
147
+ /** Read the required Factory Task ID from authenticated Eve session state. */
148
+ function requireTaskIdForSession(auth) {
149
+ return taskIdSchema.parse(auth?.attributes[factoryTaskAttribute]);
150
+ }
151
+ /** Read an optional Task ID from authenticated session state, rejecting malformed values. */
152
+ function optionalTaskIdForSession(auth) {
153
+ const value = auth?.attributes[factoryTaskAttribute];
154
+ return value === void 0 ? null : taskIdSchema.parse(value);
155
+ }
156
+ /** Read the complete, attempt-fenced Task binding established by Factory authentication. */
157
+ function taskBindingForSession(auth) {
158
+ const taskId = requireTaskIdForSession(auth);
159
+ const rawAttempt = auth?.attributes[factoryTaskAttemptAttribute];
160
+ const attempt = parseTaskAttempt(typeof rawAttempt === "string" ? rawAttempt : null);
161
+ if (attempt === null) throw new Error("Factory session Task attempt binding is invalid.");
162
+ return {
163
+ taskId,
164
+ attempt
165
+ };
166
+ }
167
+ /** Read the repository authorization envelope, or null when the session has none. */
168
+ function repositoryIdsForSession(auth) {
169
+ const value = auth?.attributes[factoryRepositoryIdsAttribute];
170
+ if (value === void 0) return null;
171
+ return repositoryIdSchema.array().min(1).parse(typeof value === "string" ? value.split(",").filter(Boolean) : value);
172
+ }
173
+ /** Read the authenticated reply destination, or null when the session has none. */
174
+ function replyToForSession(auth) {
175
+ const channel = auth?.attributes[factoryReplyChannelAttribute];
176
+ const address = auth?.attributes[factoryReplyAddressAttribute];
177
+ if (channel === void 0 && address === void 0) return null;
178
+ return replyToSchema.parse({
179
+ channel,
180
+ address
181
+ });
182
+ }
183
+ /** Read the complete conversation binding, rejecting partial authentication state. */
184
+ function conversationBindingForSession(auth) {
185
+ const repositoryIds = repositoryIdsForSession(auth);
186
+ const replyTo = replyToForSession(auth);
187
+ if (repositoryIds === null && replyTo === null) return null;
188
+ if (repositoryIds === null || replyTo === null) throw new Error("Factory session conversation binding is incomplete.");
189
+ return {
190
+ repositoryIds,
191
+ replyTo
192
+ };
193
+ }
194
+ const conversationBindingAttributes = [
195
+ factoryReplyChannelAttribute,
196
+ factoryReplyAddressAttribute,
197
+ factoryTaskAttribute,
198
+ factoryTaskAttemptAttribute
199
+ ];
200
+ /**
201
+ * Read and validate the conversation binding carried on a session's auth pair.
202
+ * The initiator's attributes are authoritative; any binding attribute the
203
+ * current auth restates must agree with them. This is the only reader of the
204
+ * binding attribute encoding; callers never touch `attributes` themselves.
205
+ *
206
+ * Distinct from `conversationBindingForSession`, which reads the initiator
207
+ * alone: admission needs every envelope the pair carries, so that work cannot
208
+ * be admitted into a repository only one side of the pair authorizes.
209
+ */
210
+ function conversationBinding(auth) {
211
+ const attributes = auth.initiator.attributes;
212
+ const replyTo = replyToSchema.parse({
213
+ channel: attributes[factoryReplyChannelAttribute],
214
+ address: attributes[factoryReplyAddressAttribute]
215
+ });
216
+ for (const key of conversationBindingAttributes) if (auth.current.attributes[key] !== void 0 && auth.current.attributes[key] !== attributes[key]) throw new Error("Conversation binding does not match the authenticated conversation");
217
+ const repositoryEnvelopes = [];
218
+ for (const [index, entry] of [auth.initiator, auth.current].entries()) {
219
+ const raw = entry.attributes[factoryRepositoryIdsAttribute];
220
+ if (index === 1 && raw === void 0) continue;
221
+ repositoryEnvelopes.push(repositoryIdSchema.array().min(1).parse(typeof raw === "string" ? raw.split(",") : raw));
222
+ }
223
+ let parentTask;
224
+ if (attributes["factoryTaskId"] !== void 0 || attributes["factoryTaskAttempt"] !== void 0) {
225
+ const taskId = taskIdSchema.parse(attributes[factoryTaskAttribute]);
226
+ const rawAttempt = attributes[factoryTaskAttemptAttribute];
227
+ const attempt = typeof rawAttempt === "string" ? parseTaskAttempt(rawAttempt) : null;
228
+ if (attempt === null) throw new Error("Conversation binding carries an invalid parent attempt");
229
+ parentTask = taskAttemptRef(taskId, attempt);
230
+ }
231
+ return {
232
+ replyTo,
233
+ repositoryEnvelopes,
234
+ parentTask
235
+ };
236
+ }
237
+ function parseTaskAttempt(value) {
238
+ if (value === null || !/^[1-9]\d*$/u.test(value)) return null;
239
+ const attempt = Number(value);
240
+ return Number.isSafeInteger(attempt) ? attempt : null;
241
+ }
242
+ //#endregion
243
+ export { conversationBinding, conversationBindingForSession, conversationHeaders, factoryReplyAddressAttribute, factoryReplyAddressHeader, factoryReplyChannelAttribute, factoryReplyChannelHeader, factoryRepositoryIdsAttribute, factoryRepositoryIdsHeader, factoryTaskAttemptAttribute, factoryTaskAttemptHeader, factoryTaskAttribute, factoryTaskHeader, hasFactoryTaskBinding, optionalTaskIdForSession, replyToForSession, repositoryIdsForSession, requireTaskIdForSession, taskBindingForSession, taskHeaders, taskSessionAuth, withFactoryTask, withOptionalFactoryTask };
244
+
245
+ //# sourceMappingURL=task-session.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-session.mjs","names":[],"sources":["../../src/eve/task-session.ts"],"sourcesContent":["import { repositoryIdSchema, taskIdSchema } from \"../schema/id\";\nimport { replyToSchema, type ReplyTo } from \"../schema/common\";\nimport { taskAttemptRef, type TaskAttemptRef } from \"../schema/execution\";\nimport type { RepositoryId, TaskId } from \"../schema/id\";\nimport { ForbiddenError, type AuthFn } from \"eve/channels/auth\";\nimport type { SessionContext } from \"eve/context\";\n\n/** HTTP header that carries the authenticated Factory Task ID into an Eve session. */\nexport const factoryTaskHeader = \"x-factory-task-id\";\n/** Eve authentication attribute that stores the bound Factory Task ID. */\nexport const factoryTaskAttribute = \"factoryTaskId\";\n/** HTTP header that carries the Task attempt fence into an Eve session. */\nexport const factoryTaskAttemptHeader = \"x-factory-task-attempt\";\n/** Eve authentication attribute that stores the bound Task attempt fence. */\nexport const factoryTaskAttemptAttribute = \"factoryTaskAttempt\";\n/** HTTP header that carries the authenticated repository authorization envelope. */\nexport const factoryRepositoryIdsHeader = \"x-factory-repository-ids\";\n/** HTTP header that carries the authenticated conversation reply channel. */\nexport const factoryReplyChannelHeader = \"x-factory-reply-channel\";\n/** HTTP header that carries the authenticated conversation reply address. */\nexport const factoryReplyAddressHeader = \"x-factory-reply-address\";\n/** Eve authentication attribute that stores the authorized repository IDs. */\nexport const factoryRepositoryIdsAttribute = \"factoryRepositoryIds\";\n/** Eve authentication attribute that stores the conversation reply channel. */\nexport const factoryReplyChannelAttribute = \"factoryReplyChannel\";\n/** Eve authentication attribute that stores the conversation reply address. */\nexport const factoryReplyAddressAttribute = \"factoryReplyAddress\";\n\ntype SessionInitiator = SessionContext[\"session\"][\"auth\"][\"initiator\"];\ntype AuthenticatedSessionInitiator = NonNullable<SessionInitiator>;\n\n/** The repository authorization envelope and reply destination bound to a conversation. */\nexport interface FactoryConversationSessionBinding {\n repositoryIds: readonly RepositoryId[];\n replyTo: ReplyTo;\n}\n\n/** Test whether authenticated Eve session state declares a Factory Task binding. */\nexport function hasFactoryTaskBinding(auth: SessionInitiator): boolean {\n return auth?.attributes[factoryTaskAttribute] !== undefined;\n}\n\n/**\n * Encodes a Task ID and attempt fence as headers for a trusted Eve session request.\n *\n * @remarks\n * These headers are a transport envelope, not standalone authorization. The receiving Eve route\n * must authenticate the trusted caller and wrap that authentication with `withFactoryTask`.\n *\n * @param task - Exact Task and attempt claimed by dispatch.\n * @returns Headers consumed by `withFactoryTask` on the target Eve channel.\n *\n * @example\n * ```ts\n * import { taskHeaders } from \"@vercel/factory\";\n * import type { TaskAttemptRef } from \"@vercel/factory/execution\";\n *\n * declare const task: TaskAttemptRef;\n * const headers = taskHeaders(task);\n * ```\n */\nexport function taskHeaders(task: TaskAttemptRef): Record<string, string> {\n return {\n [factoryTaskHeader]: task.taskId,\n [factoryTaskAttemptHeader]: String(task.attempt),\n };\n}\n\n/** Encode a conversation's repository scope and reply destination as Eve request headers. */\nexport function conversationHeaders(input: {\n repositoryIds: readonly RepositoryId[];\n replyTo: ReplyTo;\n}): Record<string, string> {\n return {\n [factoryRepositoryIdsHeader]: input.repositoryIds.join(\",\"),\n [factoryReplyChannelHeader]: input.replyTo.channel,\n [factoryReplyAddressHeader]: input.replyTo.address,\n };\n}\n\n/** Add a validated Task ID and attempt fence to an authenticated Eve initiator. */\nexport function taskSessionAuth(\n auth: AuthenticatedSessionInitiator,\n task: TaskAttemptRef,\n): AuthenticatedSessionInitiator {\n return {\n ...auth,\n attributes: {\n ...auth.attributes,\n [factoryTaskAttribute]: task.taskId,\n [factoryTaskAttemptAttribute]: String(task.attempt),\n },\n };\n}\n\n/**\n * Requires valid Factory Task headers and binds them into an authenticated Eve initiator.\n *\n * @remarks\n * The wrapped authenticator runs first. If it returns no identity, that result is preserved. For\n * an authenticated caller, both Factory headers are mandatory and validated before their Task ID\n * and attempt are copied into session attributes. This records claimed identity; mutating tools\n * call `requireTaskExecution` to recheck it against current durable Task state.\n *\n * Mount this wrapper only on routes reached through a trusted launcher that supplies\n * `taskHeaders`. It does not independently verify that the caller may claim an arbitrary Task.\n *\n * @param authenticate - Existing Eve request authenticator for the trusted launcher.\n * @returns An authenticator that adds the validated Factory Task binding.\n * @throws `ForbiddenError` when either Task header is absent or malformed.\n *\n * @example\n * ```ts\n * import { withFactoryTask } from \"@vercel/factory\";\n * import { localDev } from \"eve/channels/auth\";\n * import { eveChannel } from \"eve/channels/eve\";\n *\n * export default eveChannel({ auth: [withFactoryTask(localDev())] });\n * ```\n */\nexport function withFactoryTask(authenticate: AuthFn<Request>): AuthFn<Request> {\n return async (request) => {\n const auth = await authenticate(request);\n if (auth == null) return auth;\n const parsedTask = taskIdSchema.safeParse(request.headers.get(factoryTaskHeader));\n const parsedAttempt = parseTaskAttempt(request.headers.get(factoryTaskAttemptHeader));\n if (!parsedTask.success || parsedAttempt === null) throw new ForbiddenError();\n return taskSessionAuth(auth, taskAttemptRef(parsedTask.data, parsedAttempt));\n };\n}\n\n/** Bind optional Task and conversation headers while rejecting partial or malformed context. */\nexport function withOptionalFactoryTask(authenticate: AuthFn<Request>): AuthFn<Request> {\n return async (request) => {\n const auth = await authenticate(request);\n if (auth == null) return auth;\n const taskId = request.headers.get(factoryTaskHeader);\n const taskAttempt = request.headers.get(factoryTaskAttemptHeader);\n const repositoryIds = request.headers.get(factoryRepositoryIdsHeader);\n const replyChannel = request.headers.get(factoryReplyChannelHeader);\n const replyAddress = request.headers.get(factoryReplyAddressHeader);\n const hasConversationBinding =\n repositoryIds !== null || replyChannel !== null || replyAddress !== null;\n if (taskId === null && taskAttempt === null && !hasConversationBinding) return auth;\n const parsedTask = taskId === null ? null : taskIdSchema.safeParse(taskId);\n const parsedAttempt = parseTaskAttempt(taskAttempt);\n const parsedRepositories =\n repositoryIds === null\n ? null\n : repositoryIdSchema.array().min(1).safeParse(repositoryIds.split(\",\").filter(Boolean));\n const parsedReplyTo =\n replyChannel === null || replyAddress === null\n ? null\n : replyToSchema.safeParse({ channel: replyChannel, address: replyAddress });\n if (\n (parsedTask !== null && !parsedTask.success) ||\n (parsedTask === null) !== (parsedAttempt === null) ||\n (hasConversationBinding &&\n (parsedRepositories === null ||\n !parsedRepositories.success ||\n parsedReplyTo === null ||\n !parsedReplyTo.success))\n ) {\n throw new ForbiddenError();\n }\n const conversationAttributes: Record<string, string> =\n parsedRepositories?.success === true && parsedReplyTo?.success === true\n ? {\n [factoryRepositoryIdsAttribute]: parsedRepositories.data.join(\",\"),\n [factoryReplyChannelAttribute]: parsedReplyTo.data.channel,\n [factoryReplyAddressAttribute]: parsedReplyTo.data.address,\n }\n : {};\n return {\n ...auth,\n attributes: {\n ...auth.attributes,\n ...(parsedTask === null || parsedAttempt === null\n ? {}\n : {\n [factoryTaskAttribute]: parsedTask.data,\n [factoryTaskAttemptAttribute]: String(parsedAttempt),\n }),\n ...conversationAttributes,\n },\n };\n };\n}\n\n/** Read the required Factory Task ID from authenticated Eve session state. */\nexport function requireTaskIdForSession(auth: SessionInitiator): TaskId {\n return taskIdSchema.parse(auth?.attributes[factoryTaskAttribute]);\n}\n\n/** Read an optional Task ID from authenticated session state, rejecting malformed values. */\nexport function optionalTaskIdForSession(auth: SessionInitiator): TaskId | null {\n const value = auth?.attributes[factoryTaskAttribute];\n return value === undefined ? null : taskIdSchema.parse(value);\n}\n\n/** Read the complete, attempt-fenced Task binding established by Factory authentication. */\nexport function taskBindingForSession(auth: SessionInitiator): TaskAttemptRef {\n const taskId = requireTaskIdForSession(auth);\n const rawAttempt = auth?.attributes[factoryTaskAttemptAttribute];\n const attempt = parseTaskAttempt(typeof rawAttempt === \"string\" ? rawAttempt : null);\n if (attempt === null) throw new Error(\"Factory session Task attempt binding is invalid.\");\n return { taskId, attempt };\n}\n\n/** Read the repository authorization envelope, or null when the session has none. */\nexport function repositoryIdsForSession(auth: SessionInitiator): readonly RepositoryId[] | null {\n const value = auth?.attributes[factoryRepositoryIdsAttribute];\n if (value === undefined) return null;\n return repositoryIdSchema\n .array()\n .min(1)\n .parse(typeof value === \"string\" ? value.split(\",\").filter(Boolean) : value);\n}\n\n/** Read the authenticated reply destination, or null when the session has none. */\nexport function replyToForSession(auth: SessionInitiator): ReplyTo | null {\n const channel = auth?.attributes[factoryReplyChannelAttribute];\n const address = auth?.attributes[factoryReplyAddressAttribute];\n if (channel === undefined && address === undefined) return null;\n return replyToSchema.parse({ channel, address });\n}\n\n/** Read the complete conversation binding, rejecting partial authentication state. */\nexport function conversationBindingForSession(\n auth: SessionInitiator,\n): FactoryConversationSessionBinding | null {\n const repositoryIds = repositoryIdsForSession(auth);\n const replyTo = replyToForSession(auth);\n if (repositoryIds === null && replyTo === null) return null;\n if (repositoryIds === null || replyTo === null) {\n throw new Error(\"Factory session conversation binding is incomplete.\");\n }\n return { repositoryIds, replyTo };\n}\n\n/** Authenticated conversation authority assembled from both initiator and current session state. */\nexport interface ConversationBinding {\n replyTo: ReplyTo;\n /**\n * Repository envelopes the binding carries: the initiator's, plus the current\n * auth's when it restates one. Admitted work must sit inside every envelope.\n */\n repositoryEnvelopes: readonly (readonly RepositoryId[])[];\n parentTask?: TaskAttemptRef;\n}\n\nconst conversationBindingAttributes = [\n factoryReplyChannelAttribute,\n factoryReplyAddressAttribute,\n factoryTaskAttribute,\n factoryTaskAttemptAttribute,\n] as const;\n\n/**\n * Read and validate the conversation binding carried on a session's auth pair.\n * The initiator's attributes are authoritative; any binding attribute the\n * current auth restates must agree with them. This is the only reader of the\n * binding attribute encoding; callers never touch `attributes` themselves.\n *\n * Distinct from `conversationBindingForSession`, which reads the initiator\n * alone: admission needs every envelope the pair carries, so that work cannot\n * be admitted into a repository only one side of the pair authorizes.\n */\nexport function conversationBinding(auth: {\n initiator: AuthenticatedSessionInitiator;\n current: AuthenticatedSessionInitiator;\n}): ConversationBinding {\n const attributes = auth.initiator.attributes;\n const replyTo = replyToSchema.parse({\n channel: attributes[factoryReplyChannelAttribute],\n address: attributes[factoryReplyAddressAttribute],\n });\n for (const key of conversationBindingAttributes) {\n if (\n auth.current.attributes[key] !== undefined &&\n auth.current.attributes[key] !== attributes[key]\n )\n throw new Error(\"Conversation binding does not match the authenticated conversation\");\n }\n const repositoryEnvelopes: (readonly RepositoryId[])[] = [];\n for (const [index, entry] of [auth.initiator, auth.current].entries()) {\n const raw = entry.attributes[factoryRepositoryIdsAttribute];\n if (index === 1 && raw === undefined) continue;\n repositoryEnvelopes.push(\n repositoryIdSchema\n .array()\n .min(1)\n .parse(typeof raw === \"string\" ? raw.split(\",\") : raw),\n );\n }\n let parentTask: ConversationBinding[\"parentTask\"];\n if (\n attributes[factoryTaskAttribute] !== undefined ||\n attributes[factoryTaskAttemptAttribute] !== undefined\n ) {\n const taskId = taskIdSchema.parse(attributes[factoryTaskAttribute]);\n const rawAttempt = attributes[factoryTaskAttemptAttribute];\n const attempt = typeof rawAttempt === \"string\" ? parseTaskAttempt(rawAttempt) : null;\n if (attempt === null) throw new Error(\"Conversation binding carries an invalid parent attempt\");\n parentTask = taskAttemptRef(taskId, attempt);\n }\n return { replyTo, repositoryEnvelopes, parentTask };\n}\n\nfunction parseTaskAttempt(value: string | null): number | null {\n if (value === null || !/^[1-9]\\d*$/u.test(value)) return null;\n const attempt = Number(value);\n return Number.isSafeInteger(attempt) ? attempt : null;\n}\n"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { RepositoryId } from "../schema/id.mjs";
2
+ import { MaybePromise, ReplyTo } from "../schema/common.mjs";
3
+ import { TaskAttemptRef } from "../schema/execution.mjs";
4
+ import { FactoryStores } from "../store/engine.mjs";
5
+ //#region src/eve/transcript.d.ts
6
+ /** Identifies the Eve execution and authenticated attributes to project into a transcript. */
7
+ interface TranscriptMaterializationInput {
8
+ agent: string;
9
+ execution: {
10
+ provider: "eve";
11
+ sessionId: string;
12
+ };
13
+ attributes: Readonly<Record<string, string | readonly string[]>>;
14
+ }
15
+ /** The Task and conversation authorization context forwarded when reading an Eve transcript. */
16
+ interface EveTranscriptRequestScope {
17
+ task?: TaskAttemptRef;
18
+ conversation?: {
19
+ repositoryIds: readonly RepositoryId[];
20
+ replyTo: ReplyTo;
21
+ };
22
+ }
23
+ /** Configures durable transcript storage and authenticated access to Eve session events. */
24
+ interface EveTranscriptMaterializerOptions {
25
+ stores: Pick<FactoryStores, "transcripts">;
26
+ origin: string | (() => string);
27
+ headers?(scope: EveTranscriptRequestScope): MaybePromise<HeadersInit>;
28
+ fetch?: typeof globalThis.fetch;
29
+ timeoutMs?: number;
30
+ }
31
+ /** Materializes one Eve execution stream into Factory's browser-safe transcript store. */
32
+ type EveTranscriptMaterializer = (input: TranscriptMaterializationInput) => Promise<void>;
33
+ /** Materialize a browser-safe transcript projection from one durable Eve session stream. */
34
+ declare function createEveTranscriptMaterializer(options: EveTranscriptMaterializerOptions): EveTranscriptMaterializer;
35
+ //#endregion
36
+ export { EveTranscriptMaterializer, EveTranscriptMaterializerOptions, EveTranscriptRequestScope, TranscriptMaterializationInput, createEveTranscriptMaterializer };
37
+ //# sourceMappingURL=transcript.d.mts.map
@@ -0,0 +1,69 @@
1
+ import { repositoryIdSchema, taskIdSchema } from "../schema/id.mjs";
2
+ import { replyToSchema } from "../schema/common.mjs";
3
+ import { taskAttemptRef } from "../schema/execution.mjs";
4
+ import { factoryReplyAddressAttribute, factoryReplyChannelAttribute, factoryRepositoryIdsAttribute, factoryTaskAttemptAttribute, factoryTaskAttribute } from "./task-session.mjs";
5
+ import { readEvents } from "../client-events.mjs";
6
+ import { Transcript } from "../client-transcript.mjs";
7
+ //#region src/eve/transcript.ts
8
+ function attribute(attributes, name) {
9
+ const value = attributes[name];
10
+ return typeof value === "string" ? value : void 0;
11
+ }
12
+ function scopeFor(input) {
13
+ const taskId = taskIdSchema.safeParse(attribute(input.attributes, factoryTaskAttribute));
14
+ const attempt = Number(attribute(input.attributes, factoryTaskAttemptAttribute));
15
+ const repositories = repositoryIdSchema.array().min(1).safeParse(attribute(input.attributes, factoryRepositoryIdsAttribute)?.split(",").filter(Boolean));
16
+ const replyTo = replyToSchema.safeParse({
17
+ channel: attribute(input.attributes, factoryReplyChannelAttribute),
18
+ address: attribute(input.attributes, factoryReplyAddressAttribute)
19
+ });
20
+ return {
21
+ ...taskId.success && Number.isSafeInteger(attempt) && attempt > 0 ? { task: taskAttemptRef(taskId.data, attempt) } : {},
22
+ ...repositories.success && replyTo.success ? { conversation: {
23
+ repositoryIds: repositories.data,
24
+ replyTo: replyTo.data
25
+ } } : {}
26
+ };
27
+ }
28
+ /** Materialize a browser-safe transcript projection from one durable Eve session stream. */
29
+ function createEveTranscriptMaterializer(options) {
30
+ const fetchImplementation = options.fetch ?? globalThis.fetch;
31
+ const timeoutMs = options.timeoutMs ?? 3e4;
32
+ return async (input) => {
33
+ const previous = await options.stores.transcripts.get(input.execution);
34
+ const transcript = new Transcript();
35
+ if (previous !== null) transcript.hydrate(previous);
36
+ const query = new URLSearchParams({
37
+ startIndex: String(transcript.cursor),
38
+ includeTailIndex: "1"
39
+ });
40
+ const origin = typeof options.origin === "string" ? options.origin : options.origin();
41
+ const response = await fetchImplementation(`${origin.replace(/\/+$/u, "")}/eve/agents/${encodeURIComponent(input.agent)}/eve/v1/session/${encodeURIComponent(input.execution.sessionId)}/stream?${query}`, {
42
+ cache: "no-store",
43
+ headers: await options.headers?.(scopeFor(input)),
44
+ signal: AbortSignal.timeout(timeoutMs),
45
+ redirect: "error"
46
+ });
47
+ if (!response.ok || !response.body) {
48
+ await response.body?.cancel();
49
+ throw new Error(`Eve refused transcript materialization: ${response.status}`);
50
+ }
51
+ const tailValue = response.headers.get("x-eve-stream-tail-index");
52
+ const tail = tailValue === null ? NaN : Number(tailValue);
53
+ if (!Number.isSafeInteger(tail) || tail < -1) {
54
+ await response.body.cancel();
55
+ throw new Error("Eve transcript materialization did not include a valid durable cursor");
56
+ }
57
+ if (transcript.cursor <= tail) for await (const event of readEvents(response.body)) {
58
+ transcript.accept(event);
59
+ if (transcript.cursor === tail + 1) break;
60
+ }
61
+ else await response.body.cancel();
62
+ if (transcript.cursor !== tail + 1) throw new Error("Eve transcript materialization closed before its durable cursor");
63
+ await options.stores.transcripts.put(input.execution, transcript.snapshot());
64
+ };
65
+ }
66
+ //#endregion
67
+ export { createEveTranscriptMaterializer };
68
+
69
+ //# sourceMappingURL=transcript.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript.mjs","names":[],"sources":["../../src/eve/transcript.ts"],"sourcesContent":["import { readEvents } from \"../client-events\";\nimport { Transcript } from \"../client-transcript\";\nimport { replyToSchema, type MaybePromise, type ReplyTo } from \"../schema/common\";\nimport { taskAttemptRef, type TaskAttemptRef } from \"../schema/execution\";\nimport { repositoryIdSchema, taskIdSchema, type RepositoryId } from \"../schema/id\";\nimport type { FactoryStores } from \"../store/engine\";\nimport {\n factoryReplyAddressAttribute,\n factoryReplyChannelAttribute,\n factoryRepositoryIdsAttribute,\n factoryTaskAttemptAttribute,\n factoryTaskAttribute,\n} from \"./task-session\";\n\n/** Identifies the Eve execution and authenticated attributes to project into a transcript. */\nexport interface TranscriptMaterializationInput {\n agent: string;\n execution: { provider: \"eve\"; sessionId: string };\n attributes: Readonly<Record<string, string | readonly string[]>>;\n}\n\n/** The Task and conversation authorization context forwarded when reading an Eve transcript. */\nexport interface EveTranscriptRequestScope {\n task?: TaskAttemptRef;\n conversation?: { repositoryIds: readonly RepositoryId[]; replyTo: ReplyTo };\n}\n\n/** Configures durable transcript storage and authenticated access to Eve session events. */\nexport interface EveTranscriptMaterializerOptions {\n stores: Pick<FactoryStores, \"transcripts\">;\n origin: string | (() => string);\n headers?(scope: EveTranscriptRequestScope): MaybePromise<HeadersInit>;\n fetch?: typeof globalThis.fetch;\n timeoutMs?: number;\n}\n\n/** Materializes one Eve execution stream into Factory's browser-safe transcript store. */\nexport type EveTranscriptMaterializer = (input: TranscriptMaterializationInput) => Promise<void>;\n\nfunction attribute(\n attributes: TranscriptMaterializationInput[\"attributes\"],\n name: string,\n): string | undefined {\n const value = attributes[name];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction scopeFor(input: TranscriptMaterializationInput): EveTranscriptRequestScope {\n const taskId = taskIdSchema.safeParse(attribute(input.attributes, factoryTaskAttribute));\n const attempt = Number(attribute(input.attributes, factoryTaskAttemptAttribute));\n const repositories = repositoryIdSchema\n .array()\n .min(1)\n .safeParse(\n attribute(input.attributes, factoryRepositoryIdsAttribute)?.split(\",\").filter(Boolean),\n );\n const replyTo = replyToSchema.safeParse({\n channel: attribute(input.attributes, factoryReplyChannelAttribute),\n address: attribute(input.attributes, factoryReplyAddressAttribute),\n });\n return {\n ...(taskId.success && Number.isSafeInteger(attempt) && attempt > 0\n ? { task: taskAttemptRef(taskId.data, attempt) }\n : {}),\n ...(repositories.success && replyTo.success\n ? { conversation: { repositoryIds: repositories.data, replyTo: replyTo.data } }\n : {}),\n };\n}\n\n/** Materialize a browser-safe transcript projection from one durable Eve session stream. */\nexport function createEveTranscriptMaterializer(\n options: EveTranscriptMaterializerOptions,\n): EveTranscriptMaterializer {\n const fetchImplementation = options.fetch ?? globalThis.fetch;\n const timeoutMs = options.timeoutMs ?? 30_000;\n return async (input: TranscriptMaterializationInput): Promise<void> => {\n const previous = await options.stores.transcripts.get(input.execution);\n const transcript = new Transcript();\n if (previous !== null) transcript.hydrate(previous);\n const query = new URLSearchParams({\n startIndex: String(transcript.cursor),\n includeTailIndex: \"1\",\n });\n const origin = typeof options.origin === \"string\" ? options.origin : options.origin();\n const response = await fetchImplementation(\n `${origin.replace(/\\/+$/u, \"\")}/eve/agents/${encodeURIComponent(input.agent)}/eve/v1/session/${encodeURIComponent(input.execution.sessionId)}/stream?${query}`,\n {\n cache: \"no-store\",\n headers: await options.headers?.(scopeFor(input)),\n signal: AbortSignal.timeout(timeoutMs),\n redirect: \"error\",\n },\n );\n if (!response.ok || !response.body) {\n await response.body?.cancel();\n throw new Error(`Eve refused transcript materialization: ${response.status}`);\n }\n const tailValue = response.headers.get(\"x-eve-stream-tail-index\");\n const tail = tailValue === null ? Number.NaN : Number(tailValue);\n if (!Number.isSafeInteger(tail) || tail < -1) {\n await response.body.cancel();\n throw new Error(\"Eve transcript materialization did not include a valid durable cursor\");\n }\n if (transcript.cursor <= tail) {\n for await (const event of readEvents(response.body)) {\n transcript.accept(event);\n if (transcript.cursor === tail + 1) break;\n }\n } else {\n await response.body.cancel();\n }\n if (transcript.cursor !== tail + 1) {\n throw new Error(\"Eve transcript materialization closed before its durable cursor\");\n }\n await options.stores.transcripts.put(input.execution, transcript.snapshot());\n };\n}\n"],"mappings":";;;;;;;AAuCA,SAAS,UACP,YACA,MACoB;CACpB,MAAM,QAAQ,WAAW;CACzB,OAAO,OAAO,UAAU,WAAW,QAAQ,KAAA;AAC7C;AAEA,SAAS,SAAS,OAAkE;CAClF,MAAM,SAAS,aAAa,UAAU,UAAU,MAAM,YAAY,oBAAoB,CAAC;CACvF,MAAM,UAAU,OAAO,UAAU,MAAM,YAAY,2BAA2B,CAAC;CAC/E,MAAM,eAAe,mBAClB,MAAM,CAAC,CACP,IAAI,CAAC,CAAC,CACN,UACC,UAAU,MAAM,YAAY,6BAA6B,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO,CACvF;CACF,MAAM,UAAU,cAAc,UAAU;EACtC,SAAS,UAAU,MAAM,YAAY,4BAA4B;EACjE,SAAS,UAAU,MAAM,YAAY,4BAA4B;CACnE,CAAC;CACD,OAAO;EACL,GAAI,OAAO,WAAW,OAAO,cAAc,OAAO,KAAK,UAAU,IAC7D,EAAE,MAAM,eAAe,OAAO,MAAM,OAAO,EAAE,IAC7C,CAAC;EACL,GAAI,aAAa,WAAW,QAAQ,UAChC,EAAE,cAAc;GAAE,eAAe,aAAa;GAAM,SAAS,QAAQ;EAAK,EAAE,IAC5E,CAAC;CACP;AACF;;AAGA,SAAgB,gCACd,SAC2B;CAC3B,MAAM,sBAAsB,QAAQ,SAAS,WAAW;CACxD,MAAM,YAAY,QAAQ,aAAa;CACvC,OAAO,OAAO,UAAyD;EACrE,MAAM,WAAW,MAAM,QAAQ,OAAO,YAAY,IAAI,MAAM,SAAS;EACrE,MAAM,aAAa,IAAI,WAAW;EAClC,IAAI,aAAa,MAAM,WAAW,QAAQ,QAAQ;EAClD,MAAM,QAAQ,IAAI,gBAAgB;GAChC,YAAY,OAAO,WAAW,MAAM;GACpC,kBAAkB;EACpB,CAAC;EACD,MAAM,SAAS,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS,QAAQ,OAAO;EACpF,MAAM,WAAW,MAAM,oBACrB,GAAG,OAAO,QAAQ,SAAS,EAAE,EAAE,cAAc,mBAAmB,MAAM,KAAK,EAAE,kBAAkB,mBAAmB,MAAM,UAAU,SAAS,EAAE,UAAU,SACvJ;GACE,OAAO;GACP,SAAS,MAAM,QAAQ,UAAU,SAAS,KAAK,CAAC;GAChD,QAAQ,YAAY,QAAQ,SAAS;GACrC,UAAU;EACZ,CACF;EACA,IAAI,CAAC,SAAS,MAAM,CAAC,SAAS,MAAM;GAClC,MAAM,SAAS,MAAM,OAAO;GAC5B,MAAM,IAAI,MAAM,2CAA2C,SAAS,QAAQ;EAC9E;EACA,MAAM,YAAY,SAAS,QAAQ,IAAI,yBAAyB;EAChE,MAAM,OAAO,cAAc,OAAO,MAAa,OAAO,SAAS;EAC/D,IAAI,CAAC,OAAO,cAAc,IAAI,KAAK,OAAO,IAAI;GAC5C,MAAM,SAAS,KAAK,OAAO;GAC3B,MAAM,IAAI,MAAM,uEAAuE;EACzF;EACA,IAAI,WAAW,UAAU,MACvB,WAAW,MAAM,SAAS,WAAW,SAAS,IAAI,GAAG;GACnD,WAAW,OAAO,KAAK;GACvB,IAAI,WAAW,WAAW,OAAO,GAAG;EACtC;OAEA,MAAM,SAAS,KAAK,OAAO;EAE7B,IAAI,WAAW,WAAW,OAAO,GAC/B,MAAM,IAAI,MAAM,iEAAiE;EAEnF,MAAM,QAAQ,OAAO,YAAY,IAAI,MAAM,WAAW,WAAW,SAAS,CAAC;CAC7E;AACF"}
@@ -0,0 +1,8 @@
1
+ import { WorkNotification, WorkNotifications, workNotificationSchema } from "./store/work-notifications.mjs";
2
+ import { CodingExecutionRequest, ExecutionArtifact, ExecutionLaunchKey, ExecutionResult, TaskAttemptRef, codingExecutionRequestSchema, executionArtifactSchema, executionLaunchKeySchema, executionResultSchema, taskAttemptRef, taskAttemptRefFromTask, taskAttemptRefSchema } from "./schema/execution.mjs";
3
+ import { RecordTaskExecutionInput, RecordTaskUsageInput, StepUsage, TaskExecutionFence } from "./store/engine.mjs";
4
+ import { BudgetExhaustedError, DEFAULT_MAX_LAUNCH_ATTEMPTS, DispatchBudget, DispatchOptions, DispatchRefusalCode, DispatchRefusedError, DispatchStores, DispatchTaskInput, ExecutionLaunchPendingError, dispatchTask } from "./dispatch.mjs";
5
+ import { StallSweepOptions, TaskStallSweepResult, TaskStallSweepStores, stallWindowMinutes, sweepTaskStalls } from "./stall.mjs";
6
+ import { CancelExecutionOptions, CancelExecutionStores, ExecutionAdapter, ExecutionFenceError, ExecutionInspectionResult, InspectExecutionOptions, InspectExecutionStores, LaunchExecutionOptions, LaunchExecutionStores, RecordExecutionUsageOptions, RecordExecutionUsageStores, StartExecutionInput, cancelExecution, executionLaunchKey, inspectExecution, launchExecution, recordExecutionUsage } from "./execution.mjs";
7
+ import { SweepFailureReasonCode, SweepQueuedOptions, SweepQueuedResult, SweepQueuedStores, SweepSkipReasonCode, TaskLauncher, sweepQueued } from "./sweep.mjs";
8
+ export { BudgetExhaustedError, type CancelExecutionOptions, type CancelExecutionStores, type CodingExecutionRequest, DEFAULT_MAX_LAUNCH_ATTEMPTS, type DispatchBudget, type DispatchOptions, type DispatchRefusalCode, DispatchRefusedError, type DispatchStores, type DispatchTaskInput, type ExecutionAdapter, type ExecutionArtifact, ExecutionFenceError, type ExecutionInspectionResult, type ExecutionLaunchKey, ExecutionLaunchPendingError, type ExecutionResult, type InspectExecutionOptions, type InspectExecutionStores, type LaunchExecutionOptions, type LaunchExecutionStores, type RecordExecutionUsageOptions, type RecordExecutionUsageStores, type RecordTaskExecutionInput, type RecordTaskUsageInput, type StallSweepOptions, type StartExecutionInput, type StepUsage, type SweepFailureReasonCode, type SweepQueuedOptions, type SweepQueuedResult, type SweepQueuedStores, type SweepSkipReasonCode, type TaskAttemptRef, type TaskExecutionFence, type TaskLauncher, type TaskStallSweepResult, type TaskStallSweepStores, type WorkNotification, type WorkNotifications, cancelExecution, codingExecutionRequestSchema, dispatchTask, executionArtifactSchema, executionLaunchKey, executionLaunchKeySchema, executionResultSchema, inspectExecution, launchExecution, recordExecutionUsage, stallWindowMinutes, sweepQueued, sweepTaskStalls, taskAttemptRef, taskAttemptRefFromTask, taskAttemptRefSchema, workNotificationSchema };