@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 @@
1
+ {"version":3,"file":"execution.mjs","names":[],"sources":["../../src/sandbox/execution.ts"],"sourcesContent":["import { ExecutionLaunchPendingError } from \"../dispatch\";\nimport {\n codingExecutionRequestSchema,\n executionResultSchema,\n type CodingExecutionRequest,\n type ExecutionLaunchKey,\n type ExecutionResult,\n} from \"../schema/execution\";\nimport { type ExecutionAdapter } from \"../execution\";\nimport type { MillisecondClock } from \"../schema/common\";\nimport type { ExecutionReference } from \"../schema/task\";\nimport type { BlobClient } from \"../blob\";\nimport { ExecutionTimeoutError, withExecutionAbort } from \"./execution-abort\";\nimport type { ExecutionEnvironment } from \"./execution-environment\";\nimport {\n createExecutionRunLedger,\n type RunRecord,\n type ExecutionOutcome,\n} from \"./execution-run-ledger\";\nimport type {\n ConfiguredHarnessRunner,\n HarnessTurn,\n HarnessTurnUsage,\n SandboxHandle,\n} from \"./harness-runner\";\n\nconst defaultSandboxTimeoutMarginMs = 300_000;\n\n/** Context used to construct the immutable prompt for an admitted sandbox execution. */\nexport interface SandboxExecutionPromptContext {\n request: CodingExecutionRequest;\n reportSchema: unknown;\n sandbox: SandboxHandle;\n}\n\n/** Context used to validate and extract artifacts after a sandbox turn completes. */\nexport interface SandboxExecutionOutcomeContext {\n request: CodingExecutionRequest;\n sandbox: SandboxHandle;\n}\n\n/** Configures durable state, harnesses, environments, prompts, evidence, and usage pricing. */\nexport interface SandboxExecutionOptions {\n state: BlobClient;\n harnesses: Partial<Record<CodingExecutionRequest[\"harness\"], ConfiguredHarnessRunner>>;\n environment: ExecutionEnvironment;\n buildPrompt(context: SandboxExecutionPromptContext): string;\n extractOutcome(context: SandboxExecutionOutcomeContext): Promise<ExecutionOutcome>;\n calculateCostUsd?(model: string, turns: readonly HarnessTurnUsage[]): number | undefined;\n sandboxTimeoutMarginMs?: number;\n now?: MillisecondClock;\n}\n\n/** Coding request, stable launch key, and optional report contract for sandbox admission. */\nexport interface StartSandboxExecutionInput {\n request: CodingExecutionRequest;\n launchKey: ExecutionLaunchKey;\n context?: SandboxExecutionStartContext;\n}\n\n/** Optional report contract associated with one sandbox execution launch. */\nexport interface SandboxExecutionStartContext {\n reportSchema: unknown;\n}\n\n/** Execution adapter with explicit serial driving and pending-run discovery for sandbox work. */\nexport interface SandboxExecutionAdapter extends ExecutionAdapter {\n start(input: StartSandboxExecutionInput): Promise<ExecutionReference>;\n /** Serialize calls per execution; ledger CAS does not fence provider effects. */\n drive(execution: ExecutionReference): Promise<ExecutionResult>;\n /** Launch keys with admitted but unfinished runs, for drivers and drills. */\n pending(): Promise<readonly ExecutionReference[]>;\n}\n\nconst bounded = (reason: string) => reason.slice(0, 2000);\n\n/** Create a durable execution adapter that runs configured harnesses in Task-scoped sandboxes. */\nexport function createSandboxExecutionAdapter(\n options: SandboxExecutionOptions,\n): SandboxExecutionAdapter {\n const now = options.now ?? Date.now;\n const ledger = createExecutionRunLedger({\n state: options.state,\n now,\n ...(options.calculateCostUsd ? { calculateCostUsd: options.calculateCostUsd } : {}),\n });\n\n function configuredHarness(harness: CodingExecutionRequest[\"harness\"]) {\n const configured = options.harnesses[harness];\n if (!configured || !configured.model.trim()) {\n throw new Error(`Execution harness ${harness} has no configured runner and model`);\n }\n return configured;\n }\n\n const keyOf = (record: RunRecord) => ({\n taskId: record.request.taskId,\n attempt: record.request.attempt,\n });\n\n const sandboxTimeout = (request: CodingExecutionRequest) =>\n request.environment.timeoutMs +\n (options.sandboxTimeoutMarginMs ?? defaultSandboxTimeoutMarginMs);\n\n async function extract(sandbox: SandboxHandle, record: RunRecord): Promise<ExecutionOutcome> {\n const request = record.request;\n const failed = (reason: string): ExecutionOutcome => ({\n status: \"failed\",\n artifacts: [],\n reason: bounded(reason),\n });\n // Post-turn checks detect overruns; they cannot enforce a hard cap.\n const usage = ledger.usage(record);\n const { maxCostUsd, maxTokens } = request.limits;\n if (maxCostUsd !== undefined && usage.costUsd !== undefined && usage.costUsd > maxCostUsd) {\n return failed(\n `Execution spent $${usage.costUsd}, exceeding its maxCostUsd of $${maxCostUsd}`,\n );\n }\n if (\n maxTokens !== undefined &&\n (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0) > maxTokens\n ) {\n return failed(\n `Execution used ${(usage.inputTokens ?? 0) + (usage.outputTokens ?? 0)} tokens, exceeding its maxTokens of ${maxTokens}`,\n );\n }\n return options.extractOutcome({ sandbox, request });\n }\n\n /** Best-effort idempotent environment shutdown; ambiguity propagates for retry. */\n async function stopEnvironment(record: RunRecord): Promise<void> {\n const sandbox = await options.environment.find(keyOf(record));\n if (sandbox) await options.environment.stop(sandbox.sandbox);\n }\n\n return {\n async start({ request, launchKey, context }) {\n const parsed = codingExecutionRequestSchema.parse(request);\n const configured = configuredHarness(parsed.harness);\n const keyParts = { taskId: parsed.taskId, attempt: parsed.attempt };\n const stored = await ledger.admit({\n request: parsed,\n key: launchKey,\n model: configured.model,\n environmentId: options.environment.name(keyParts),\n reportSchema: context?.reportSchema,\n });\n if (stored.record.launched || stored.record.result) return stored.record.execution;\n try {\n await options.environment.ensure(keyParts, {\n timeoutMs: sandboxTimeout(parsed),\n request: parsed,\n });\n } catch (cause) {\n // Admission already exists; provisioning failure must recover with the same key.\n throw new ExecutionLaunchPendingError(\n \"Execution environment provisioning is unresolved; recover with the original key\",\n { cause },\n );\n }\n return stored.record.execution;\n },\n\n async inspect(execution) {\n const stored = await ledger.read(execution);\n if (!stored) return { status: \"expired\" };\n if (stored.record.result) return { status: \"finished\", result: stored.record.result };\n const sandbox = await options.environment.find(keyOf(stored.record));\n if (!sandbox || sandbox.liveness === \"terminal\") {\n return { status: \"expired\" };\n }\n if (sandbox.liveness !== \"live\")\n throw new Error(\"Execution environment is transitioning; inspect again shortly\");\n return { status: \"active\" };\n },\n\n async stop(execution) {\n const stored = await ledger.read(execution);\n if (!stored) {\n return executionResultSchema.parse({\n status: \"cancelled\",\n execution,\n artifacts: [],\n usage: { computeMs: 0 },\n reason: \"No admitted execution matches this reference; its cost is unknown\",\n });\n }\n const { record } = stored;\n if (record.result) {\n // A final result does not imply the sandbox has stopped.\n await stopEnvironment(record);\n return record.result;\n }\n await stopEnvironment(record);\n return ledger.finalize(stored, {\n status: \"cancelled\",\n artifacts: [],\n reason: record.launched\n ? record.turns.length > 0\n ? \"Execution was stopped after its completed turn was recorded\"\n : \"Execution was stopped after launch; unfinished turn cost is unknown\"\n : \"Execution was stopped before its prompt was sent\",\n });\n },\n\n async drive(execution) {\n const admitted = await ledger.read(execution);\n if (!admitted) {\n throw new Error(\"No admitted execution matches this reference\");\n }\n let stored = admitted;\n if (stored.record.result) return stored.record.result;\n const request = stored.record.request;\n const configured = configuredHarness(request.harness);\n if (configured.model !== stored.record.model) {\n throw new Error(\"Execution model changed; restore its admitted harness configuration\");\n }\n // A launched attempt must never recreate its environment.\n let sandbox: SandboxHandle;\n if (!stored.record.launched) {\n const observed = await options.environment.ensure(keyOf(stored.record), {\n timeoutMs: sandboxTimeout(request),\n request,\n });\n if (observed.liveness !== \"live\") throw new Error(\"Execution environment is not live\");\n sandbox = observed.sandbox;\n } else {\n const found = await options.environment.find(keyOf(stored.record));\n if (!found || found.liveness === \"terminal\") {\n return ledger.finalize(stored, {\n status: \"failed\",\n artifacts: [],\n reason:\n \"Execution environment expired before a result was extracted; replacement requires a new attempt\",\n });\n }\n if (found.liveness !== \"live\") {\n throw new Error(\"Execution environment is transitioning; drive again shortly\");\n }\n sandbox = found.sandbox;\n }\n const remainingMs = Math.max(\n 0,\n request.environment.timeoutMs - (now() - (stored.record.startedAtMs ?? now())),\n );\n try {\n return await withExecutionAbort({\n timeoutMs: remainingMs,\n isStopped: async () => {\n const latest = await ledger.read(execution);\n if (!latest) throw new Error(\"The admitted execution disappeared\");\n return latest.record.result !== undefined;\n },\n run: async (abortSignal) => {\n if (remainingMs === 0) throw new ExecutionTimeoutError();\n let observedFlip = false;\n if (!stored.record.launched) {\n // Confirm launch intent durably before sending any prompt.\n const session = await configured.runner.open({\n sandbox,\n sessionId: stored.record.harnessSessionId,\n abortSignal,\n });\n stored = await ledger.markLaunched(stored, await session.detach());\n if (stored.record.result) return stored.record.result;\n observedFlip = true;\n }\n let turn: HarnessTurn | undefined;\n let promptedHere = false;\n if (stored.record.promptedAtMs === undefined && stored.record.turns.length === 0) {\n const session = await configured.runner.open({\n sandbox,\n sessionId: stored.record.harnessSessionId,\n resumeFrom: stored.record.resumeState,\n abortSignal,\n });\n const prompt = options.buildPrompt({\n request,\n reportSchema: stored.record.reportSchema,\n sandbox,\n });\n // An unmarked prompt from another driver may have spent money already.\n const foreignFlip = !observedFlip;\n try {\n const inflight = await session.beginPrompt(prompt);\n stored = await ledger.markPrompted({\n base: stored,\n resumeState: inflight,\n origin: foreignFlip ? \"recovered\" : \"this-driver\",\n });\n promptedHere = true;\n } catch (error) {\n if (!(error instanceof Error && /unfinished turn/iu.test(error.message)))\n throw error;\n // Drain the existing turn; its earlier usage was not observed.\n turn = await session.continueTurn();\n stored = await ledger.recordTurn({\n base: stored,\n turn: turn.usage,\n resumeState: await session.detach(),\n origin: \"recovered\",\n });\n }\n if (stored.record.result) return stored.record.result;\n }\n if (turn === undefined && stored.record.turns.length === 0) {\n const session = await configured.runner.open({\n sandbox,\n sessionId: stored.record.harnessSessionId,\n resumeFrom: stored.record.resumeState,\n abortSignal,\n });\n turn = await session.continueTurn();\n stored = await ledger.recordTurn({\n base: stored,\n turn: turn.usage,\n resumeState: await session.detach(),\n origin: promptedHere ? \"this-driver\" : \"recovered\",\n });\n if (stored.record.result) return stored.record.result;\n }\n const result = await extract(sandbox, stored.record);\n abortSignal.throwIfAborted();\n return ledger.finalize(stored, result);\n },\n });\n } catch (error) {\n const latest = await ledger.read(execution);\n if (latest?.record.result) return latest.record.result;\n if (!(error instanceof ExecutionTimeoutError) || !latest) throw error;\n await stopEnvironment(latest.record);\n return ledger.finalize(latest, {\n status: \"failed\",\n artifacts: [],\n reason: error.message,\n });\n }\n },\n\n pending: ledger.pending,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ import { SandboxWorkspaceHandle } from "./workspace.mjs";
2
+ import { HarnessAgentAdapter } from "@ai-sdk/harness/agent";
3
+ //#region src/sandbox/harness-runner.d.ts
4
+ /** Normalized per-turn token accounting, including whether the observation is complete. */
5
+ interface HarnessTurnUsage {
6
+ inputTokens: number;
7
+ noCacheInputTokens: number;
8
+ cacheReadTokens: number;
9
+ cacheWriteTokens: number;
10
+ outputTokens: number;
11
+ /** False when the SDK omitted token details or suspension lost usage. */
12
+ complete?: boolean;
13
+ }
14
+ /** Bounded harness response text paired with its normalized usage observation. */
15
+ interface HarnessTurn {
16
+ text: string;
17
+ usage: HarnessTurnUsage;
18
+ }
19
+ /** One recoverable harness session opened against a supplied sandbox. */
20
+ interface HarnessSession {
21
+ hasUnfinishedTurn(): boolean;
22
+ /** Do not reuse this handle; persist the returned state before reopening. */
23
+ beginPrompt(text: string): Promise<unknown>;
24
+ /** Drain the current turn — still running or already finished — to completion. */
25
+ continueTurn(): Promise<HarnessTurn>;
26
+ /** Persist cross-process resume state; the session handle is done afterwards. */
27
+ detach(): Promise<unknown>;
28
+ }
29
+ /** Minimal sandbox command and working-directory boundary required by harness runners. */
30
+ interface SandboxHandle extends SandboxWorkspaceHandle {
31
+ runCommand(params: SandboxRunCommandInput): Promise<SandboxRunCommandResult>;
32
+ }
33
+ /** Executable, arguments, and optional execution bounds for a sandbox command. */
34
+ interface SandboxRunCommandInput {
35
+ cmd: string;
36
+ args?: readonly string[];
37
+ cwd?: string;
38
+ timeoutMs?: number;
39
+ }
40
+ /** Exit status and lazy output streams returned by a sandbox command. */
41
+ interface SandboxRunCommandResult {
42
+ exitCode: number | null;
43
+ stdout(): Promise<string>;
44
+ stderr(): Promise<string>;
45
+ }
46
+ /** Sandbox, session identity, and optional continuation used to open a harness session. */
47
+ interface OpenHarnessSessionOptions {
48
+ sandbox: SandboxHandle;
49
+ sessionId: string;
50
+ resumeFrom?: unknown;
51
+ abortSignal?: AbortSignal;
52
+ }
53
+ /** Opens recoverable, serial harness sessions against a supplied sandbox. */
54
+ interface HarnessRunner {
55
+ open(options: OpenHarnessSessionOptions): Promise<HarnessSession>;
56
+ }
57
+ /** Harness adapter, model, workspace, and continuation policy used by a harness runner. */
58
+ interface HarnessAgentRunnerOptions {
59
+ harness: HarnessAgentAdapter;
60
+ model: string;
61
+ /** Directory used by the harness SDK inside the sandbox. */
62
+ workDir?: string;
63
+ /** Pi resolves a provider-qualified ID; persisted pricing uses the gateway ID. */
64
+ providerModel?: string;
65
+ /** Pi suspends its host model loop by aborting and replaying its journal. */
66
+ suspensionLosesUsage?: boolean;
67
+ /** A changed or unavailable runtime identity makes continuation usage incomplete. */
68
+ continuationIdentity?(state: unknown): string | undefined;
69
+ }
70
+ /** Model and configured runner selected for one execution harness. */
71
+ interface ConfiguredHarnessRunner {
72
+ model: string;
73
+ runner: HarnessRunner;
74
+ }
75
+ /** Adapt an AI SDK harness agent into Factory's durable open/continue/detach session contract. */
76
+ declare function createHarnessAgentRunner(options: HarnessAgentRunnerOptions): HarnessRunner;
77
+ //#endregion
78
+ export { ConfiguredHarnessRunner, HarnessAgentRunnerOptions, HarnessRunner, HarnessSession, HarnessTurn, HarnessTurnUsage, OpenHarnessSessionOptions, SandboxHandle, SandboxRunCommandInput, SandboxRunCommandResult, createHarnessAgentRunner };
79
+ //# sourceMappingURL=harness-runner.d.mts.map
@@ -0,0 +1,162 @@
1
+ import { jsonValueSchema } from "../schema/work.mjs";
2
+ import "./workspace.mjs";
3
+ import { z } from "zod";
4
+ import { HarnessAgent } from "@ai-sdk/harness/agent";
5
+ import { createVercelSandbox } from "@ai-sdk/sandbox-vercel";
6
+ //#region src/sandbox/harness-runner.ts
7
+ const count = z.number().int().nonnegative();
8
+ const turnSchema = z.object({
9
+ text: z.string(),
10
+ usage: z.object({
11
+ inputTokens: count,
12
+ noCacheInputTokens: count,
13
+ cacheReadTokens: count,
14
+ cacheWriteTokens: count,
15
+ outputTokens: count,
16
+ complete: z.boolean()
17
+ })
18
+ });
19
+ const resumeSchema = z.strictObject({
20
+ harness: z.string(),
21
+ model: z.string(),
22
+ session: jsonValueSchema,
23
+ usageIncomplete: z.boolean(),
24
+ completedTurn: turnSchema.optional()
25
+ });
26
+ const usageSchema = z.object({
27
+ inputTokens: count.optional(),
28
+ outputTokens: count.optional(),
29
+ inputTokenDetails: z.object({
30
+ noCacheTokens: count.optional(),
31
+ cacheReadTokens: count.optional(),
32
+ cacheWriteTokens: count.optional()
33
+ }).optional()
34
+ });
35
+ function observedTurn(result, usageIncomplete) {
36
+ const usage = usageSchema.parse(result.totalUsage ?? {});
37
+ const details = usage.inputTokenDetails;
38
+ return {
39
+ text: result.text.slice(0, 2e3),
40
+ usage: {
41
+ inputTokens: usage.inputTokens ?? 0,
42
+ noCacheInputTokens: details?.noCacheTokens ?? 0,
43
+ cacheReadTokens: details?.cacheReadTokens ?? 0,
44
+ cacheWriteTokens: details?.cacheWriteTokens ?? 0,
45
+ outputTokens: usage.outputTokens ?? 0,
46
+ complete: !usageIncomplete && usage.inputTokens !== void 0 && usage.outputTokens !== void 0 && details?.noCacheTokens !== void 0 && details.cacheReadTokens !== void 0 && details.cacheWriteTokens !== void 0 && details.noCacheTokens + details.cacheReadTokens + details.cacheWriteTokens === usage.inputTokens
47
+ }
48
+ };
49
+ }
50
+ /** Adapt an AI SDK harness agent into Factory's durable open/continue/detach session contract. */
51
+ function createHarnessAgentRunner(options) {
52
+ return { async open({ sandbox, sessionId, resumeFrom, abortSignal }) {
53
+ abortSignal?.throwIfAborted();
54
+ const abortOptions = abortSignal ? { abortSignal } : {};
55
+ const saved = resumeFrom === void 0 ? void 0 : resumeSchema.parse(resumeFrom);
56
+ if (saved && (saved.harness !== options.harness.harnessId || saved.model !== options.model)) throw new Error("Harness continuation belongs to a different harness or model");
57
+ if (saved?.completedTurn) {
58
+ const turn = saved.completedTurn;
59
+ return {
60
+ hasUnfinishedTurn: () => false,
61
+ beginPrompt: async () => {
62
+ throw new Error("A completed turn cannot be prompted again");
63
+ },
64
+ continueTurn: async () => {
65
+ abortSignal?.throwIfAborted();
66
+ return turn;
67
+ },
68
+ detach: async () => saved
69
+ };
70
+ }
71
+ const provider = createVercelSandbox({ sandbox });
72
+ let finished = false;
73
+ const observe = (emit) => (event) => {
74
+ if (event.type === "finish") finished = true;
75
+ emit(event);
76
+ };
77
+ const harness = {
78
+ ...options.harness,
79
+ async doStart(input) {
80
+ const runtime = await options.harness.doStart(input);
81
+ return {
82
+ ...runtime,
83
+ doPromptTurn: (turn) => runtime.doPromptTurn({
84
+ ...turn,
85
+ emit: observe(turn.emit)
86
+ }),
87
+ doContinueTurn: (turn) => runtime.doContinueTurn({
88
+ ...turn,
89
+ emit: observe(turn.emit)
90
+ })
91
+ };
92
+ }
93
+ };
94
+ const agent = new HarnessAgent({
95
+ id: `factory-${options.harness.harnessId}`,
96
+ harness,
97
+ model: options.providerModel ?? options.model,
98
+ sandbox: provider,
99
+ sandboxConfig: { workDir: options.workDir ?? "workspace" }
100
+ });
101
+ const session = await agent.createSession({
102
+ sessionId,
103
+ ...abortOptions,
104
+ ...saved ? { resumeFrom: saved.session } : {}
105
+ });
106
+ let usageIncomplete = saved?.usageIncomplete ?? false;
107
+ let detached;
108
+ async function abortable(run) {
109
+ try {
110
+ return await run();
111
+ } finally {
112
+ if (abortSignal?.aborted) await session.destroy();
113
+ }
114
+ }
115
+ const snapshot = (state, completedTurn) => resumeSchema.parse({
116
+ harness: options.harness.harnessId,
117
+ model: options.model,
118
+ session: JSON.parse(JSON.stringify(state)),
119
+ usageIncomplete,
120
+ ...completedTurn ? { completedTurn } : {}
121
+ });
122
+ return {
123
+ hasUnfinishedTurn: () => session.hasUnfinishedTurn(),
124
+ beginPrompt: (text) => abortable(async () => {
125
+ const stream = await agent.stream({
126
+ session,
127
+ prompt: text,
128
+ ...abortOptions
129
+ });
130
+ const state = await session.detach();
131
+ if (state.continueFrom && !finished) {
132
+ usageIncomplete ||= options.suspensionLosesUsage === true;
133
+ return snapshot(state);
134
+ }
135
+ return snapshot(state, observedTurn({
136
+ text: await stream.text,
137
+ totalUsage: await stream.totalUsage
138
+ }, usageIncomplete));
139
+ }),
140
+ continueTurn: () => abortable(async () => {
141
+ const result = await agent.continueGenerate({
142
+ session,
143
+ ...abortOptions
144
+ });
145
+ const state = await session.detach();
146
+ if (saved && options.continuationIdentity) {
147
+ const before = options.continuationIdentity(saved.session);
148
+ const after = options.continuationIdentity(state);
149
+ usageIncomplete ||= before === void 0 || after === void 0 || before !== after;
150
+ }
151
+ const turn = observedTurn(result, usageIncomplete);
152
+ detached = snapshot(state, turn);
153
+ return turn;
154
+ }),
155
+ detach: async () => detached ?? snapshot(await session.detach())
156
+ };
157
+ } };
158
+ }
159
+ //#endregion
160
+ export { createHarnessAgentRunner };
161
+
162
+ //# sourceMappingURL=harness-runner.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-runner.mjs","names":[],"sources":["../../src/sandbox/harness-runner.ts"],"sourcesContent":["import {\n HarnessAgent,\n type HarnessAgentAdapter,\n type HarnessAgentResumeSessionState,\n} from \"@ai-sdk/harness/agent\";\nimport { createVercelSandbox } from \"@ai-sdk/sandbox-vercel\";\nimport type { HarnessV1StreamPart } from \"@ai-sdk/harness\";\nimport { jsonValueSchema } from \"../schema/work\";\nimport { z } from \"zod\";\nimport { defaultHarnessWorkDir, type SandboxWorkspaceHandle } from \"./workspace\";\n\n/** Normalized per-turn token accounting, including whether the observation is complete. */\nexport interface HarnessTurnUsage {\n inputTokens: number;\n noCacheInputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n outputTokens: number;\n /** False when the SDK omitted token details or suspension lost usage. */\n complete?: boolean;\n}\n\n/** Bounded harness response text paired with its normalized usage observation. */\nexport interface HarnessTurn {\n text: string;\n usage: HarnessTurnUsage;\n}\n\n/** One recoverable harness session opened against a supplied sandbox. */\nexport interface HarnessSession {\n hasUnfinishedTurn(): boolean;\n /** Do not reuse this handle; persist the returned state before reopening. */\n beginPrompt(text: string): Promise<unknown>;\n /** Drain the current turn — still running or already finished — to completion. */\n continueTurn(): Promise<HarnessTurn>;\n /** Persist cross-process resume state; the session handle is done afterwards. */\n detach(): Promise<unknown>;\n}\n\n/** Minimal sandbox command and working-directory boundary required by harness runners. */\nexport interface SandboxHandle extends SandboxWorkspaceHandle {\n runCommand(params: SandboxRunCommandInput): Promise<SandboxRunCommandResult>;\n}\n\n/** Executable, arguments, and optional execution bounds for a sandbox command. */\nexport interface SandboxRunCommandInput {\n cmd: string;\n args?: readonly string[];\n cwd?: string;\n timeoutMs?: number;\n}\n\n/** Exit status and lazy output streams returned by a sandbox command. */\nexport interface SandboxRunCommandResult {\n exitCode: number | null;\n stdout(): Promise<string>;\n stderr(): Promise<string>;\n}\n\n/** Sandbox, session identity, and optional continuation used to open a harness session. */\nexport interface OpenHarnessSessionOptions {\n sandbox: SandboxHandle;\n sessionId: string;\n resumeFrom?: unknown;\n abortSignal?: AbortSignal;\n}\n\n/** Opens recoverable, serial harness sessions against a supplied sandbox. */\nexport interface HarnessRunner {\n open(options: OpenHarnessSessionOptions): Promise<HarnessSession>;\n}\n\n/** Harness adapter, model, workspace, and continuation policy used by a harness runner. */\nexport interface HarnessAgentRunnerOptions {\n harness: HarnessAgentAdapter;\n model: string;\n /** Directory used by the harness SDK inside the sandbox. */\n workDir?: string;\n /** Pi resolves a provider-qualified ID; persisted pricing uses the gateway ID. */\n providerModel?: string;\n /** Pi suspends its host model loop by aborting and replaying its journal. */\n suspensionLosesUsage?: boolean;\n /** A changed or unavailable runtime identity makes continuation usage incomplete. */\n continuationIdentity?(state: unknown): string | undefined;\n}\n\n/** Model and configured runner selected for one execution harness. */\nexport interface ConfiguredHarnessRunner {\n model: string;\n runner: HarnessRunner;\n}\n\nconst count = z.number().int().nonnegative();\nconst turnSchema = z.object({\n text: z.string(),\n usage: z.object({\n inputTokens: count,\n noCacheInputTokens: count,\n cacheReadTokens: count,\n cacheWriteTokens: count,\n outputTokens: count,\n complete: z.boolean(),\n }),\n});\nconst resumeSchema = z.strictObject({\n harness: z.string(),\n model: z.string(),\n session: jsonValueSchema,\n usageIncomplete: z.boolean(),\n completedTurn: turnSchema.optional(),\n});\nconst usageSchema = z.object({\n inputTokens: count.optional(),\n outputTokens: count.optional(),\n inputTokenDetails: z\n .object({\n noCacheTokens: count.optional(),\n cacheReadTokens: count.optional(),\n cacheWriteTokens: count.optional(),\n })\n .optional(),\n});\n\nfunction observedTurn(\n result: { text: string; totalUsage: unknown },\n usageIncomplete: boolean,\n): HarnessTurn & z.infer<typeof turnSchema> {\n const usage = usageSchema.parse(result.totalUsage ?? {});\n const details = usage.inputTokenDetails;\n return {\n text: result.text.slice(0, 2000),\n usage: {\n inputTokens: usage.inputTokens ?? 0,\n noCacheInputTokens: details?.noCacheTokens ?? 0,\n cacheReadTokens: details?.cacheReadTokens ?? 0,\n cacheWriteTokens: details?.cacheWriteTokens ?? 0,\n outputTokens: usage.outputTokens ?? 0,\n complete:\n !usageIncomplete &&\n usage.inputTokens !== undefined &&\n usage.outputTokens !== undefined &&\n details?.noCacheTokens !== undefined &&\n details.cacheReadTokens !== undefined &&\n details.cacheWriteTokens !== undefined &&\n details.noCacheTokens + details.cacheReadTokens + details.cacheWriteTokens ===\n usage.inputTokens,\n },\n };\n}\n\n/** Adapt an AI SDK harness agent into Factory's durable open/continue/detach session contract. */\nexport function createHarnessAgentRunner(options: HarnessAgentRunnerOptions): HarnessRunner {\n return {\n async open({ sandbox, sessionId, resumeFrom, abortSignal }) {\n abortSignal?.throwIfAborted();\n const abortOptions = abortSignal ? { abortSignal } : {};\n const saved = resumeFrom === undefined ? undefined : resumeSchema.parse(resumeFrom);\n if (saved && (saved.harness !== options.harness.harnessId || saved.model !== options.model)) {\n throw new Error(\"Harness continuation belongs to a different harness or model\");\n }\n if (saved?.completedTurn) {\n const turn = saved.completedTurn;\n return {\n hasUnfinishedTurn: () => false,\n beginPrompt: async () => {\n throw new Error(\"A completed turn cannot be prompted again\");\n },\n continueTurn: async () => {\n abortSignal?.throwIfAborted();\n return turn;\n },\n detach: async () => saved,\n };\n }\n // sandbox-vercel types target Sandbox 3.x; this caller-owned 2.x instance has the same operations.\n const provider = createVercelSandbox({ sandbox } as unknown as Parameters<\n typeof createVercelSandbox\n >[0]);\n let finished = false;\n const observe =\n (emit: (event: HarnessV1StreamPart) => void) => (event: HarnessV1StreamPart) => {\n if (event.type === \"finish\") finished = true;\n emit(event);\n };\n const harness: HarnessAgentAdapter = {\n ...options.harness,\n async doStart(input) {\n const runtime = await options.harness.doStart(input);\n return {\n ...runtime,\n doPromptTurn: (turn) => runtime.doPromptTurn({ ...turn, emit: observe(turn.emit) }),\n doContinueTurn: (turn) => runtime.doContinueTurn({ ...turn, emit: observe(turn.emit) }),\n };\n },\n };\n const agent = new HarnessAgent({\n id: `factory-${options.harness.harnessId}`,\n harness,\n model: options.providerModel ?? options.model,\n sandbox: provider,\n sandboxConfig: { workDir: options.workDir ?? defaultHarnessWorkDir },\n });\n const session = await agent.createSession({\n sessionId,\n ...abortOptions,\n // HarnessAgent validates the provider-specific lifecycle payload.\n ...(saved\n ? { resumeFrom: saved.session as unknown as HarnessAgentResumeSessionState }\n : {}),\n });\n let usageIncomplete = saved?.usageIncomplete ?? false;\n let detached: z.infer<typeof resumeSchema> | undefined;\n async function abortable<T>(run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } finally {\n // Pi may emit an error before its host loop stops; wait for cleanup.\n if (abortSignal?.aborted) await session.destroy();\n }\n }\n const snapshot = (\n state: HarnessAgentResumeSessionState,\n completedTurn?: z.infer<typeof turnSchema>,\n ) =>\n resumeSchema.parse({\n harness: options.harness.harnessId,\n model: options.model,\n session: JSON.parse(JSON.stringify(state)) as unknown,\n usageIncomplete,\n ...(completedTurn ? { completedTurn } : {}),\n });\n return {\n hasUnfinishedTurn: () => session.hasUnfinishedTurn(),\n beginPrompt: (text) =>\n abortable(async () => {\n // hasUnfinishedTurn can reflect local intent; stream confirms runtime acceptance.\n const stream = await agent.stream({ session, prompt: text, ...abortOptions });\n const state = await session.detach();\n if (state.continueFrom && !finished) {\n usageIncomplete ||= options.suspensionLosesUsage === true;\n return snapshot(state);\n }\n // A fast turn can finish before detach; retain its result for continuation.\n return snapshot(\n state,\n observedTurn(\n {\n text: await stream.text,\n totalUsage: await stream.totalUsage,\n },\n usageIncomplete,\n ),\n );\n }),\n continueTurn: () =>\n abortable(async () => {\n const result = await agent.continueGenerate({ session, ...abortOptions });\n const state = await session.detach();\n if (saved && options.continuationIdentity) {\n const before = options.continuationIdentity(saved.session);\n const after = options.continuationIdentity(state);\n usageIncomplete ||= before === undefined || after === undefined || before !== after;\n }\n const turn = observedTurn(result, usageIncomplete);\n detached = snapshot(state, turn);\n return turn;\n }),\n detach: async () => detached ?? snapshot(await session.detach()),\n };\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { CommandSandbox, CommandSandboxRunInput, CommandSandboxRunResult } from "./command.mjs";
2
+ import { HarnessWorkspace, SandboxOutputPath, SandboxSession, SandboxWorkspaceHandle, defaultHarnessWorkDir, harnessWorkspace, parseSandboxOutputPath } from "./workspace.mjs";
3
+ import { ConfiguredHarnessRunner, HarnessAgentRunnerOptions, HarnessRunner, HarnessSession, HarnessTurn, HarnessTurnUsage, OpenHarnessSessionOptions, SandboxHandle, SandboxRunCommandInput, SandboxRunCommandResult, createHarnessAgentRunner } from "./harness-runner.mjs";
4
+ import { EnsureExecutionEnvironmentOptions, EnvironmentLiveness, ExecutionEnvironment, ExecutionEnvironmentObservation } from "./execution-environment.mjs";
5
+ import { AdmitExecutionRunInput, ExecutionOutcome, ExecutionRunLedger, ExecutionRunLedgerOptions, MarkExecutionRunPromptedInput, RecordExecutionRunTurnInput, RunRecord, RunSnapshot, createExecutionRunLedger } from "./execution-run-ledger.mjs";
6
+ import { SandboxExecutionAdapter, SandboxExecutionOptions, SandboxExecutionOutcomeContext, SandboxExecutionPromptContext, SandboxExecutionStartContext, StartSandboxExecutionInput, createSandboxExecutionAdapter } from "./execution.mjs";
7
+ import { ExecutionAbortOptions, ExecutionTimeoutError, withExecutionAbort } from "./execution-abort.mjs";
8
+ import { EnsureTaskSandboxOptions, FindTaskSandboxOptions, SandboxApi, TaskSandboxEnvironmentOptions, TaskSandboxScope, createTaskSandboxEnvironment, ensureTaskSandbox, findTaskSandbox, stopTaskSandbox, taskSandboxName, taskSandboxTags } from "./task-environment.mjs";
9
+ export { type AdmitExecutionRunInput, type CommandSandbox, type CommandSandboxRunInput, type CommandSandboxRunResult, type ConfiguredHarnessRunner, type EnsureExecutionEnvironmentOptions, type EnsureTaskSandboxOptions, type EnvironmentLiveness, type ExecutionAbortOptions, type ExecutionEnvironment, type ExecutionEnvironmentObservation, type ExecutionOutcome, type ExecutionRunLedger, type ExecutionRunLedgerOptions, ExecutionTimeoutError, type FindTaskSandboxOptions, type HarnessAgentRunnerOptions, type HarnessRunner, type HarnessSession, type HarnessTurn, type HarnessTurnUsage, type HarnessWorkspace, type MarkExecutionRunPromptedInput, type OpenHarnessSessionOptions, type RecordExecutionRunTurnInput, type RunRecord, type RunSnapshot, type SandboxApi, type SandboxExecutionAdapter, type SandboxExecutionOptions, type SandboxExecutionOutcomeContext, type SandboxExecutionPromptContext, type SandboxExecutionStartContext, type SandboxHandle, type SandboxOutputPath, type SandboxRunCommandInput, type SandboxRunCommandResult, type SandboxSession, type SandboxWorkspaceHandle, type StartSandboxExecutionInput, type TaskSandboxEnvironmentOptions, type TaskSandboxScope, createExecutionRunLedger, createHarnessAgentRunner, createSandboxExecutionAdapter, createTaskSandboxEnvironment, defaultHarnessWorkDir, ensureTaskSandbox, findTaskSandbox, harnessWorkspace, parseSandboxOutputPath, stopTaskSandbox, taskSandboxName, taskSandboxTags, withExecutionAbort };
@@ -0,0 +1,7 @@
1
+ import { ExecutionTimeoutError, withExecutionAbort } from "./execution-abort.mjs";
2
+ import { createExecutionRunLedger } from "./execution-run-ledger.mjs";
3
+ import { createSandboxExecutionAdapter } from "./execution.mjs";
4
+ import { defaultHarnessWorkDir, harnessWorkspace, parseSandboxOutputPath } from "./workspace.mjs";
5
+ import { createHarnessAgentRunner } from "./harness-runner.mjs";
6
+ import { createTaskSandboxEnvironment, ensureTaskSandbox, findTaskSandbox, stopTaskSandbox, taskSandboxName, taskSandboxTags } from "./task-environment.mjs";
7
+ export { ExecutionTimeoutError, createExecutionRunLedger, createHarnessAgentRunner, createSandboxExecutionAdapter, createTaskSandboxEnvironment, defaultHarnessWorkDir, ensureTaskSandbox, findTaskSandbox, harnessWorkspace, parseSandboxOutputPath, stopTaskSandbox, taskSandboxName, taskSandboxTags, withExecutionAbort };
@@ -0,0 +1,50 @@
1
+ import { CodingExecutionRequest, TaskAttemptRef } from "../schema/execution.mjs";
2
+ import { ExecutionEnvironment } from "./execution-environment.mjs";
3
+ import { Sandbox } from "@vercel/sandbox";
4
+ //#region src/sandbox/task-environment.d.ts
5
+ /** Isolates stores that reuse Task IDs within the project's shared sandbox namespace. */
6
+ interface TaskSandboxScope {
7
+ scope: string;
8
+ }
9
+ /** Injectable subset of the Vercel Sandbox API used for creation and exact identity discovery. */
10
+ type SandboxApi = Pick<typeof Sandbox, "getOrCreate" | "get" | "list">;
11
+ /** Derive a deterministic provider sandbox name from a scoped Task-attempt identity. */
12
+ declare function taskSandboxName(key: TaskAttemptRef, scope: string): string;
13
+ /** Build the complete tag set used to discover and re-verify a Task sandbox. */
14
+ declare function taskSandboxTags(key: TaskAttemptRef, scope: string): Record<string, string>;
15
+ /** Configures idempotent creation and workspace seeding for a Task sandbox. */
16
+ interface EnsureTaskSandboxOptions extends TaskSandboxScope {
17
+ /** Sandbox lifetime; callers add margin over the execution timeout. */
18
+ timeoutMs: number;
19
+ /** Seeds the workspace; must be idempotent because a crashed seed reruns. */
20
+ seed(sandbox: Sandbox): Promise<void>;
21
+ runtime?: string;
22
+ ports?: readonly number[];
23
+ seededMarker?: string;
24
+ api?: SandboxApi;
25
+ }
26
+ /** Create or recover the exact sandbox for a Task attempt and ensure seeding completed. */
27
+ declare function ensureTaskSandbox(key: TaskAttemptRef, options: EnsureTaskSandboxOptions): Promise<Sandbox>;
28
+ /** Scope and provider API used to discover an existing Task sandbox. */
29
+ interface FindTaskSandboxOptions extends TaskSandboxScope {
30
+ api?: SandboxApi;
31
+ }
32
+ /** Discover an existing Task sandbox without resuming or replacing it. */
33
+ declare function findTaskSandbox(key: TaskAttemptRef, options: FindTaskSandboxOptions): Promise<Sandbox | null>;
34
+ /** Stop a live Task sandbox idempotently while treating provider disappearance as success. */
35
+ declare function stopTaskSandbox(sandbox: Sandbox): Promise<void>;
36
+ /** Scoped creation, seeding, and provider dependencies for a Task sandbox environment. */
37
+ interface TaskSandboxEnvironmentOptions {
38
+ /** Deployment- or run-unique namespace; see {@link TaskSandboxScope}. */
39
+ scope: string;
40
+ seed(request: CodingExecutionRequest, sandbox: Sandbox): Promise<void>;
41
+ runtime?: EnsureTaskSandboxOptions["runtime"];
42
+ ports?: readonly number[];
43
+ seededMarker?: string;
44
+ api?: SandboxApi;
45
+ }
46
+ /** Adapt scoped Vercel Sandbox creation and discovery to the execution-environment contract. */
47
+ declare function createTaskSandboxEnvironment(options: TaskSandboxEnvironmentOptions): ExecutionEnvironment<Sandbox>;
48
+ //#endregion
49
+ export { EnsureTaskSandboxOptions, FindTaskSandboxOptions, SandboxApi, TaskSandboxEnvironmentOptions, TaskSandboxScope, createTaskSandboxEnvironment, ensureTaskSandbox, findTaskSandbox, stopTaskSandbox, taskSandboxName, taskSandboxTags };
50
+ //# sourceMappingURL=task-environment.d.mts.map
@@ -0,0 +1,140 @@
1
+ import { createHash } from "node:crypto";
2
+ import { Sandbox } from "@vercel/sandbox";
3
+ //#region src/sandbox/task-environment.ts
4
+ const livenessByStatus = {
5
+ pending: "transitioning",
6
+ running: "live",
7
+ stopping: "terminal",
8
+ stopped: "terminal",
9
+ failed: "terminal",
10
+ aborted: "terminal",
11
+ snapshotting: "terminal"
12
+ };
13
+ function observe(sandbox) {
14
+ const liveness = livenessByStatus[sandbox.status];
15
+ if (liveness === void 0) throw new Error("Unsupported sandbox liveness state");
16
+ return {
17
+ sandbox,
18
+ liveness
19
+ };
20
+ }
21
+ const discoveryTagKey = "factoryTask";
22
+ const defaultSeededMarker = "/workspace/.factory-seeded";
23
+ const defaultBridgePorts = [4e3];
24
+ /** Derive a deterministic provider sandbox name from a scoped Task-attempt identity. */
25
+ function taskSandboxName(key, scope) {
26
+ return `factory-task-${createHash("sha256").update(`${scope}:${key.taskId}:${key.attempt}`).digest("hex").slice(0, 16)}`;
27
+ }
28
+ /** Build the complete tag set used to discover and re-verify a Task sandbox. */
29
+ function taskSandboxTags(key, scope) {
30
+ return {
31
+ [discoveryTagKey]: taskSandboxName(key, scope),
32
+ factoryScope: createHash("sha256").update(scope).digest("hex").slice(0, 16),
33
+ factoryTaskId: key.taskId,
34
+ factoryTaskAttempt: String(key.attempt)
35
+ };
36
+ }
37
+ function verifyTags(key, scope, name, tags) {
38
+ const expected = taskSandboxTags(key, scope);
39
+ if (name !== taskSandboxName(key, scope) || tags?.[discoveryTagKey] !== expected[discoveryTagKey] || tags?.factoryScope !== expected.factoryScope || tags?.factoryTaskId !== expected.factoryTaskId || tags?.factoryTaskAttempt !== expected.factoryTaskAttempt) throw new Error(`Sandbox ${name} does not carry the identity of Task ${key.taskId} attempt ${key.attempt}`);
40
+ }
41
+ async function isSeeded(sandbox, marker) {
42
+ return (await sandbox.runCommand({
43
+ cmd: "test",
44
+ args: ["-f", marker],
45
+ timeoutMs: 1e4
46
+ })).exitCode === 0;
47
+ }
48
+ async function markSeeded(sandbox, marker) {
49
+ await sandbox.writeFiles([{
50
+ path: marker,
51
+ content: "seeded"
52
+ }]);
53
+ }
54
+ /** Create or recover the exact sandbox for a Task attempt and ensure seeding completed. */
55
+ async function ensureTaskSandbox(key, options) {
56
+ const api = options.api ?? Sandbox;
57
+ const name = taskSandboxName(key, options.scope);
58
+ const seededMarker = options.seededMarker ?? defaultSeededMarker;
59
+ const sandbox = await api.getOrCreate({
60
+ name,
61
+ runtime: options.runtime ?? "node24",
62
+ ports: [...options.ports ?? defaultBridgePorts],
63
+ timeout: options.timeoutMs,
64
+ tags: taskSandboxTags(key, options.scope),
65
+ async onCreate(created) {
66
+ await options.seed(created);
67
+ await markSeeded(created, seededMarker);
68
+ }
69
+ });
70
+ verifyTags(key, options.scope, sandbox.name, sandbox.tags);
71
+ if (!await isSeeded(sandbox, seededMarker)) {
72
+ await options.seed(sandbox);
73
+ await markSeeded(sandbox, seededMarker);
74
+ }
75
+ return sandbox;
76
+ }
77
+ /** Discover an existing Task sandbox without resuming or replacing it. */
78
+ async function findTaskSandbox(key, options) {
79
+ const api = options.api ?? Sandbox;
80
+ const name = taskSandboxName(key, options.scope);
81
+ const matches = await api.list({
82
+ tags: { [discoveryTagKey]: name },
83
+ limit: 2
84
+ });
85
+ if (matches.sandboxes.length === 0) return null;
86
+ if (matches.sandboxes.length > 1 || matches.pagination.next) throw new Error(`More than one sandbox matches Task ${key.taskId} attempt ${key.attempt}; refusing to select one`);
87
+ const candidate = matches.sandboxes[0];
88
+ verifyTags(key, options.scope, candidate.name, candidate.tags);
89
+ let sandbox;
90
+ try {
91
+ sandbox = await api.get({
92
+ name: candidate.name,
93
+ resume: false
94
+ });
95
+ } catch (error) {
96
+ if (isMissing(error)) return null;
97
+ throw error;
98
+ }
99
+ verifyTags(key, options.scope, sandbox.name, sandbox.tags);
100
+ return sandbox;
101
+ }
102
+ /** Stop a live Task sandbox idempotently while treating provider disappearance as success. */
103
+ async function stopTaskSandbox(sandbox) {
104
+ if (observe(sandbox).liveness === "terminal") return;
105
+ try {
106
+ await sandbox.stop();
107
+ } catch (error) {
108
+ if (!isMissing(error)) throw error;
109
+ }
110
+ }
111
+ function isMissing(error) {
112
+ return typeof error === "object" && error !== null && ("status" in error && error.status === 404 || "response" in error && error.response instanceof Response && error.response.status === 404);
113
+ }
114
+ /** Adapt scoped Vercel Sandbox creation and discovery to the execution-environment contract. */
115
+ function createTaskSandboxEnvironment(options) {
116
+ return {
117
+ name: (key) => taskSandboxName(key, options.scope),
118
+ ensure: (key, { timeoutMs, request }) => ensureTaskSandbox(key, {
119
+ scope: options.scope,
120
+ timeoutMs,
121
+ seed: (sandbox) => options.seed(request, sandbox),
122
+ ...options.runtime ? { runtime: options.runtime } : {},
123
+ ...options.ports ? { ports: options.ports } : {},
124
+ ...options.seededMarker ? { seededMarker: options.seededMarker } : {},
125
+ api: options.api
126
+ }).then(observe),
127
+ find: async (key) => {
128
+ const sandbox = await findTaskSandbox(key, {
129
+ scope: options.scope,
130
+ api: options.api
131
+ });
132
+ return sandbox ? observe(sandbox) : null;
133
+ },
134
+ stop: stopTaskSandbox
135
+ };
136
+ }
137
+ //#endregion
138
+ export { createTaskSandboxEnvironment, ensureTaskSandbox, findTaskSandbox, stopTaskSandbox, taskSandboxName, taskSandboxTags };
139
+
140
+ //# sourceMappingURL=task-environment.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-environment.mjs","names":[],"sources":["../../src/sandbox/task-environment.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { Sandbox } from \"@vercel/sandbox\";\nimport type { CodingExecutionRequest, TaskAttemptRef } from \"../schema/execution\";\nimport type { ExecutionEnvironment, EnvironmentLiveness } from \"./execution-environment\";\n\nconst livenessByStatus: Record<Sandbox[\"status\"], EnvironmentLiveness> = {\n pending: \"transitioning\",\n running: \"live\",\n stopping: \"terminal\",\n stopped: \"terminal\",\n failed: \"terminal\",\n aborted: \"terminal\",\n snapshotting: \"terminal\",\n};\n\nfunction observe(sandbox: Sandbox) {\n const liveness = livenessByStatus[sandbox.status];\n if (liveness === undefined) throw new Error(\"Unsupported sandbox liveness state\");\n return { sandbox, liveness };\n}\n\n/** Isolates stores that reuse Task IDs within the project's shared sandbox namespace. */\nexport interface TaskSandboxScope {\n scope: string;\n}\n\n/** Injectable subset of the Vercel Sandbox API used for creation and exact identity discovery. */\nexport type SandboxApi = Pick<typeof Sandbox, \"getOrCreate\" | \"get\" | \"list\">;\n\nconst discoveryTagKey = \"factoryTask\";\nconst defaultSeededMarker = \"/workspace/.factory-seeded\";\n// The harness bridge listens on port 4000.\nconst defaultBridgePorts = [4000];\n\n/** Derive a deterministic provider sandbox name from a scoped Task-attempt identity. */\nexport function taskSandboxName(key: TaskAttemptRef, scope: string): string {\n const digest = createHash(\"sha256\")\n .update(`${scope}:${key.taskId}:${key.attempt}`)\n .digest(\"hex\")\n .slice(0, 16);\n return `factory-task-${digest}`;\n}\n\n/** Build the complete tag set used to discover and re-verify a Task sandbox. */\nexport function taskSandboxTags(key: TaskAttemptRef, scope: string): Record<string, string> {\n return {\n [discoveryTagKey]: taskSandboxName(key, scope),\n factoryScope: createHash(\"sha256\").update(scope).digest(\"hex\").slice(0, 16),\n factoryTaskId: key.taskId,\n factoryTaskAttempt: String(key.attempt),\n };\n}\n\nfunction verifyTags(\n key: TaskAttemptRef,\n scope: string,\n name: string,\n tags: Record<string, string> | undefined,\n) {\n const expected = taskSandboxTags(key, scope);\n if (\n name !== taskSandboxName(key, scope) ||\n tags?.[discoveryTagKey] !== expected[discoveryTagKey] ||\n tags?.factoryScope !== expected.factoryScope ||\n tags?.factoryTaskId !== expected.factoryTaskId ||\n tags?.factoryTaskAttempt !== expected.factoryTaskAttempt\n ) {\n throw new Error(\n `Sandbox ${name} does not carry the identity of Task ${key.taskId} attempt ${key.attempt}`,\n );\n }\n}\n\nasync function isSeeded(sandbox: Sandbox, marker: string): Promise<boolean> {\n const command = await sandbox.runCommand({\n cmd: \"test\",\n args: [\"-f\", marker],\n timeoutMs: 10_000,\n });\n return command.exitCode === 0;\n}\n\nasync function markSeeded(sandbox: Sandbox, marker: string): Promise<void> {\n await sandbox.writeFiles([{ path: marker, content: \"seeded\" }]);\n}\n\n/** Configures idempotent creation and workspace seeding for a Task sandbox. */\nexport interface EnsureTaskSandboxOptions extends TaskSandboxScope {\n /** Sandbox lifetime; callers add margin over the execution timeout. */\n timeoutMs: number;\n /** Seeds the workspace; must be idempotent because a crashed seed reruns. */\n seed(sandbox: Sandbox): Promise<void>;\n runtime?: string;\n ports?: readonly number[];\n seededMarker?: string;\n api?: SandboxApi;\n}\n\n/** Create or recover the exact sandbox for a Task attempt and ensure seeding completed. */\nexport async function ensureTaskSandbox(\n key: TaskAttemptRef,\n options: EnsureTaskSandboxOptions,\n): Promise<Sandbox> {\n const api = options.api ?? Sandbox;\n const name = taskSandboxName(key, options.scope);\n const seededMarker = options.seededMarker ?? defaultSeededMarker;\n const sandbox = await api.getOrCreate({\n name,\n runtime: options.runtime ?? \"node24\",\n ports: [...(options.ports ?? defaultBridgePorts)],\n timeout: options.timeoutMs,\n tags: taskSandboxTags(key, options.scope),\n async onCreate(created) {\n await options.seed(created);\n await markSeeded(created, seededMarker);\n },\n });\n verifyTags(key, options.scope, sandbox.name, sandbox.tags);\n // onCreate can crash between creation and the marker; finish seeding here.\n if (!(await isSeeded(sandbox, seededMarker))) {\n await options.seed(sandbox);\n await markSeeded(sandbox, seededMarker);\n }\n return sandbox;\n}\n\n/** Scope and provider API used to discover an existing Task sandbox. */\nexport interface FindTaskSandboxOptions extends TaskSandboxScope {\n api?: SandboxApi;\n}\n\n/** Discover an existing Task sandbox without resuming or replacing it. */\nexport async function findTaskSandbox(\n key: TaskAttemptRef,\n options: FindTaskSandboxOptions,\n): Promise<Sandbox | null> {\n const api = options.api ?? Sandbox;\n const name = taskSandboxName(key, options.scope);\n // The Sandbox API accepts only one tag filter; all tags are re-verified below.\n const matches = await api.list({ tags: { [discoveryTagKey]: name }, limit: 2 });\n if (matches.sandboxes.length === 0) return null;\n if (matches.sandboxes.length > 1 || matches.pagination.next) {\n throw new Error(\n `More than one sandbox matches Task ${key.taskId} attempt ${key.attempt}; refusing to select one`,\n );\n }\n const candidate = matches.sandboxes[0]!;\n verifyTags(key, options.scope, candidate.name, candidate.tags);\n let sandbox: Sandbox;\n try {\n sandbox = await api.get({ name: candidate.name, resume: false });\n } catch (error) {\n if (isMissing(error)) return null;\n throw error;\n }\n verifyTags(key, options.scope, sandbox.name, sandbox.tags);\n return sandbox;\n}\n\n/** Stop a live Task sandbox idempotently while treating provider disappearance as success. */\nexport async function stopTaskSandbox(sandbox: Sandbox): Promise<void> {\n if (observe(sandbox).liveness === \"terminal\") return;\n try {\n await sandbox.stop();\n } catch (error) {\n if (!isMissing(error)) throw error;\n }\n}\n\nfunction isMissing(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n ((\"status\" in error && error.status === 404) ||\n (\"response\" in error && error.response instanceof Response && error.response.status === 404))\n );\n}\n\n/** Scoped creation, seeding, and provider dependencies for a Task sandbox environment. */\nexport interface TaskSandboxEnvironmentOptions {\n /** Deployment- or run-unique namespace; see {@link TaskSandboxScope}. */\n scope: string;\n seed(request: CodingExecutionRequest, sandbox: Sandbox): Promise<void>;\n runtime?: EnsureTaskSandboxOptions[\"runtime\"];\n ports?: readonly number[];\n seededMarker?: string;\n api?: SandboxApi;\n}\n\n/** Adapt scoped Vercel Sandbox creation and discovery to the execution-environment contract. */\nexport function createTaskSandboxEnvironment(\n options: TaskSandboxEnvironmentOptions,\n): ExecutionEnvironment<Sandbox> {\n return {\n name: (key) => taskSandboxName(key, options.scope),\n ensure: (key, { timeoutMs, request }) =>\n ensureTaskSandbox(key, {\n scope: options.scope,\n timeoutMs,\n seed: (sandbox) => options.seed(request, sandbox),\n ...(options.runtime ? { runtime: options.runtime } : {}),\n ...(options.ports ? { ports: options.ports } : {}),\n ...(options.seededMarker ? { seededMarker: options.seededMarker } : {}),\n api: options.api,\n }).then(observe),\n find: async (key) => {\n const sandbox = await findTaskSandbox(key, { scope: options.scope, api: options.api });\n return sandbox ? observe(sandbox) : null;\n },\n stop: stopTaskSandbox,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ //#region src/sandbox/workspace.d.ts
3
+ declare const outputPathSchema: z.core.$ZodBranded<z.ZodString, "SandboxOutputPath", "out">;
4
+ /** An absolute, normalized artifact path confined to the configured sandbox output directory. */
5
+ type SandboxOutputPath = z.infer<typeof outputPathSchema>;
6
+ /** Current working directory reported by a sandbox session. */
7
+ interface SandboxSession {
8
+ cwd: string;
9
+ }
10
+ /** Minimal sandbox session boundary needed to derive workspace paths. */
11
+ interface SandboxWorkspaceHandle {
12
+ currentSession(): SandboxSession;
13
+ }
14
+ /** Standard repository, output, and artifact paths inside a harness workspace. */
15
+ interface HarnessWorkspace {
16
+ root: string;
17
+ repo: string;
18
+ out: string;
19
+ artifacts: string;
20
+ }
21
+ /** File existence, symlinks, and read limits are checked by the sandbox reader. */
22
+ declare function parseSandboxOutputPath(value: unknown, outputDirectory: string): SandboxOutputPath;
23
+ /** Default harness SDK working directory beneath the sandbox session root. */
24
+ declare const defaultHarnessWorkDir = "workspace";
25
+ /** Resolve the standard repository, output, and artifact paths for a harness workspace. */
26
+ declare function harnessWorkspace(sandbox: SandboxWorkspaceHandle): HarnessWorkspace;
27
+ //#endregion
28
+ export { HarnessWorkspace, SandboxOutputPath, SandboxSession, SandboxWorkspaceHandle, defaultHarnessWorkDir, harnessWorkspace, parseSandboxOutputPath };
29
+ //# sourceMappingURL=workspace.d.mts.map
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ import { posix } from "node:path";
3
+ //#region src/sandbox/workspace.ts
4
+ const outputPathSchema = z.string().refine((value) => posix.isAbsolute(value) && posix.normalize(value) === value && !value.includes("\0"), "Artifact paths must stay inside the captured workspace output").brand();
5
+ /** File existence, symlinks, and read limits are checked by the sandbox reader. */
6
+ function parseSandboxOutputPath(value, outputDirectory) {
7
+ const path = outputPathSchema.parse(value);
8
+ if (!path.startsWith(`${outputDirectory}/`)) throw new Error("Artifact paths must stay inside the captured workspace output");
9
+ return path;
10
+ }
11
+ /** Default harness SDK working directory beneath the sandbox session root. */
12
+ const defaultHarnessWorkDir = "workspace";
13
+ /** Resolve the standard repository, output, and artifact paths for a harness workspace. */
14
+ function harnessWorkspace(sandbox) {
15
+ const cwd = sandbox.currentSession().cwd;
16
+ if (!posix.isAbsolute(cwd)) throw new Error("The sandbox working directory must be absolute");
17
+ const root = posix.join(cwd, defaultHarnessWorkDir);
18
+ return {
19
+ root,
20
+ repo: posix.join(root, "repo"),
21
+ out: posix.join(root, "out"),
22
+ artifacts: posix.join(root, "artifacts")
23
+ };
24
+ }
25
+ //#endregion
26
+ export { defaultHarnessWorkDir, harnessWorkspace, parseSandboxOutputPath };
27
+
28
+ //# sourceMappingURL=workspace.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.mjs","names":[],"sources":["../../src/sandbox/workspace.ts"],"sourcesContent":["import { posix } from \"node:path\";\nimport { z } from \"zod\";\n\nconst outputPathSchema = z\n .string()\n .refine(\n (value) => posix.isAbsolute(value) && posix.normalize(value) === value && !value.includes(\"\\0\"),\n \"Artifact paths must stay inside the captured workspace output\",\n )\n .brand<\"SandboxOutputPath\">();\n\n/** An absolute, normalized artifact path confined to the configured sandbox output directory. */\nexport type SandboxOutputPath = z.infer<typeof outputPathSchema>;\n\n/** Current working directory reported by a sandbox session. */\nexport interface SandboxSession {\n cwd: string;\n}\n\n/** Minimal sandbox session boundary needed to derive workspace paths. */\nexport interface SandboxWorkspaceHandle {\n currentSession(): SandboxSession;\n}\n\n/** Standard repository, output, and artifact paths inside a harness workspace. */\nexport interface HarnessWorkspace {\n root: string;\n repo: string;\n out: string;\n artifacts: string;\n}\n\n/** File existence, symlinks, and read limits are checked by the sandbox reader. */\nexport function parseSandboxOutputPath(value: unknown, outputDirectory: string): SandboxOutputPath {\n const path = outputPathSchema.parse(value);\n if (!path.startsWith(`${outputDirectory}/`))\n throw new Error(\"Artifact paths must stay inside the captured workspace output\");\n return path;\n}\n\n/** Default harness SDK working directory beneath the sandbox session root. */\nexport const defaultHarnessWorkDir = \"workspace\";\n\n/** Resolve the standard repository, output, and artifact paths for a harness workspace. */\nexport function harnessWorkspace(sandbox: SandboxWorkspaceHandle): HarnessWorkspace {\n const cwd = sandbox.currentSession().cwd;\n if (!posix.isAbsolute(cwd)) throw new Error(\"The sandbox working directory must be absolute\");\n const root = posix.join(cwd, defaultHarnessWorkDir);\n return {\n root,\n repo: posix.join(root, \"repo\"),\n out: posix.join(root, \"out\"),\n artifacts: posix.join(root, \"artifacts\"),\n };\n}\n"],"mappings":";;;AAGA,MAAM,mBAAmB,EACtB,OAAO,CAAC,CACR,QACE,UAAU,MAAM,WAAW,KAAK,KAAK,MAAM,UAAU,KAAK,MAAM,SAAS,CAAC,MAAM,SAAS,IAAI,GAC9F,+DACF,CAAC,CACA,MAA2B;;AAwB9B,SAAgB,uBAAuB,OAAgB,iBAA4C;CACjG,MAAM,OAAO,iBAAiB,MAAM,KAAK;CACzC,IAAI,CAAC,KAAK,WAAW,GAAG,gBAAgB,EAAE,GACxC,MAAM,IAAI,MAAM,+DAA+D;CACjF,OAAO;AACT;;AAGA,MAAa,wBAAwB;;AAGrC,SAAgB,iBAAiB,SAAmD;CAClF,MAAM,MAAM,QAAQ,eAAe,CAAC,CAAC;CACrC,IAAI,CAAC,MAAM,WAAW,GAAG,GAAG,MAAM,IAAI,MAAM,gDAAgD;CAC5F,MAAM,OAAO,MAAM,KAAK,KAAK,qBAAqB;CAClD,OAAO;EACL;EACA,MAAM,MAAM,KAAK,MAAM,MAAM;EAC7B,KAAK,MAAM,KAAK,MAAM,KAAK;EAC3B,WAAW,MAAM,KAAK,MAAM,WAAW;CACzC;AACF"}