@elie-laloum/outpost 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (381) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +3 -1
  3. package/SECURITY.md +3 -1
  4. package/dist/adapters/agents/gemini-adapter.d.ts +3 -0
  5. package/dist/adapters/agents/gemini-adapter.js +15 -0
  6. package/dist/adapters/agents/gemini-adapter.js.map +1 -0
  7. package/dist/adapters/agents/gemini-diagnostics.d.ts +2 -0
  8. package/dist/adapters/agents/gemini-diagnostics.js +15 -0
  9. package/dist/adapters/agents/gemini-diagnostics.js.map +1 -0
  10. package/dist/adapters/agents/gemini-events.d.ts +2 -0
  11. package/dist/adapters/agents/gemini-events.js +50 -0
  12. package/dist/adapters/agents/gemini-events.js.map +1 -0
  13. package/dist/adapters/agents/gemini-request.d.ts +4 -0
  14. package/dist/adapters/agents/gemini-request.js +21 -0
  15. package/dist/adapters/agents/gemini-request.js.map +1 -0
  16. package/dist/adapters/agents/gemini.types.d.ts +6 -0
  17. package/dist/adapters/agents/gemini.types.js +2 -0
  18. package/dist/adapters/agents/gemini.types.js.map +1 -0
  19. package/dist/adapters/agents/protocol-fixtures.constants.d.ts +1 -1
  20. package/dist/adapters/agents/protocol-fixtures.constants.js +37 -0
  21. package/dist/adapters/agents/protocol-fixtures.constants.js.map +1 -1
  22. package/dist/application/agent-bootstrap.constants.d.ts +1 -0
  23. package/dist/application/agent-bootstrap.constants.js +1 -0
  24. package/dist/application/agent-bootstrap.constants.js.map +1 -1
  25. package/dist/application/agent-bootstrap.js +6 -2
  26. package/dist/application/agent-bootstrap.js.map +1 -1
  27. package/dist/application/agent-output.js +9 -2
  28. package/dist/application/agent-output.js.map +1 -1
  29. package/dist/application/artifact-tasks.d.ts +5 -0
  30. package/dist/application/artifact-tasks.js +31 -0
  31. package/dist/application/artifact-tasks.js.map +1 -0
  32. package/dist/application/artifact-tasks.types.d.ts +8 -0
  33. package/dist/application/artifact-tasks.types.js +2 -0
  34. package/dist/application/artifact-tasks.types.js.map +1 -0
  35. package/dist/application/dispatch-validation.js +2 -0
  36. package/dist/application/dispatch-validation.js.map +1 -1
  37. package/dist/application/doctor-agent.constants.d.ts +2 -0
  38. package/dist/application/doctor-agent.constants.js +2 -0
  39. package/dist/application/doctor-agent.constants.js.map +1 -1
  40. package/dist/application/doctor-agent.js +1 -1
  41. package/dist/application/doctor-agent.js.map +1 -1
  42. package/dist/application/doctor-protocol.js +2 -1
  43. package/dist/application/doctor-protocol.js.map +1 -1
  44. package/dist/application/doctor.constants.js +1 -1
  45. package/dist/application/doctor.constants.js.map +1 -1
  46. package/dist/application/doctor.types.d.ts +1 -1
  47. package/dist/application/doctor.types.js.map +1 -1
  48. package/dist/application/outpost.types.d.ts +2 -0
  49. package/dist/application/outpost.types.js.map +1 -1
  50. package/dist/application/queue-worker.d.ts +2 -0
  51. package/dist/application/queue-worker.js +75 -0
  52. package/dist/application/queue-worker.js.map +1 -0
  53. package/dist/application/queue-worker.types.d.ts +15 -0
  54. package/dist/application/queue-worker.types.js +2 -0
  55. package/dist/application/queue-worker.types.js.map +1 -0
  56. package/dist/application/queued-task.d.ts +3 -0
  57. package/dist/application/queued-task.js +56 -0
  58. package/dist/application/queued-task.js.map +1 -0
  59. package/dist/application/queued-task.types.d.ts +11 -0
  60. package/dist/application/queued-task.types.js +2 -0
  61. package/dist/application/queued-task.types.js.map +1 -0
  62. package/dist/application/recovery-inspection.js +5 -0
  63. package/dist/application/recovery-inspection.js.map +1 -1
  64. package/dist/application/recovery-inspection.types.d.ts +3 -0
  65. package/dist/application/recovery-inspection.types.js.map +1 -1
  66. package/dist/application/recovery-restore-snapshot.d.ts +2 -0
  67. package/dist/application/recovery-restore-snapshot.js +57 -0
  68. package/dist/application/recovery-restore-snapshot.js.map +1 -0
  69. package/dist/application/recovery-restore.d.ts +3 -0
  70. package/dist/application/recovery-restore.js +161 -0
  71. package/dist/application/recovery-restore.js.map +1 -0
  72. package/dist/application/recovery-restore.types.d.ts +28 -0
  73. package/dist/application/recovery-restore.types.js +2 -0
  74. package/dist/application/recovery-restore.types.js.map +1 -0
  75. package/dist/application/recovery-retention.js +5 -0
  76. package/dist/application/recovery-retention.js.map +1 -1
  77. package/dist/application/recovery-verification.d.ts +2 -1
  78. package/dist/application/recovery-verification.js +1 -1
  79. package/dist/application/recovery-verification.js.map +1 -1
  80. package/dist/application/remote-apply.js +6 -0
  81. package/dist/application/remote-apply.js.map +1 -1
  82. package/dist/application/remote-download.js +2 -2
  83. package/dist/application/remote-download.js.map +1 -1
  84. package/dist/application/remote-history.d.ts +6 -0
  85. package/dist/application/remote-history.js +114 -0
  86. package/dist/application/remote-history.js.map +1 -0
  87. package/dist/application/remote-upload.d.ts +2 -0
  88. package/dist/application/remote-upload.js +17 -0
  89. package/dist/application/remote-upload.js.map +1 -0
  90. package/dist/application/remote-validation.js +20 -28
  91. package/dist/application/remote-validation.js.map +1 -1
  92. package/dist/application/remote-workspace.js +4 -10
  93. package/dist/application/remote-workspace.js.map +1 -1
  94. package/dist/application/sandbox-activity.d.ts +3 -0
  95. package/dist/application/sandbox-activity.js +25 -0
  96. package/dist/application/sandbox-activity.js.map +1 -0
  97. package/dist/application/sandbox-provision.js +55 -10
  98. package/dist/application/sandbox-provision.js.map +1 -1
  99. package/dist/application/sandbox-session.types.d.ts +2 -0
  100. package/dist/application/sandbox-session.types.js.map +1 -1
  101. package/dist/application/sandbox.js +23 -11
  102. package/dist/application/sandbox.js.map +1 -1
  103. package/dist/application/speculation-host.d.ts +2 -0
  104. package/dist/application/speculation-host.js +30 -0
  105. package/dist/application/speculation-host.js.map +1 -0
  106. package/dist/application/speculation.constants.d.ts +4 -0
  107. package/dist/application/speculation.constants.js +2 -0
  108. package/dist/application/speculation.constants.js.map +1 -0
  109. package/dist/application/speculation.d.ts +2 -0
  110. package/dist/application/speculation.js +166 -0
  111. package/dist/application/speculation.js.map +1 -0
  112. package/dist/application/speculation.types.d.ts +56 -0
  113. package/dist/application/speculation.types.js +2 -0
  114. package/dist/application/speculation.types.js.map +1 -0
  115. package/dist/application/storage-reservation.d.ts +3 -0
  116. package/dist/application/storage-reservation.js +10 -0
  117. package/dist/application/storage-reservation.js.map +1 -0
  118. package/dist/application/storage-reservation.types.d.ts +4 -0
  119. package/dist/application/storage-reservation.types.js +2 -0
  120. package/dist/application/storage-reservation.types.js.map +1 -0
  121. package/dist/application/task-usage.d.ts +1 -1
  122. package/dist/application/task-usage.js.map +1 -1
  123. package/dist/application/tasks.js +1 -1
  124. package/dist/application/tasks.js.map +1 -1
  125. package/dist/application/tasks.types.d.ts +4 -3
  126. package/dist/application/tasks.types.js.map +1 -1
  127. package/dist/application/workspace-allocation.d.ts +3 -0
  128. package/dist/application/workspace-allocation.js +34 -0
  129. package/dist/application/workspace-allocation.js.map +1 -0
  130. package/dist/application/workspace.js +2 -2
  131. package/dist/application/workspace.js.map +1 -1
  132. package/dist/cli/doctor-command.js +1 -1
  133. package/dist/cli/doctor-command.js.map +1 -1
  134. package/dist/cli/main.constants.d.ts +11 -2
  135. package/dist/cli/main.constants.js +8 -4
  136. package/dist/cli/main.constants.js.map +1 -1
  137. package/dist/cli/recovery-command.js +28 -4
  138. package/dist/cli/recovery-command.js.map +1 -1
  139. package/dist/cli/recovery-restore-command.d.ts +2 -0
  140. package/dist/cli/recovery-restore-command.js +34 -0
  141. package/dist/cli/recovery-restore-command.js.map +1 -0
  142. package/dist/cli/scaffold-files.js +2 -2
  143. package/dist/cli/scaffold-files.js.map +1 -1
  144. package/dist/cli/scaffold-validation.js +1 -1
  145. package/dist/cli/scaffold-validation.js.map +1 -1
  146. package/dist/cli/scaffold.constants.d.ts +5 -0
  147. package/dist/cli/scaffold.constants.js +7 -2
  148. package/dist/cli/scaffold.constants.js.map +1 -1
  149. package/dist/cli/scaffold.types.d.ts +1 -1
  150. package/dist/cli/scaffold.types.js.map +1 -1
  151. package/dist/domain/agent.types.d.ts +2 -0
  152. package/dist/domain/agent.types.js.map +1 -1
  153. package/dist/domain/artifact-reference.d.ts +4 -0
  154. package/dist/domain/artifact-reference.js +90 -0
  155. package/dist/domain/artifact-reference.js.map +1 -0
  156. package/dist/domain/artifact.constants.d.ts +2 -0
  157. package/dist/domain/artifact.constants.js +3 -0
  158. package/dist/domain/artifact.constants.js.map +1 -0
  159. package/dist/domain/artifact.d.ts +7 -0
  160. package/dist/domain/artifact.js +104 -0
  161. package/dist/domain/artifact.js.map +1 -0
  162. package/dist/domain/artifact.types.d.ts +44 -0
  163. package/dist/domain/artifact.types.js +2 -0
  164. package/dist/domain/artifact.types.js.map +1 -0
  165. package/dist/domain/egress.constants.d.ts +1 -0
  166. package/dist/domain/egress.constants.js +7 -0
  167. package/dist/domain/egress.constants.js.map +1 -0
  168. package/dist/domain/egress.d.ts +2 -0
  169. package/dist/domain/egress.js +48 -0
  170. package/dist/domain/egress.js.map +1 -0
  171. package/dist/domain/egress.types.d.ts +8 -0
  172. package/dist/domain/egress.types.js +2 -0
  173. package/dist/domain/egress.types.js.map +1 -0
  174. package/dist/domain/sandbox.types.d.ts +1 -0
  175. package/dist/domain/sandbox.types.js.map +1 -1
  176. package/dist/domain/task-queue.constants.d.ts +8 -0
  177. package/dist/domain/task-queue.constants.js +9 -0
  178. package/dist/domain/task-queue.constants.js.map +1 -0
  179. package/dist/domain/task-queue.d.ts +11 -0
  180. package/dist/domain/task-queue.js +105 -0
  181. package/dist/domain/task-queue.js.map +1 -0
  182. package/dist/domain/task-queue.types.d.ts +41 -0
  183. package/dist/domain/task-queue.types.js +2 -0
  184. package/dist/domain/task-queue.types.js.map +1 -0
  185. package/dist/domain/workflow/budget.d.ts +2 -2
  186. package/dist/domain/workflow/budget.js +5 -3
  187. package/dist/domain/workflow/budget.js.map +1 -1
  188. package/dist/domain/workflow/checkpoint-validation.d.ts +3 -0
  189. package/dist/domain/workflow/checkpoint-validation.js +81 -0
  190. package/dist/domain/workflow/checkpoint-validation.js.map +1 -0
  191. package/dist/domain/workflow/checkpoint-value.d.ts +2 -0
  192. package/dist/domain/workflow/checkpoint-value.js +49 -0
  193. package/dist/domain/workflow/checkpoint-value.js.map +1 -0
  194. package/dist/domain/workflow/checkpoint.d.ts +3 -0
  195. package/dist/domain/workflow/checkpoint.js +70 -0
  196. package/dist/domain/workflow/checkpoint.js.map +1 -0
  197. package/dist/domain/workflow/checkpoint.types.d.ts +40 -0
  198. package/dist/domain/workflow/checkpoint.types.js +2 -0
  199. package/dist/domain/workflow/checkpoint.types.js.map +1 -0
  200. package/dist/domain/workflow/gate-validation.d.ts +4 -0
  201. package/dist/domain/workflow/gate-validation.js +71 -0
  202. package/dist/domain/workflow/gate-validation.js.map +1 -0
  203. package/dist/domain/workflow/gates.constants.d.ts +4 -0
  204. package/dist/domain/workflow/gates.constants.js +5 -0
  205. package/dist/domain/workflow/gates.constants.js.map +1 -0
  206. package/dist/domain/workflow/gates.d.ts +7 -0
  207. package/dist/domain/workflow/gates.js +85 -0
  208. package/dist/domain/workflow/gates.js.map +1 -0
  209. package/dist/domain/workflow/gates.types.d.ts +27 -0
  210. package/dist/domain/workflow/gates.types.js +2 -0
  211. package/dist/domain/workflow/gates.types.js.map +1 -0
  212. package/dist/domain/workflow/task-runner.js +14 -2
  213. package/dist/domain/workflow/task-runner.js.map +1 -1
  214. package/dist/domain/workflow/usage-receipt.constants.d.ts +2 -0
  215. package/dist/domain/workflow/usage-receipt.constants.js +3 -0
  216. package/dist/domain/workflow/usage-receipt.constants.js.map +1 -0
  217. package/dist/domain/workflow/usage-receipt.d.ts +2 -0
  218. package/dist/domain/workflow/usage-receipt.js +18 -0
  219. package/dist/domain/workflow/usage-receipt.js.map +1 -0
  220. package/dist/domain/workflow/validation.js +6 -0
  221. package/dist/domain/workflow/validation.js.map +1 -1
  222. package/dist/domain/workflow/workflow-scheduler.js +65 -32
  223. package/dist/domain/workflow/workflow-scheduler.js.map +1 -1
  224. package/dist/domain/workflow/workflow-state.d.ts +2 -1
  225. package/dist/domain/workflow/workflow-state.js +91 -16
  226. package/dist/domain/workflow/workflow-state.js.map +1 -1
  227. package/dist/domain/workflow.types.d.ts +13 -2
  228. package/dist/domain/workflow.types.js.map +1 -1
  229. package/dist/index.d.ts +32 -2
  230. package/dist/index.js +14 -1
  231. package/dist/index.js.map +1 -1
  232. package/dist/infrastructure/artifact-store.constants.d.ts +1 -0
  233. package/dist/infrastructure/artifact-store.constants.js +2 -0
  234. package/dist/infrastructure/artifact-store.constants.js.map +1 -0
  235. package/dist/infrastructure/artifact-store.d.ts +3 -0
  236. package/dist/infrastructure/artifact-store.js +100 -0
  237. package/dist/infrastructure/artifact-store.js.map +1 -0
  238. package/dist/infrastructure/artifact-store.types.d.ts +4 -0
  239. package/dist/infrastructure/artifact-store.types.js +2 -0
  240. package/dist/infrastructure/artifact-store.types.js.map +1 -0
  241. package/dist/infrastructure/file-manifest.d.ts +1 -1
  242. package/dist/infrastructure/file-manifest.js +3 -2
  243. package/dist/infrastructure/file-manifest.js.map +1 -1
  244. package/dist/infrastructure/git/verification-command.d.ts +1 -1
  245. package/dist/infrastructure/git/verification-command.js +3 -2
  246. package/dist/infrastructure/git/verification-command.js.map +1 -1
  247. package/dist/infrastructure/opentelemetry.js +1 -1
  248. package/dist/infrastructure/opentelemetry.js.map +1 -1
  249. package/dist/infrastructure/resource-activity-inspection.d.ts +2 -0
  250. package/dist/infrastructure/resource-activity-inspection.js +152 -0
  251. package/dist/infrastructure/resource-activity-inspection.js.map +1 -0
  252. package/dist/infrastructure/resource-activity.constants.d.ts +8 -0
  253. package/dist/infrastructure/resource-activity.constants.js +26 -0
  254. package/dist/infrastructure/resource-activity.constants.js.map +1 -0
  255. package/dist/infrastructure/resource-activity.d.ts +2 -0
  256. package/dist/infrastructure/resource-activity.js +166 -0
  257. package/dist/infrastructure/resource-activity.js.map +1 -0
  258. package/dist/infrastructure/resource-activity.types.d.ts +53 -0
  259. package/dist/infrastructure/resource-activity.types.js +2 -0
  260. package/dist/infrastructure/resource-activity.types.js.map +1 -0
  261. package/dist/infrastructure/storage-mutation-lock.constants.d.ts +5 -0
  262. package/dist/infrastructure/storage-mutation-lock.constants.js +6 -0
  263. package/dist/infrastructure/storage-mutation-lock.constants.js.map +1 -0
  264. package/dist/infrastructure/storage-mutation-lock.d.ts +1 -0
  265. package/dist/infrastructure/storage-mutation-lock.js +21 -0
  266. package/dist/infrastructure/storage-mutation-lock.js.map +1 -0
  267. package/dist/infrastructure/storage-reservations.constants.d.ts +4 -0
  268. package/dist/infrastructure/storage-reservations.constants.js +5 -0
  269. package/dist/infrastructure/storage-reservations.constants.js.map +1 -0
  270. package/dist/infrastructure/storage-reservations.d.ts +2 -0
  271. package/dist/infrastructure/storage-reservations.js +150 -0
  272. package/dist/infrastructure/storage-reservations.js.map +1 -0
  273. package/dist/infrastructure/storage-reservations.types.d.ts +21 -0
  274. package/dist/infrastructure/storage-reservations.types.js +2 -0
  275. package/dist/infrastructure/storage-reservations.types.js.map +1 -0
  276. package/dist/infrastructure/task-queue-http.constants.d.ts +2 -0
  277. package/dist/infrastructure/task-queue-http.constants.js +3 -0
  278. package/dist/infrastructure/task-queue-http.constants.js.map +1 -0
  279. package/dist/infrastructure/task-queue-http.d.ts +4 -0
  280. package/dist/infrastructure/task-queue-http.js +158 -0
  281. package/dist/infrastructure/task-queue-http.js.map +1 -0
  282. package/dist/infrastructure/task-queue-http.types.d.ts +16 -0
  283. package/dist/infrastructure/task-queue-http.types.js +2 -0
  284. package/dist/infrastructure/task-queue-http.types.js.map +1 -0
  285. package/dist/infrastructure/task-queue.d.ts +2 -0
  286. package/dist/infrastructure/task-queue.js +134 -0
  287. package/dist/infrastructure/task-queue.js.map +1 -0
  288. package/dist/infrastructure/transfer.js +5 -0
  289. package/dist/infrastructure/transfer.js.map +1 -1
  290. package/dist/infrastructure/workflow-checkpoint.constants.d.ts +1 -0
  291. package/dist/infrastructure/workflow-checkpoint.constants.js +2 -0
  292. package/dist/infrastructure/workflow-checkpoint.constants.js.map +1 -0
  293. package/dist/infrastructure/workflow-checkpoint.d.ts +3 -0
  294. package/dist/infrastructure/workflow-checkpoint.js +77 -0
  295. package/dist/infrastructure/workflow-checkpoint.js.map +1 -0
  296. package/dist/infrastructure/workflow-checkpoint.types.d.ts +4 -0
  297. package/dist/infrastructure/workflow-checkpoint.types.js +2 -0
  298. package/dist/infrastructure/workflow-checkpoint.types.js.map +1 -0
  299. package/dist/providers/agents.d.ts +2 -0
  300. package/dist/providers/agents.js +1 -0
  301. package/dist/providers/agents.js.map +1 -1
  302. package/dist/providers/container-isolation.d.ts +2 -0
  303. package/dist/providers/container-isolation.js +29 -0
  304. package/dist/providers/container-isolation.js.map +1 -0
  305. package/dist/providers/container-mounts.js +7 -2
  306. package/dist/providers/container-mounts.js.map +1 -1
  307. package/dist/providers/container-network.d.ts +2 -0
  308. package/dist/providers/container-network.js +14 -0
  309. package/dist/providers/container-network.js.map +1 -0
  310. package/dist/providers/container-plan.js +4 -2
  311. package/dist/providers/container-plan.js.map +1 -1
  312. package/dist/providers/container.constants.d.ts +1 -0
  313. package/dist/providers/container.constants.js +1 -0
  314. package/dist/providers/container.constants.js.map +1 -1
  315. package/dist/providers/container.js +19 -2
  316. package/dist/providers/container.js.map +1 -1
  317. package/dist/providers/container.types.d.ts +3 -0
  318. package/dist/providers/container.types.js.map +1 -1
  319. package/dist/providers/daytona-command.js +3 -2
  320. package/dist/providers/daytona-command.js.map +1 -1
  321. package/dist/providers/daytona-terminal.d.ts +3 -0
  322. package/dist/providers/daytona-terminal.js +128 -0
  323. package/dist/providers/daytona-terminal.js.map +1 -0
  324. package/dist/providers/daytona.js +2 -0
  325. package/dist/providers/daytona.js.map +1 -1
  326. package/dist/providers/docker.d.ts +1 -0
  327. package/dist/providers/docker.js.map +1 -1
  328. package/dist/providers/file-batches.d.ts +1 -1
  329. package/dist/providers/file-batches.js +9 -0
  330. package/dist/providers/file-batches.js.map +1 -1
  331. package/dist/providers/file-upload.constants.d.ts +1 -0
  332. package/dist/providers/file-upload.constants.js +68 -0
  333. package/dist/providers/file-upload.constants.js.map +1 -0
  334. package/dist/providers/file-upload.d.ts +2 -0
  335. package/dist/providers/file-upload.js +146 -0
  336. package/dist/providers/file-upload.js.map +1 -0
  337. package/dist/providers/firecracker-command.d.ts +5 -0
  338. package/dist/providers/firecracker-command.js +114 -0
  339. package/dist/providers/firecracker-command.js.map +1 -0
  340. package/dist/providers/firecracker-files.constants.d.ts +1 -0
  341. package/dist/providers/firecracker-files.constants.js +21 -0
  342. package/dist/providers/firecracker-files.constants.js.map +1 -0
  343. package/dist/providers/firecracker-files.d.ts +3 -0
  344. package/dist/providers/firecracker-files.js +110 -0
  345. package/dist/providers/firecracker-files.js.map +1 -0
  346. package/dist/providers/firecracker-machine.d.ts +3 -0
  347. package/dist/providers/firecracker-machine.js +155 -0
  348. package/dist/providers/firecracker-machine.js.map +1 -0
  349. package/dist/providers/firecracker.constants.d.ts +10 -0
  350. package/dist/providers/firecracker.constants.js +11 -0
  351. package/dist/providers/firecracker.constants.js.map +1 -0
  352. package/dist/providers/firecracker.d.ts +4 -0
  353. package/dist/providers/firecracker.js +103 -0
  354. package/dist/providers/firecracker.js.map +1 -0
  355. package/dist/providers/firecracker.types.d.ts +36 -0
  356. package/dist/providers/firecracker.types.js +2 -0
  357. package/dist/providers/firecracker.types.js.map +1 -0
  358. package/dist/providers/local.js +2 -1
  359. package/dist/providers/local.js.map +1 -1
  360. package/dist/providers/podman.d.ts +1 -0
  361. package/dist/providers/podman.js.map +1 -1
  362. package/dist/providers/terminal-bridge.d.ts +14 -0
  363. package/dist/providers/terminal-bridge.js +100 -0
  364. package/dist/providers/terminal-bridge.js.map +1 -0
  365. package/dist/providers/vercel-directory.d.ts +2 -0
  366. package/dist/providers/vercel-directory.js +7 -0
  367. package/dist/providers/vercel-directory.js.map +1 -0
  368. package/dist/providers/vercel-files.js +3 -2
  369. package/dist/providers/vercel-files.js.map +1 -1
  370. package/dist/providers/vercel-network.d.ts +2 -0
  371. package/dist/providers/vercel-network.js +18 -0
  372. package/dist/providers/vercel-network.js.map +1 -0
  373. package/dist/providers/vercel.d.ts +1 -0
  374. package/dist/providers/vercel.js +5 -1
  375. package/dist/providers/vercel.js.map +1 -1
  376. package/dist/providers/vercel.types.d.ts +2 -0
  377. package/dist/providers/vercel.types.js.map +1 -1
  378. package/dist/providers/versions.constants.d.ts +1 -0
  379. package/dist/providers/versions.constants.js +1 -0
  380. package/dist/providers/versions.constants.js.map +1 -1
  381. package/package.json +5 -1
@@ -0,0 +1,3 @@
1
+ import type { Command, CommandResult } from "../domain/command.types.ts";
2
+ import type { DaytonaRuntime } from "./daytona.types.ts";
3
+ export declare function daytonaTerminal(runtime: DaytonaRuntime, command: Command, signal: AbortSignal): Promise<CommandResult>;
@@ -0,0 +1,128 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { setTimeout } from "node:timers/promises";
3
+ import { OutpostError } from "../domain/errors.js";
4
+ import { interruptible } from "../infrastructure/abort.js";
5
+ import { quote } from "../infrastructure/process.js";
6
+ import { cloudDefaults } from "./cloud.constants.js";
7
+ import { terminalBridge } from "./terminal-bridge.js";
8
+ export async function daytonaTerminal(runtime, command, signal) {
9
+ const { sandbox, root, options, context } = runtime;
10
+ const id = `outpost-${randomUUID()}`;
11
+ const base = `/tmp/${id}`;
12
+ const program = [
13
+ ...(command.elevated ? ["sudo", "-n", "--"] : []),
14
+ command.executable,
15
+ ...(command.arguments ?? []),
16
+ ]
17
+ .map(quote)
18
+ .join(" ");
19
+ const script = `kill -0 -$$ 2>/dev/null || exit 125
20
+ echo $$ > ${quote(base + ".pid")}
21
+ ${program}
22
+ status=$?
23
+ printf '%s' "$status" > ${quote(base + ".status")}
24
+ exit "$status"
25
+ `;
26
+ let handle;
27
+ let bridge;
28
+ let completed = false;
29
+ let creating = false;
30
+ let failure;
31
+ try {
32
+ await sandbox.fs.uploadFile(Buffer.from(script), base);
33
+ signal.throwIfAborted();
34
+ bridge = terminalBridge(command, command.retain ?? options.retain ?? cloudDefaults.retainBytes);
35
+ // createPty owns its connection timeout; await ownership before cancellation cleanup.
36
+ creating = true;
37
+ handle = await sandbox.process.createPty({
38
+ id,
39
+ cwd: command.directory ?? root,
40
+ envs: {
41
+ TERM: process.env.TERM ?? "xterm-256color",
42
+ ...context.variables,
43
+ ...command.variables,
44
+ },
45
+ ...bridge.size(),
46
+ onData: bridge.output,
47
+ });
48
+ signal.throwIfAborted();
49
+ await interruptible(handle.sendInput(`exec sh ${quote(base)}\n`), signal);
50
+ bridge.connect(handle);
51
+ if (command.stdin !== undefined)
52
+ await interruptible(handle.sendInput(command.stdin), signal);
53
+ let nativeStatus;
54
+ const nativeFailure = handle.wait().then((exit) => {
55
+ nativeStatus = exit.exitCode;
56
+ if (exit.error && exit.exitCode === undefined)
57
+ throw new OutpostError("provider", `Daytona terminal failed: ${exit.error}`);
58
+ return new Promise(() => { });
59
+ });
60
+ void nativeFailure.catch(() => undefined);
61
+ // The SDK can infer success from socket closure; the script records process completion.
62
+ while (true) {
63
+ const status = await interruptible(Promise.race([
64
+ sandbox.process.executeCommand(`if [ -f ${quote(base + ".status")} ]; then cat ${quote(base + ".status")}; else exit 3; fi`),
65
+ bridge.failure,
66
+ nativeFailure,
67
+ ]), signal);
68
+ const recorded = status.exitCode === 0 && /^\d+$/.test(status.result.trim());
69
+ if (recorded ||
70
+ (status.exitCode === 3 &&
71
+ nativeStatus !== undefined &&
72
+ nativeStatus !== 0)) {
73
+ completed = true;
74
+ await interruptible(bridge.flush(), signal);
75
+ return {
76
+ status: recorded ? Number(status.result.trim()) : nativeStatus,
77
+ stdout: bridge.text(),
78
+ stderr: "",
79
+ };
80
+ }
81
+ if (status.exitCode !== 3)
82
+ throw new OutpostError("provider", "Daytona terminal returned invalid completion status");
83
+ await Promise.race([
84
+ setTimeout(cloudDefaults.pollMs, undefined, { signal }),
85
+ bridge.failure,
86
+ nativeFailure,
87
+ ]);
88
+ }
89
+ }
90
+ catch (cause) {
91
+ failure = signal.aborted ? signal.reason : cause;
92
+ throw failure;
93
+ }
94
+ finally {
95
+ const errors = [];
96
+ const cleanup = async (operation) => {
97
+ try {
98
+ await interruptible(Promise.resolve().then(operation), AbortSignal.timeout(cloudDefaults.cancellationMs));
99
+ }
100
+ catch (cause) {
101
+ errors.push(cause);
102
+ }
103
+ };
104
+ await cleanup(() => bridge?.close());
105
+ if (!completed) {
106
+ // The native PTY already supplies a session; terminate its existing process group.
107
+ const kill = `if [ -f ${quote(base + ".pid")} ]; then p=$(cat ${quote(base + ".pid")}); kill -KILL -"$p" 2>/dev/null || true; fi`;
108
+ await cleanup(() => sandbox.process.executeCommand(command.elevated ? `sudo -n sh -c ${quote(kill)}` : kill));
109
+ if (creating)
110
+ await cleanup(async () => {
111
+ try {
112
+ if (handle)
113
+ return await handle.kill();
114
+ await sandbox.process.killPtySession(id);
115
+ }
116
+ catch (cause) {
117
+ if (!(cause instanceof Error && cause.name === "DaytonaNotFoundError"))
118
+ throw cause;
119
+ }
120
+ });
121
+ }
122
+ await cleanup(() => handle?.disconnect());
123
+ await cleanup(() => sandbox.process.executeCommand(`rm -f ${quote(base)} ${quote(base + ".pid")} ${quote(base + ".status")}`));
124
+ if (errors.length)
125
+ throw new AggregateError(failure === undefined ? errors : [failure, ...errors], "Daytona terminal cleanup failed");
126
+ }
127
+ }
128
+ //# sourceMappingURL=daytona-terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daytona-terminal.js","sourceRoot":"","sources":["../../src/providers/daytona-terminal.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { setTimeout } from \"node:timers/promises\";\nimport type { PtyHandle } from \"@daytona/sdk\";\nimport type { Command, CommandResult } from \"../domain/command.types.ts\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport { interruptible } from \"../infrastructure/abort.ts\";\nimport { quote } from \"../infrastructure/process.ts\";\nimport { cloudDefaults } from \"./cloud.constants.ts\";\nimport type { DaytonaRuntime } from \"./daytona.types.ts\";\nimport { terminalBridge } from \"./terminal-bridge.ts\";\n\nexport async function daytonaTerminal(\n runtime: DaytonaRuntime,\n command: Command,\n signal: AbortSignal,\n): Promise<CommandResult> {\n const { sandbox, root, options, context } = runtime;\n const id = `outpost-${randomUUID()}`;\n const base = `/tmp/${id}`;\n const program = [\n ...(command.elevated ? [\"sudo\", \"-n\", \"--\"] : []),\n command.executable,\n ...(command.arguments ?? []),\n ]\n .map(quote)\n .join(\" \");\n const script = `kill -0 -$$ 2>/dev/null || exit 125\necho $$ > ${quote(base + \".pid\")}\n${program}\nstatus=$?\nprintf '%s' \"$status\" > ${quote(base + \".status\")}\nexit \"$status\"\n`;\n let handle: PtyHandle | undefined;\n let bridge: ReturnType<typeof terminalBridge> | undefined;\n let completed = false;\n let creating = false;\n let failure: unknown;\n try {\n await sandbox.fs.uploadFile(Buffer.from(script), base);\n signal.throwIfAborted();\n bridge = terminalBridge(\n command,\n command.retain ?? options.retain ?? cloudDefaults.retainBytes,\n );\n // createPty owns its connection timeout; await ownership before cancellation cleanup.\n creating = true;\n handle = await sandbox.process.createPty({\n id,\n cwd: command.directory ?? root,\n envs: {\n TERM: process.env.TERM ?? \"xterm-256color\",\n ...context.variables,\n ...command.variables,\n },\n ...bridge.size(),\n onData: bridge.output,\n });\n signal.throwIfAborted();\n await interruptible(handle.sendInput(`exec sh ${quote(base)}\\n`), signal);\n bridge.connect(handle);\n if (command.stdin !== undefined)\n await interruptible(handle.sendInput(command.stdin), signal);\n let nativeStatus: number | undefined;\n const nativeFailure = handle.wait().then((exit) => {\n nativeStatus = exit.exitCode;\n if (exit.error && exit.exitCode === undefined)\n throw new OutpostError(\n \"provider\",\n `Daytona terminal failed: ${exit.error}`,\n );\n return new Promise<never>(() => {});\n });\n void nativeFailure.catch(() => undefined);\n // The SDK can infer success from socket closure; the script records process completion.\n while (true) {\n const status = await interruptible(\n Promise.race([\n sandbox.process.executeCommand(\n `if [ -f ${quote(base + \".status\")} ]; then cat ${quote(base + \".status\")}; else exit 3; fi`,\n ),\n bridge.failure,\n nativeFailure,\n ]),\n signal,\n );\n const recorded =\n status.exitCode === 0 && /^\\d+$/.test(status.result.trim());\n if (\n recorded ||\n (status.exitCode === 3 &&\n nativeStatus !== undefined &&\n nativeStatus !== 0)\n ) {\n completed = true;\n await interruptible(bridge.flush(), signal);\n return {\n status: recorded ? Number(status.result.trim()) : nativeStatus!,\n stdout: bridge.text(),\n stderr: \"\",\n };\n }\n if (status.exitCode !== 3)\n throw new OutpostError(\n \"provider\",\n \"Daytona terminal returned invalid completion status\",\n );\n await Promise.race([\n setTimeout(cloudDefaults.pollMs, undefined, { signal }),\n bridge.failure,\n nativeFailure,\n ]);\n }\n } catch (cause) {\n failure = signal.aborted ? signal.reason : cause;\n throw failure;\n } finally {\n const errors: unknown[] = [];\n const cleanup = async (operation: () => unknown) => {\n try {\n await interruptible(\n Promise.resolve().then(operation),\n AbortSignal.timeout(cloudDefaults.cancellationMs),\n );\n } catch (cause) {\n errors.push(cause);\n }\n };\n await cleanup(() => bridge?.close());\n if (!completed) {\n // The native PTY already supplies a session; terminate its existing process group.\n const kill = `if [ -f ${quote(base + \".pid\")} ]; then p=$(cat ${quote(base + \".pid\")}); kill -KILL -\"$p\" 2>/dev/null || true; fi`;\n await cleanup(() =>\n sandbox.process.executeCommand(\n command.elevated ? `sudo -n sh -c ${quote(kill)}` : kill,\n ),\n );\n if (creating)\n await cleanup(async () => {\n try {\n if (handle) return await handle.kill();\n await sandbox.process.killPtySession(id);\n } catch (cause) {\n if (!(\n cause instanceof Error && cause.name === \"DaytonaNotFoundError\"\n ))\n throw cause;\n }\n });\n }\n await cleanup(() => handle?.disconnect());\n await cleanup(() =>\n sandbox.process.executeCommand(\n `rm -f ${quote(base)} ${quote(base + \".pid\")} ${quote(base + \".status\")}`,\n ),\n );\n if (errors.length)\n throw new AggregateError(\n failure === undefined ? errors : [failure, ...errors],\n \"Daytona terminal cleanup failed\",\n );\n }\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { invariant } from "../domain/errors.js";
1
2
  import { posix } from "node:path";
2
3
  import { fileBatches } from "./file-batches.js";
3
4
  import { registerCleanup } from "../infrastructure/shutdown.js";
@@ -5,6 +6,7 @@ import { cloudRoots } from "./cloud.constants.js";
5
6
  import { daytonaCommand } from "./daytona-command.js";
6
7
  import { daytonaFiles } from "./daytona-files.js";
7
8
  export function daytona(options = {}, connect = async (config) => new (await import("@daytona/sdk")).Daytona(config)) {
9
+ invariant(!("egress" in options) || options.egress === undefined, "Daytona does not support Outpost egress policies; configure provider-native networking explicitly");
8
10
  return {
9
11
  name: "daytona",
10
12
  placement: "remote",
@@ -1 +1 @@
1
- {"version":3,"file":"daytona.js","sourceRoot":"","sources":["../../src/providers/daytona.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKlD,MAAM,UAAU,OAAO,CACrB,UAA0B,EAAE,EAC5B,UAEmD,KAAK,EAAE,MAAM,EAAE,EAAE,CAClE,IAAI,CAAC,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAEpD,OAAO;QACL,IAAI,EAAE,SAAS;QACf,SAAS,EAAE,QAAQ;QACnB,SAAS,EAAE,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE;QACnC,KAAK,CAAC,OAAO,CAAC,OAAO;YACnB,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YAC1D,IAAI,MAAM,GAAG,KAAK,EAChB,SAAoC,CAAC;YACvC,IAAI,UAAU,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;YAC1B,MAAM,OAAO,GAAG,GAAG,EAAE,CACnB,CAAC,SAAS,KAAK,MAAM;iBAClB,MAAM,CAAC,OAAO,CAAC;iBACf,IAAI,CAAC,GAAG,EAAE;gBACT,MAAM,GAAG,IAAI,CAAC;gBACd,UAAU,EAAE,CAAC;YACf,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACf,SAAS,GAAG,SAAS,CAAC;gBACtB,MAAM,KAAK,CAAC;YACd,CAAC,CAAC,CAAC,CAAC;YACR,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YACtC,IAAI,IAAY,CAAC;YACjB,IAAI,IAAY,CAAC;YACjB,IAAI,CAAC;gBACH,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,cAAc,EAAE,CAAC,IAAI,UAAU,CAAC,WAAW,CAAC;gBAClE,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;gBACnD,MAAM,OAAO,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC7C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC;oBACH,MAAM,OAAO,EAAE,CAAC;gBAClB,CAAC;gBAAC,OAAO,OAAO,EAAE,CAAC;oBACjB,MAAM,IAAI,cAAc,CACtB,CAAC,KAAK,EAAE,OAAO,CAAC,EAChB,gCAAgC,CACjC,CAAC;gBACJ,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,KAAK,GAAG;gBACZ,IAAI;gBACJ,IAAI;gBACJ,MAAM,EAAE,cAAc,CAAC;oBACrB,OAAO;oBACP,IAAI;oBACJ,OAAO;oBACP,OAAO;oBACP,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM;iBACvB,CAAC;gBACF,GAAG,YAAY,CAAC,OAAO,CAAC;gBACxB,OAAO;aACR,CAAC;YACF,OAAO,EAAE,GAAG,KAAK,EAAE,aAAa,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { Daytona, DaytonaConfig } from \"@daytona/sdk\";\nimport { posix } from \"node:path\";\nimport type { SandboxProvider } from \"../domain/sandbox.types.ts\";\nimport { fileBatches } from \"./file-batches.ts\";\nimport { registerCleanup } from \"../infrastructure/shutdown.ts\";\nimport { cloudRoots } from \"./cloud.constants.ts\";\nimport { daytonaCommand } from \"./daytona-command.ts\";\nimport { daytonaFiles } from \"./daytona-files.ts\";\nimport type { DaytonaOptions } from \"./daytona.types.ts\";\n\nexport type { DaytonaOptions } from \"./daytona.types.ts\";\n\nexport function daytona(\n options: DaytonaOptions = {},\n connect: (\n config?: DaytonaConfig,\n ) => Promise<Pick<Daytona, \"create\" | \"delete\">> = async (config) =>\n new (await import(\"@daytona/sdk\")).Daytona(config),\n): SandboxProvider {\n return {\n name: \"daytona\",\n placement: \"remote\",\n variables: { ...options.variables },\n async acquire(context) {\n context.signal?.throwIfAborted();\n const client = await connect(options.connection);\n const sandbox = await client.create(options.create ?? {});\n let closed = false,\n releasing: Promise<void> | undefined;\n let unregister = () => {};\n const release = () =>\n (releasing ??= client\n .delete(sandbox)\n .then(() => {\n closed = true;\n unregister();\n })\n .catch((error) => {\n releasing = undefined;\n throw error;\n }));\n unregister = registerCleanup(release);\n let home: string;\n let root: string;\n try {\n home = (await sandbox.getUserHomeDir()) ?? cloudRoots.daytonaHome;\n root = options.root ?? posix.join(home, \"outpost\");\n await sandbox.fs.createFolder(root, \"755\");\n } catch (cause) {\n try {\n await release();\n } catch (cleanup) {\n throw new AggregateError(\n [cause, cleanup],\n \"Cloud setup and cleanup failed\",\n );\n }\n throw cause;\n }\n const lease = {\n root,\n home,\n invoke: daytonaCommand({\n sandbox,\n root,\n options,\n context,\n isClosed: () => closed,\n }),\n ...daytonaFiles(sandbox),\n release,\n };\n return { ...lease, fileTransfers: fileBatches(lease) };\n },\n };\n}\n"]}
1
+ {"version":3,"file":"daytona.js","sourceRoot":"","sources":["../../src/providers/daytona.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Daytona, DaytonaConfig } from \"@daytona/sdk\";\nimport { invariant } from \"../domain/errors.ts\";\nimport { posix } from \"node:path\";\nimport type { SandboxProvider } from \"../domain/sandbox.types.ts\";\nimport { fileBatches } from \"./file-batches.ts\";\nimport { registerCleanup } from \"../infrastructure/shutdown.ts\";\nimport { cloudRoots } from \"./cloud.constants.ts\";\nimport { daytonaCommand } from \"./daytona-command.ts\";\nimport { daytonaFiles } from \"./daytona-files.ts\";\nimport type { DaytonaOptions } from \"./daytona.types.ts\";\n\nexport type { DaytonaOptions } from \"./daytona.types.ts\";\n\nexport function daytona(\n options: DaytonaOptions = {},\n connect: (\n config?: DaytonaConfig,\n ) => Promise<Pick<Daytona, \"create\" | \"delete\">> = async (config) =>\n new (await import(\"@daytona/sdk\")).Daytona(config),\n): SandboxProvider {\n invariant(\n !(\"egress\" in options) || options.egress === undefined,\n \"Daytona does not support Outpost egress policies; configure provider-native networking explicitly\",\n );\n return {\n name: \"daytona\",\n placement: \"remote\",\n variables: { ...options.variables },\n async acquire(context) {\n context.signal?.throwIfAborted();\n const client = await connect(options.connection);\n const sandbox = await client.create(options.create ?? {});\n let closed = false,\n releasing: Promise<void> | undefined;\n let unregister = () => {};\n const release = () =>\n (releasing ??= client\n .delete(sandbox)\n .then(() => {\n closed = true;\n unregister();\n })\n .catch((error) => {\n releasing = undefined;\n throw error;\n }));\n unregister = registerCleanup(release);\n let home: string;\n let root: string;\n try {\n home = (await sandbox.getUserHomeDir()) ?? cloudRoots.daytonaHome;\n root = options.root ?? posix.join(home, \"outpost\");\n await sandbox.fs.createFolder(root, \"755\");\n } catch (cause) {\n try {\n await release();\n } catch (cleanup) {\n throw new AggregateError(\n [cause, cleanup],\n \"Cloud setup and cleanup failed\",\n );\n }\n throw cause;\n }\n const lease = {\n root,\n home,\n invoke: daytonaCommand({\n sandbox,\n root,\n options,\n context,\n isClosed: () => closed,\n }),\n ...daytonaFiles(sandbox),\n release,\n };\n return { ...lease, fileTransfers: fileBatches(lease) };\n },\n };\n}\n"]}
@@ -2,3 +2,4 @@ import type { ContainerOptions } from "./container.types.ts";
2
2
  export type { ContainerOptions } from "./container.ts";
3
3
  export declare const docker: (options?: ContainerOptions) => import("../index.ts").SandboxProvider;
4
4
  export type { DependencyCache } from "./container-cache.types.ts";
5
+ export type { EgressPolicy } from "../domain/egress.types.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"docker.js","sourceRoot":"","sources":["../../src/providers/docker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKnD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,UAA4B,EAAE,EAAE,EAAE,CACvD,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC","sourcesContent":["import { containerProvider } from \"./container.ts\";\nimport type { ContainerOptions } from \"./container.types.ts\";\n\nexport type { ContainerOptions } from \"./container.ts\";\n\nexport const docker = (options: ContainerOptions = {}) =>\n containerProvider(\"docker\", options);\n\nexport type { DependencyCache } from \"./container-cache.types.ts\";\n"]}
1
+ {"version":3,"file":"docker.js","sourceRoot":"","sources":["../../src/providers/docker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKnD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,UAA4B,EAAE,EAAE,EAAE,CACvD,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC","sourcesContent":["import { containerProvider } from \"./container.ts\";\nimport type { ContainerOptions } from \"./container.types.ts\";\n\nexport type { ContainerOptions } from \"./container.ts\";\n\nexport const docker = (options: ContainerOptions = {}) =>\n containerProvider(\"docker\", options);\n\nexport type { DependencyCache } from \"./container-cache.types.ts\";\n\nexport type { EgressPolicy } from \"../domain/egress.types.ts\";\n"]}
@@ -1,2 +1,2 @@
1
1
  import type { FileTransfers, SandboxLease } from "../domain/sandbox.types.ts";
2
- export declare function fileBatches(lease: Pick<SandboxLease, "invoke" | "download">): FileTransfers;
2
+ export declare function fileBatches(lease: Pick<SandboxLease, "invoke" | "download"> & Partial<Pick<SandboxLease, "upload">>): FileTransfers;
@@ -8,6 +8,7 @@ import { fileManifest, parseManifest, sameFile, sameLocalFile, validateFilePaths
8
8
  import { safeDestination } from "../infrastructure/files.js";
9
9
  import { transfer } from "../infrastructure/transfer.js";
10
10
  import { fileBatchCleanupScript, fileBatchLimits, fileBatchScript, } from "./file-batches.constants.js";
11
+ import { uploadBatch } from "./file-upload.js";
11
12
  export function fileBatches(lease) {
12
13
  const run = async (args, options) => {
13
14
  const result = await lease.invoke({
@@ -21,6 +22,14 @@ export function fileBatches(lease) {
21
22
  return result.stdout;
22
23
  };
23
24
  return {
25
+ ...(lease.upload
26
+ ? {
27
+ uploadBatch: uploadBatch({
28
+ invoke: lease.invoke.bind(lease),
29
+ upload: lease.upload.bind(lease),
30
+ }),
31
+ }
32
+ : {}),
24
33
  manifest(source, paths, options = {}) {
25
34
  return transfer(options, async (signal) => {
26
35
  validateFilePaths(paths);
@@ -1 +1 @@
1
- {"version":3,"file":"file-batches.js","sourceRoot":"","sources":["../../src/providers/file-batches.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID, createHash } from \"node:crypto\";\nimport {\n chmod,\n lstat,\n mkdir,\n mkdtemp,\n readFile,\n rm,\n symlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { gunzipSync } from \"node:zlib\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport type {\n FileManifestEntry,\n FileTransfers,\n SandboxLease,\n TransferOptions,\n} from \"../domain/sandbox.types.ts\";\nimport {\n fileManifest,\n parseManifest,\n sameFile,\n sameLocalFile,\n validateFilePaths,\n} from \"../infrastructure/file-manifest.ts\";\nimport { safeDestination } from \"../infrastructure/files.ts\";\nimport { transfer } from \"../infrastructure/transfer.ts\";\nimport {\n fileBatchCleanupScript,\n fileBatchLimits,\n fileBatchScript,\n} from \"./file-batches.constants.ts\";\n\nexport function fileBatches(\n lease: Pick<SandboxLease, \"invoke\" | \"download\">,\n): FileTransfers {\n const run = async (args: readonly string[], options: TransferOptions) => {\n const result = await lease.invoke({\n executable: \"node\",\n arguments: [\"-e\", fileBatchScript, ...args],\n retain: fileBatchLimits.manifestBytes,\n ...options,\n });\n if (result.status !== 0)\n throw new OutpostError(\n \"provider\",\n \"Remote file manifest or batch failed\",\n { stderr: result.stderr },\n );\n return result.stdout;\n };\n return {\n manifest(source, paths, options = {}) {\n return transfer(options, async (signal) => {\n validateFilePaths(paths);\n const result: FileManifestEntry[] = [];\n for (let offset = 0; offset < paths.length;) {\n signal.throwIfAborted();\n const selected = paths.slice(\n offset,\n offset + fileBatchLimits.entries,\n );\n while (\n Buffer.byteLength(JSON.stringify(selected)) >\n fileBatchLimits.argumentBytes\n )\n selected.pop();\n if (!selected.length)\n throw new OutpostError(\n \"provider\",\n \"Manifest path exceeds command size limit\",\n );\n offset += selected.length;\n result.push(\n ...parseManifest(\n JSON.parse(\n await run([\"manifest\", source, JSON.stringify(selected)], {\n ...options,\n signal,\n }),\n ),\n selected,\n ),\n );\n }\n return result;\n });\n },\n downloadBatch(source, entries, destination, options = {}) {\n return transfer(options, async (signal) => {\n parseManifest(\n entries,\n entries.map((entry) => entry.path),\n );\n if (!entries.length) return;\n const staging = await mkdtemp(join(tmpdir(), \"outpost-batch-\"));\n try {\n let pending: FileManifestEntry[] = [],\n bytes = 0;\n const flush = async () => {\n if (!pending.length) return;\n const remote = `${source.replaceAll(\"\\\\\", \"/\")}/../.outpost-${randomUUID()}.json.gz`;\n try {\n await run([\"batch\", source, JSON.stringify(pending), remote], {\n ...options,\n signal,\n });\n signal.throwIfAborted();\n const archive = join(staging, \"batch.json.gz\");\n await lease.download(remote, archive, { ...options, signal });\n signal.throwIfAborted();\n await unpackBatch(archive, pending, destination, signal);\n } finally {\n await lease\n .invoke({\n executable: \"node\",\n arguments: [\"-e\", fileBatchCleanupScript, remote],\n deadlineMs: fileBatchLimits.cleanupMs,\n })\n .catch(() => undefined);\n }\n pending = [];\n bytes = 0;\n };\n for (const entry of entries) {\n signal.throwIfAborted();\n await safeDestination(destination, entry.path);\n if (entry.size > fileBatchLimits.bytes) {\n await flush();\n const target = await safeDestination(destination, entry.path);\n await lease.download(`${source}/${entry.path}`, target, {\n ...options,\n signal,\n });\n if (\n !sameLocalFile(\n entry,\n await fileManifest(destination, entry.path),\n )\n )\n throw new OutpostError(\n \"provider\",\n \"Remote file changed during transfer\",\n { path: entry.path },\n );\n continue;\n }\n if (\n pending.length >= fileBatchLimits.entries ||\n bytes + entry.size > fileBatchLimits.bytes ||\n Buffer.byteLength(JSON.stringify([...pending, entry])) >\n fileBatchLimits.argumentBytes\n )\n await flush();\n pending.push(entry);\n bytes += entry.size;\n }\n await flush();\n } finally {\n await rm(staging, { recursive: true, force: true });\n }\n });\n },\n };\n}\n\nasync function unpackBatch(\n archive: string,\n entries: readonly FileManifestEntry[],\n destination: string,\n signal: AbortSignal,\n): Promise<void> {\n const payload: unknown = JSON.parse(\n gunzipSync(await readFile(archive), {\n maxOutputLength: fileBatchLimits.decodedBytes,\n }).toString(\"utf8\"),\n );\n const manifest = parseManifest(\n payload,\n entries.map((entry) => entry.path),\n );\n if (!Array.isArray(payload))\n throw new OutpostError(\"provider\", \"Invalid file batch\");\n for (const [index, entry] of manifest.entries()) {\n signal.throwIfAborted();\n const record: unknown = payload[index];\n if (\n !record ||\n typeof record !== \"object\" ||\n !(\"data\" in record) ||\n typeof record.data !== \"string\"\n )\n throw new OutpostError(\"provider\", \"Invalid batch payload\");\n const data = Buffer.from(record.data, \"base64\");\n if (\n !sameFile(entry, entries[index]!) ||\n data.length !== entry.size ||\n createHash(\"sha256\").update(data).digest(\"hex\") !== entry.sha256\n )\n throw new OutpostError(\"provider\", \"File batch checksum mismatch\", {\n path: entry.path,\n });\n const target = await safeDestination(destination, entry.path);\n await mkdir(dirname(target), { recursive: true });\n if (\n await lstat(target).catch((error) => {\n if (error.code === \"ENOENT\") return undefined;\n throw error;\n })\n )\n throw new OutpostError(\"provider\", \"Batch destination already exists\", {\n path: entry.path,\n });\n if (entry.kind === \"link\") {\n await symlink(data.toString(\"utf8\"), target);\n continue;\n }\n await writeFile(target, data, { mode: entry.mode, flag: \"wx\" });\n await chmod(target, entry.mode);\n }\n}\n"]}
1
+ {"version":3,"file":"file-batches.js","sourceRoot":"","sources":["../../src/providers/file-batches.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID, createHash } from \"node:crypto\";\nimport {\n chmod,\n lstat,\n mkdir,\n mkdtemp,\n readFile,\n rm,\n symlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { gunzipSync } from \"node:zlib\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport type {\n FileManifestEntry,\n FileTransfers,\n SandboxLease,\n TransferOptions,\n} from \"../domain/sandbox.types.ts\";\nimport {\n fileManifest,\n parseManifest,\n sameFile,\n sameLocalFile,\n validateFilePaths,\n} from \"../infrastructure/file-manifest.ts\";\nimport { safeDestination } from \"../infrastructure/files.ts\";\nimport { transfer } from \"../infrastructure/transfer.ts\";\nimport {\n fileBatchCleanupScript,\n fileBatchLimits,\n fileBatchScript,\n} from \"./file-batches.constants.ts\";\n\nimport { uploadBatch } from \"./file-upload.ts\";\n\nexport function fileBatches(\n lease: Pick<SandboxLease, \"invoke\" | \"download\"> &\n Partial<Pick<SandboxLease, \"upload\">>,\n): FileTransfers {\n const run = async (args: readonly string[], options: TransferOptions) => {\n const result = await lease.invoke({\n executable: \"node\",\n arguments: [\"-e\", fileBatchScript, ...args],\n retain: fileBatchLimits.manifestBytes,\n ...options,\n });\n if (result.status !== 0)\n throw new OutpostError(\n \"provider\",\n \"Remote file manifest or batch failed\",\n { stderr: result.stderr },\n );\n return result.stdout;\n };\n return {\n ...(lease.upload\n ? {\n uploadBatch: uploadBatch({\n invoke: lease.invoke.bind(lease),\n upload: lease.upload.bind(lease),\n }),\n }\n : {}),\n manifest(source, paths, options = {}) {\n return transfer(options, async (signal) => {\n validateFilePaths(paths);\n const result: FileManifestEntry[] = [];\n for (let offset = 0; offset < paths.length;) {\n signal.throwIfAborted();\n const selected = paths.slice(\n offset,\n offset + fileBatchLimits.entries,\n );\n while (\n Buffer.byteLength(JSON.stringify(selected)) >\n fileBatchLimits.argumentBytes\n )\n selected.pop();\n if (!selected.length)\n throw new OutpostError(\n \"provider\",\n \"Manifest path exceeds command size limit\",\n );\n offset += selected.length;\n result.push(\n ...parseManifest(\n JSON.parse(\n await run([\"manifest\", source, JSON.stringify(selected)], {\n ...options,\n signal,\n }),\n ),\n selected,\n ),\n );\n }\n return result;\n });\n },\n downloadBatch(source, entries, destination, options = {}) {\n return transfer(options, async (signal) => {\n parseManifest(\n entries,\n entries.map((entry) => entry.path),\n );\n if (!entries.length) return;\n const staging = await mkdtemp(join(tmpdir(), \"outpost-batch-\"));\n try {\n let pending: FileManifestEntry[] = [],\n bytes = 0;\n const flush = async () => {\n if (!pending.length) return;\n const remote = `${source.replaceAll(\"\\\\\", \"/\")}/../.outpost-${randomUUID()}.json.gz`;\n try {\n await run([\"batch\", source, JSON.stringify(pending), remote], {\n ...options,\n signal,\n });\n signal.throwIfAborted();\n const archive = join(staging, \"batch.json.gz\");\n await lease.download(remote, archive, { ...options, signal });\n signal.throwIfAborted();\n await unpackBatch(archive, pending, destination, signal);\n } finally {\n await lease\n .invoke({\n executable: \"node\",\n arguments: [\"-e\", fileBatchCleanupScript, remote],\n deadlineMs: fileBatchLimits.cleanupMs,\n })\n .catch(() => undefined);\n }\n pending = [];\n bytes = 0;\n };\n for (const entry of entries) {\n signal.throwIfAborted();\n await safeDestination(destination, entry.path);\n if (entry.size > fileBatchLimits.bytes) {\n await flush();\n const target = await safeDestination(destination, entry.path);\n await lease.download(`${source}/${entry.path}`, target, {\n ...options,\n signal,\n });\n if (\n !sameLocalFile(\n entry,\n await fileManifest(destination, entry.path),\n )\n )\n throw new OutpostError(\n \"provider\",\n \"Remote file changed during transfer\",\n { path: entry.path },\n );\n continue;\n }\n if (\n pending.length >= fileBatchLimits.entries ||\n bytes + entry.size > fileBatchLimits.bytes ||\n Buffer.byteLength(JSON.stringify([...pending, entry])) >\n fileBatchLimits.argumentBytes\n )\n await flush();\n pending.push(entry);\n bytes += entry.size;\n }\n await flush();\n } finally {\n await rm(staging, { recursive: true, force: true });\n }\n });\n },\n };\n}\n\nasync function unpackBatch(\n archive: string,\n entries: readonly FileManifestEntry[],\n destination: string,\n signal: AbortSignal,\n): Promise<void> {\n const payload: unknown = JSON.parse(\n gunzipSync(await readFile(archive), {\n maxOutputLength: fileBatchLimits.decodedBytes,\n }).toString(\"utf8\"),\n );\n const manifest = parseManifest(\n payload,\n entries.map((entry) => entry.path),\n );\n if (!Array.isArray(payload))\n throw new OutpostError(\"provider\", \"Invalid file batch\");\n for (const [index, entry] of manifest.entries()) {\n signal.throwIfAborted();\n const record: unknown = payload[index];\n if (\n !record ||\n typeof record !== \"object\" ||\n !(\"data\" in record) ||\n typeof record.data !== \"string\"\n )\n throw new OutpostError(\"provider\", \"Invalid batch payload\");\n const data = Buffer.from(record.data, \"base64\");\n if (\n !sameFile(entry, entries[index]!) ||\n data.length !== entry.size ||\n createHash(\"sha256\").update(data).digest(\"hex\") !== entry.sha256\n )\n throw new OutpostError(\"provider\", \"File batch checksum mismatch\", {\n path: entry.path,\n });\n const target = await safeDestination(destination, entry.path);\n await mkdir(dirname(target), { recursive: true });\n if (\n await lstat(target).catch((error) => {\n if (error.code === \"ENOENT\") return undefined;\n throw error;\n })\n )\n throw new OutpostError(\"provider\", \"Batch destination already exists\", {\n path: entry.path,\n });\n if (entry.kind === \"link\") {\n await symlink(data.toString(\"utf8\"), target);\n continue;\n }\n await writeFile(target, data, { mode: entry.mode, flag: \"wx\" });\n await chmod(target, entry.mode);\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ export declare const fileUploadScript: string;
@@ -0,0 +1,68 @@
1
+ export const fileUploadScript = String.raw `
2
+ const f = require('node:fs'), p = require('node:path'), c = require('node:crypto'), z = require('node:zlib');
3
+ const [operation, root, input, staging] = process.argv.slice(1);
4
+ const keys = ['path', 'kind', 'mode', 'size', 'sha256'];
5
+ function safe(path) {
6
+ if (!path || p.isAbsolute(path) || path.includes('\\') || path.includes('\0') || path.split('/').some(x => !x || x === '.' || x === '..' || x.toLowerCase() === '.git')) throw Error('Unsafe upload path');
7
+ const target = p.resolve(root, path);
8
+ let parent = p.dirname(target);
9
+ while (true) {
10
+ let stat;
11
+ try { stat = f.lstatSync(parent); } catch (error) { if (error.code !== 'ENOENT') throw error; }
12
+ if (stat && (!stat.isDirectory() || stat.isSymbolicLink())) throw Error('Upload path traverses non-directory');
13
+ if (parent === p.resolve(root)) break;
14
+ parent = p.dirname(parent);
15
+ }
16
+ return target;
17
+ }
18
+ async function inspect(target, path) {
19
+ const stat = f.lstatSync(target), hash = c.createHash('sha256');
20
+ if (!stat.isFile() && !stat.isSymbolicLink()) throw Error('Unsupported upload destination');
21
+ let size = stat.size;
22
+ if (stat.isSymbolicLink()) { const data = Buffer.from(f.readlinkSync(target)); size = data.length; hash.update(data); }
23
+ else for await (const chunk of f.createReadStream(target)) hash.update(chunk);
24
+ return { path, kind: stat.isSymbolicLink() ? 'link' : 'file', mode: stat.mode & 511, size, sha256: hash.digest('hex') };
25
+ }
26
+ function same(left, right) { return keys.every(key => left[key] === right[key]); }
27
+ (async () => {
28
+ if (operation === 'cleanup') { f.rmSync(input, { recursive: true, force: true }); return; }
29
+ if (operation === 'stage') { f.mkdirSync(input, { mode: 448 }); process.stdout.write(input); return; }
30
+ const entries = JSON.parse(input);
31
+ if (operation === 'missing') {
32
+ const missing = [];
33
+ for (const entry of entries) {
34
+ const target = safe(entry.path);
35
+ let actual;
36
+ try { actual = await inspect(target, entry.path); } catch (error) { if (error.code !== 'ENOENT') throw error; }
37
+ if (!actual || !same(actual, entry)) missing.push(entry.path);
38
+ }
39
+ process.stdout.write(JSON.stringify(missing)); return;
40
+ }
41
+ const records = operation === 'batch' ? JSON.parse(z.gunzipSync(f.readFileSync(p.join(staging, 'payload')), { maxOutputLength: 16777216 }).toString('utf8')) : undefined;
42
+ if (records && (!Array.isArray(records) || records.length !== entries.length)) throw Error('Invalid upload batch');
43
+ for (const [index, entry] of entries.entries()) {
44
+ safe(entry.path);
45
+ const temporary = p.join(staging, 'entry-' + index);
46
+ if (records) {
47
+ const record = records[index];
48
+ if (!record || !same(record, entry) || typeof record.data !== 'string') throw Error('Invalid upload batch');
49
+ const data = Buffer.from(record.data, 'base64');
50
+ if (data.length !== entry.size || c.createHash('sha256').update(data).digest('hex') !== entry.sha256) throw Error('Upload checksum mismatch');
51
+ if (entry.kind === 'link') f.symlinkSync(data.toString('utf8'), temporary);
52
+ else { f.writeFileSync(temporary, data, { flag: 'wx', mode: entry.mode }); f.chmodSync(temporary, entry.mode); }
53
+ } else {
54
+ if (entry.kind !== 'file') throw Error('Invalid large upload');
55
+ const actual = await inspect(p.join(staging, 'payload'), entry.path);
56
+ if (actual.kind !== entry.kind || actual.size !== entry.size || actual.sha256 !== entry.sha256) throw Error('Upload checksum mismatch');
57
+ f.renameSync(p.join(staging, 'payload'), temporary); f.chmodSync(temporary, entry.mode);
58
+ }
59
+ }
60
+ for (const [index, entry] of entries.entries()) {
61
+ const target = safe(entry.path);
62
+ f.mkdirSync(p.dirname(target), { recursive: true });
63
+ f.renameSync(p.join(staging, 'entry-' + index), target);
64
+ if (!same(await inspect(target, entry.path), entry)) throw Error('Upload verification failed');
65
+ }
66
+ })().catch(error => { console.error(error.message); process.exitCode = 1; });
67
+ `;
68
+ //# sourceMappingURL=file-upload.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-upload.constants.js","sourceRoot":"","sources":["../../src/providers/file-upload.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkEzC,CAAC","sourcesContent":["export const fileUploadScript = String.raw`\nconst f = require('node:fs'), p = require('node:path'), c = require('node:crypto'), z = require('node:zlib');\nconst [operation, root, input, staging] = process.argv.slice(1);\nconst keys = ['path', 'kind', 'mode', 'size', 'sha256'];\nfunction safe(path) {\n if (!path || p.isAbsolute(path) || path.includes('\\\\') || path.includes('\\0') || path.split('/').some(x => !x || x === '.' || x === '..' || x.toLowerCase() === '.git')) throw Error('Unsafe upload path');\n const target = p.resolve(root, path);\n let parent = p.dirname(target);\n while (true) {\n let stat;\n try { stat = f.lstatSync(parent); } catch (error) { if (error.code !== 'ENOENT') throw error; }\n if (stat && (!stat.isDirectory() || stat.isSymbolicLink())) throw Error('Upload path traverses non-directory');\n if (parent === p.resolve(root)) break;\n parent = p.dirname(parent);\n }\n return target;\n}\nasync function inspect(target, path) {\n const stat = f.lstatSync(target), hash = c.createHash('sha256');\n if (!stat.isFile() && !stat.isSymbolicLink()) throw Error('Unsupported upload destination');\n let size = stat.size;\n if (stat.isSymbolicLink()) { const data = Buffer.from(f.readlinkSync(target)); size = data.length; hash.update(data); }\n else for await (const chunk of f.createReadStream(target)) hash.update(chunk);\n return { path, kind: stat.isSymbolicLink() ? 'link' : 'file', mode: stat.mode & 511, size, sha256: hash.digest('hex') };\n}\nfunction same(left, right) { return keys.every(key => left[key] === right[key]); }\n(async () => {\n if (operation === 'cleanup') { f.rmSync(input, { recursive: true, force: true }); return; }\n if (operation === 'stage') { f.mkdirSync(input, { mode: 448 }); process.stdout.write(input); return; }\n const entries = JSON.parse(input);\n if (operation === 'missing') {\n const missing = [];\n for (const entry of entries) {\n const target = safe(entry.path);\n let actual;\n try { actual = await inspect(target, entry.path); } catch (error) { if (error.code !== 'ENOENT') throw error; }\n if (!actual || !same(actual, entry)) missing.push(entry.path);\n }\n process.stdout.write(JSON.stringify(missing)); return;\n }\n const records = operation === 'batch' ? JSON.parse(z.gunzipSync(f.readFileSync(p.join(staging, 'payload')), { maxOutputLength: 16777216 }).toString('utf8')) : undefined;\n if (records && (!Array.isArray(records) || records.length !== entries.length)) throw Error('Invalid upload batch');\n for (const [index, entry] of entries.entries()) {\n safe(entry.path);\n const temporary = p.join(staging, 'entry-' + index);\n if (records) {\n const record = records[index];\n if (!record || !same(record, entry) || typeof record.data !== 'string') throw Error('Invalid upload batch');\n const data = Buffer.from(record.data, 'base64');\n if (data.length !== entry.size || c.createHash('sha256').update(data).digest('hex') !== entry.sha256) throw Error('Upload checksum mismatch');\n if (entry.kind === 'link') f.symlinkSync(data.toString('utf8'), temporary);\n else { f.writeFileSync(temporary, data, { flag: 'wx', mode: entry.mode }); f.chmodSync(temporary, entry.mode); }\n } else {\n if (entry.kind !== 'file') throw Error('Invalid large upload');\n const actual = await inspect(p.join(staging, 'payload'), entry.path);\n if (actual.kind !== entry.kind || actual.size !== entry.size || actual.sha256 !== entry.sha256) throw Error('Upload checksum mismatch');\n f.renameSync(p.join(staging, 'payload'), temporary); f.chmodSync(temporary, entry.mode);\n }\n }\n for (const [index, entry] of entries.entries()) {\n const target = safe(entry.path);\n f.mkdirSync(p.dirname(target), { recursive: true });\n f.renameSync(p.join(staging, 'entry-' + index), target);\n if (!same(await inspect(target, entry.path), entry)) throw Error('Upload verification failed');\n }\n})().catch(error => { console.error(error.message); process.exitCode = 1; });\n`;\n"]}
@@ -0,0 +1,2 @@
1
+ import type { FileTransfers, SandboxLease } from "../domain/sandbox.types.ts";
2
+ export declare function uploadBatch(lease: Pick<SandboxLease, "invoke" | "upload">): NonNullable<FileTransfers["uploadBatch"]>;
@@ -0,0 +1,146 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { copyFile, mkdtemp, open, readlink, rm, writeFile, } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { gzipSync } from "node:zlib";
6
+ import { OutpostError } from "../domain/errors.js";
7
+ import { fileManifest, parseManifest, sameFile, } from "../infrastructure/file-manifest.js";
8
+ import { inspectionFileFlags } from "../infrastructure/inspection-file.constants.js";
9
+ import { safeDestination } from "../infrastructure/files.js";
10
+ import { transfer } from "../infrastructure/transfer.js";
11
+ import { fileBatchLimits } from "./file-batches.constants.js";
12
+ import { fileUploadScript } from "./file-upload.constants.js";
13
+ export function uploadBatch(lease) {
14
+ return (source, entries, destination, options = {}) => transfer(options, async (signal) => {
15
+ parseManifest(entries, entries.map((entry) => entry.path));
16
+ const run = async (operation, input, staging = "", controls = { ...options, signal }) => {
17
+ const result = await lease.invoke({
18
+ executable: "node",
19
+ arguments: [
20
+ "-e",
21
+ fileUploadScript,
22
+ operation,
23
+ destination,
24
+ input,
25
+ staging,
26
+ ],
27
+ retain: fileBatchLimits.manifestBytes,
28
+ ...controls,
29
+ });
30
+ if (result.status !== 0)
31
+ throw new OutpostError("provider", "Remote file upload failed", {
32
+ stderr: result.stderr,
33
+ });
34
+ return result.stdout;
35
+ };
36
+ const staging = await mkdtemp(join(tmpdir(), "outpost-upload-"));
37
+ try {
38
+ let pending = [], bytes = 0;
39
+ const flush = async () => {
40
+ if (!pending.length)
41
+ return;
42
+ signal.throwIfAborted();
43
+ for (const entry of pending) {
44
+ if (!sameFile(entry, await fileManifest(source, entry.path, signal)))
45
+ throw new OutpostError("provider", "Upload source changed", {
46
+ path: entry.path,
47
+ });
48
+ }
49
+ const missing = JSON.parse(await run("missing", JSON.stringify(pending)));
50
+ if (!Array.isArray(missing) ||
51
+ missing.some((path) => typeof path !== "string" ||
52
+ !pending.some((entry) => entry.path === path)) ||
53
+ new Set(missing).size !== missing.length)
54
+ throw new OutpostError("provider", "Invalid destination upload manifest");
55
+ const selected = pending.filter((entry) => missing.includes(entry.path));
56
+ if (selected.length) {
57
+ const remote = `${destination.replaceAll("\\", "/").replace(/\/$/, "")}/.outpost-upload-${randomUUID()}`;
58
+ try {
59
+ if ((await run("stage", remote)) !== remote)
60
+ throw new OutpostError("provider", "Invalid remote upload staging path");
61
+ const payload = join(staging, "payload");
62
+ await rm(payload, { force: true });
63
+ const large = selected[0].size > fileBatchLimits.bytes;
64
+ if (large) {
65
+ const entry = selected[0];
66
+ await copyFile(await safeDestination(source, entry.path), payload);
67
+ if (!sameFile({ ...entry, path: "payload" }, await fileManifest(staging, "payload", signal)))
68
+ throw new OutpostError("provider", "Upload source changed", {
69
+ path: entry.path,
70
+ });
71
+ }
72
+ else {
73
+ const records = [];
74
+ for (const entry of selected) {
75
+ signal.throwIfAborted();
76
+ const path = await safeDestination(source, entry.path);
77
+ const data = entry.kind === "link"
78
+ ? Buffer.from(await readlink(path))
79
+ : await readPayload(path, entry.size, signal);
80
+ if (data.length !== entry.size ||
81
+ createHash("sha256").update(data).digest("hex") !==
82
+ entry.sha256 ||
83
+ !sameFile(entry, await fileManifest(source, entry.path, signal)))
84
+ throw new OutpostError("provider", "Upload source changed", { path: entry.path });
85
+ records.push({ ...entry, data: data.toString("base64") });
86
+ }
87
+ await writeFile(payload, gzipSync(Buffer.from(JSON.stringify(records))), { mode: 0o600 });
88
+ }
89
+ signal.throwIfAborted();
90
+ await lease.upload(payload, `${remote}/payload`, {
91
+ ...options,
92
+ signal,
93
+ });
94
+ signal.throwIfAborted();
95
+ await run(large ? "large" : "batch", JSON.stringify(selected), remote);
96
+ }
97
+ finally {
98
+ await run("cleanup", remote, "", {
99
+ deadlineMs: fileBatchLimits.cleanupMs,
100
+ }).catch(() => undefined);
101
+ }
102
+ }
103
+ for (const entry of pending) {
104
+ if (!sameFile(entry, await fileManifest(source, entry.path, signal)))
105
+ throw new OutpostError("provider", "Upload source changed", {
106
+ path: entry.path,
107
+ });
108
+ }
109
+ signal.throwIfAborted();
110
+ pending = [];
111
+ bytes = 0;
112
+ };
113
+ for (const entry of entries) {
114
+ if (Buffer.byteLength(JSON.stringify([entry])) >
115
+ fileBatchLimits.argumentBytes)
116
+ throw new OutpostError("provider", "Upload path exceeds command size limit");
117
+ if (pending.length >= fileBatchLimits.entries ||
118
+ bytes + entry.size > fileBatchLimits.bytes ||
119
+ Buffer.byteLength(JSON.stringify([...pending, entry])) >
120
+ fileBatchLimits.argumentBytes)
121
+ await flush();
122
+ pending.push(entry);
123
+ bytes += entry.size;
124
+ if (entry.size > fileBatchLimits.bytes)
125
+ await flush();
126
+ }
127
+ await flush();
128
+ }
129
+ finally {
130
+ await rm(staging, { recursive: true, force: true });
131
+ }
132
+ });
133
+ }
134
+ async function readPayload(path, size, signal) {
135
+ const chunks = [];
136
+ let bytes = 0;
137
+ const file = await open(path, inspectionFileFlags);
138
+ for await (const chunk of file.createReadStream({ signal })) {
139
+ bytes += chunk.length;
140
+ if (bytes > size)
141
+ throw new OutpostError("provider", "Upload source changed", { path });
142
+ chunks.push(chunk);
143
+ }
144
+ return Buffer.concat(chunks);
145
+ }
146
+ //# sourceMappingURL=file-upload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-upload.js","sourceRoot":"","sources":["../../src/providers/file-upload.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport {\n copyFile,\n mkdtemp,\n open,\n readlink,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { gzipSync } from \"node:zlib\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport type {\n FileManifestEntry,\n FileTransfers,\n SandboxLease,\n TransferOptions,\n} from \"../domain/sandbox.types.ts\";\nimport {\n fileManifest,\n parseManifest,\n sameFile,\n} from \"../infrastructure/file-manifest.ts\";\nimport { inspectionFileFlags } from \"../infrastructure/inspection-file.constants.ts\";\nimport { safeDestination } from \"../infrastructure/files.ts\";\nimport { transfer } from \"../infrastructure/transfer.ts\";\nimport { fileBatchLimits } from \"./file-batches.constants.ts\";\nimport { fileUploadScript } from \"./file-upload.constants.ts\";\n\nexport function uploadBatch(\n lease: Pick<SandboxLease, \"invoke\" | \"upload\">,\n): NonNullable<FileTransfers[\"uploadBatch\"]> {\n return (source, entries, destination, options = {}) =>\n transfer(options, async (signal) => {\n parseManifest(\n entries,\n entries.map((entry) => entry.path),\n );\n const run = async (\n operation: string,\n input: string,\n staging = \"\",\n controls: TransferOptions = { ...options, signal },\n ) => {\n const result = await lease.invoke({\n executable: \"node\",\n arguments: [\n \"-e\",\n fileUploadScript,\n operation,\n destination,\n input,\n staging,\n ],\n retain: fileBatchLimits.manifestBytes,\n ...controls,\n });\n if (result.status !== 0)\n throw new OutpostError(\"provider\", \"Remote file upload failed\", {\n stderr: result.stderr,\n });\n return result.stdout;\n };\n const staging = await mkdtemp(join(tmpdir(), \"outpost-upload-\"));\n try {\n let pending: FileManifestEntry[] = [],\n bytes = 0;\n const flush = async () => {\n if (!pending.length) return;\n signal.throwIfAborted();\n for (const entry of pending) {\n if (\n !sameFile(entry, await fileManifest(source, entry.path, signal))\n )\n throw new OutpostError(\"provider\", \"Upload source changed\", {\n path: entry.path,\n });\n }\n const missing: unknown = JSON.parse(\n await run(\"missing\", JSON.stringify(pending)),\n );\n if (\n !Array.isArray(missing) ||\n missing.some(\n (path) =>\n typeof path !== \"string\" ||\n !pending.some((entry) => entry.path === path),\n ) ||\n new Set(missing).size !== missing.length\n )\n throw new OutpostError(\n \"provider\",\n \"Invalid destination upload manifest\",\n );\n const selected = pending.filter((entry) =>\n missing.includes(entry.path),\n );\n if (selected.length) {\n const remote = `${destination.replaceAll(\"\\\\\", \"/\").replace(/\\/$/, \"\")}/.outpost-upload-${randomUUID()}`;\n try {\n if ((await run(\"stage\", remote)) !== remote)\n throw new OutpostError(\n \"provider\",\n \"Invalid remote upload staging path\",\n );\n const payload = join(staging, \"payload\");\n await rm(payload, { force: true });\n const large = selected[0]!.size > fileBatchLimits.bytes;\n if (large) {\n const entry = selected[0]!;\n await copyFile(\n await safeDestination(source, entry.path),\n payload,\n );\n if (\n !sameFile(\n { ...entry, path: \"payload\" },\n await fileManifest(staging, \"payload\", signal),\n )\n )\n throw new OutpostError(\"provider\", \"Upload source changed\", {\n path: entry.path,\n });\n } else {\n const records = [];\n for (const entry of selected) {\n signal.throwIfAborted();\n const path = await safeDestination(source, entry.path);\n const data =\n entry.kind === \"link\"\n ? Buffer.from(await readlink(path))\n : await readPayload(path, entry.size, signal);\n if (\n data.length !== entry.size ||\n createHash(\"sha256\").update(data).digest(\"hex\") !==\n entry.sha256 ||\n !sameFile(\n entry,\n await fileManifest(source, entry.path, signal),\n )\n )\n throw new OutpostError(\n \"provider\",\n \"Upload source changed\",\n { path: entry.path },\n );\n records.push({ ...entry, data: data.toString(\"base64\") });\n }\n await writeFile(\n payload,\n gzipSync(Buffer.from(JSON.stringify(records))),\n { mode: 0o600 },\n );\n }\n signal.throwIfAborted();\n await lease.upload(payload, `${remote}/payload`, {\n ...options,\n signal,\n });\n signal.throwIfAborted();\n await run(\n large ? \"large\" : \"batch\",\n JSON.stringify(selected),\n remote,\n );\n } finally {\n await run(\"cleanup\", remote, \"\", {\n deadlineMs: fileBatchLimits.cleanupMs,\n }).catch(() => undefined);\n }\n }\n for (const entry of pending) {\n if (\n !sameFile(entry, await fileManifest(source, entry.path, signal))\n )\n throw new OutpostError(\"provider\", \"Upload source changed\", {\n path: entry.path,\n });\n }\n signal.throwIfAborted();\n pending = [];\n bytes = 0;\n };\n for (const entry of entries) {\n if (\n Buffer.byteLength(JSON.stringify([entry])) >\n fileBatchLimits.argumentBytes\n )\n throw new OutpostError(\n \"provider\",\n \"Upload path exceeds command size limit\",\n );\n if (\n pending.length >= fileBatchLimits.entries ||\n bytes + entry.size > fileBatchLimits.bytes ||\n Buffer.byteLength(JSON.stringify([...pending, entry])) >\n fileBatchLimits.argumentBytes\n )\n await flush();\n pending.push(entry);\n bytes += entry.size;\n if (entry.size > fileBatchLimits.bytes) await flush();\n }\n await flush();\n } finally {\n await rm(staging, { recursive: true, force: true });\n }\n });\n}\n\nasync function readPayload(\n path: string,\n size: number,\n signal: AbortSignal,\n): Promise<Buffer> {\n const chunks: Buffer[] = [];\n let bytes = 0;\n const file = await open(path, inspectionFileFlags);\n for await (const chunk of file.createReadStream({ signal })) {\n bytes += chunk.length;\n if (bytes > size)\n throw new OutpostError(\"provider\", \"Upload source changed\", { path });\n chunks.push(chunk);\n }\n return Buffer.concat(chunks);\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import type { Command } from "../domain/command.types.ts";
2
+ import type { SandboxLease } from "../domain/sandbox.types.ts";
3
+ import type { FirecrackerOptions, FirecrackerRuntime } from "./firecracker.types.ts";
4
+ export declare function firecrackerSsh(options: FirecrackerOptions, script: string): Command;
5
+ export declare function firecrackerCommand(runtime: FirecrackerRuntime): SandboxLease["invoke"];