@elie-laloum/outpost 11.1.3 → 11.2.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 (596) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +1 -0
  3. package/SECURITY.md +5 -1
  4. package/dist/adapters/agents/antigravity/antigravity-adapter.js +9 -0
  5. package/dist/adapters/agents/antigravity/antigravity-adapter.js.map +1 -1
  6. package/dist/adapters/agents/antigravity/antigravity-hook-plan.d.ts +3 -0
  7. package/dist/adapters/agents/antigravity/antigravity-hook-plan.js +39 -0
  8. package/dist/adapters/agents/antigravity/antigravity-hook-plan.js.map +1 -0
  9. package/dist/adapters/agents/antigravity/antigravity-hooks.constants.d.ts +3 -0
  10. package/dist/adapters/agents/antigravity/antigravity-hooks.constants.js +394 -0
  11. package/dist/adapters/agents/antigravity/antigravity-hooks.constants.js.map +1 -0
  12. package/dist/adapters/agents/antigravity/antigravity-hooks.d.ts +2 -0
  13. package/dist/adapters/agents/antigravity/antigravity-hooks.js +6 -0
  14. package/dist/adapters/agents/antigravity/antigravity-hooks.js.map +1 -0
  15. package/dist/adapters/agents/antigravity/antigravity-hooks.types.d.ts +114 -0
  16. package/dist/adapters/agents/antigravity/antigravity-hooks.types.js +2 -0
  17. package/dist/adapters/agents/antigravity/antigravity-hooks.types.js.map +1 -0
  18. package/dist/adapters/agents/antigravity/antigravity.types.d.ts +1 -0
  19. package/dist/adapters/agents/antigravity/antigravity.types.js.map +1 -1
  20. package/dist/adapters/agents/authentication.js +1 -0
  21. package/dist/adapters/agents/authentication.js.map +1 -1
  22. package/dist/adapters/agents/claude/claude-adapter.js +15 -0
  23. package/dist/adapters/agents/claude/claude-adapter.js.map +1 -1
  24. package/dist/adapters/agents/claude/claude-hook-plan.constants.d.ts +1 -0
  25. package/dist/adapters/agents/claude/claude-hook-plan.constants.js +20 -0
  26. package/dist/adapters/agents/claude/claude-hook-plan.constants.js.map +1 -0
  27. package/dist/adapters/agents/claude/claude-hook-plan.d.ts +4 -0
  28. package/dist/adapters/agents/claude/claude-hook-plan.js +60 -0
  29. package/dist/adapters/agents/claude/claude-hook-plan.js.map +1 -0
  30. package/dist/adapters/agents/claude/claude-hooks.constants.d.ts +3 -0
  31. package/dist/adapters/agents/claude/claude-hooks.constants.js +2968 -0
  32. package/dist/adapters/agents/claude/claude-hooks.constants.js.map +1 -0
  33. package/dist/adapters/agents/claude/claude-hooks.d.ts +2 -0
  34. package/dist/adapters/agents/claude/claude-hooks.js +6 -0
  35. package/dist/adapters/agents/claude/claude-hooks.js.map +1 -0
  36. package/dist/adapters/agents/claude/claude-hooks.types.d.ts +900 -0
  37. package/dist/adapters/agents/claude/claude-hooks.types.js +2 -0
  38. package/dist/adapters/agents/claude/claude-hooks.types.js.map +1 -0
  39. package/dist/adapters/agents/claude/claude-profile.d.ts +1 -0
  40. package/dist/adapters/agents/claude/claude-profile.js +23 -11
  41. package/dist/adapters/agents/claude/claude-profile.js.map +1 -1
  42. package/dist/adapters/agents/codex/codex-adapter.js +17 -1
  43. package/dist/adapters/agents/codex/codex-adapter.js.map +1 -1
  44. package/dist/adapters/agents/codex/codex-authentication.js +1 -0
  45. package/dist/adapters/agents/codex/codex-authentication.js.map +1 -1
  46. package/dist/adapters/agents/codex/codex-conversations.constants.d.ts +1 -0
  47. package/dist/adapters/agents/codex/codex-conversations.constants.js +2 -0
  48. package/dist/adapters/agents/codex/codex-conversations.constants.js.map +1 -0
  49. package/dist/adapters/agents/codex/codex-conversations.js +8 -5
  50. package/dist/adapters/agents/codex/codex-conversations.js.map +1 -1
  51. package/dist/adapters/agents/codex/codex-hook-plan.d.ts +3 -0
  52. package/dist/adapters/agents/codex/codex-hook-plan.js +72 -0
  53. package/dist/adapters/agents/codex/codex-hook-plan.js.map +1 -0
  54. package/dist/adapters/agents/codex/codex-hooks.constants.d.ts +3 -0
  55. package/dist/adapters/agents/codex/codex-hooks.constants.js +942 -0
  56. package/dist/adapters/agents/codex/codex-hooks.constants.js.map +1 -0
  57. package/dist/adapters/agents/codex/codex-hooks.d.ts +2 -0
  58. package/dist/adapters/agents/codex/codex-hooks.js +6 -0
  59. package/dist/adapters/agents/codex/codex-hooks.js.map +1 -0
  60. package/dist/adapters/agents/codex/codex-hooks.types.d.ts +255 -0
  61. package/dist/adapters/agents/codex/codex-hooks.types.js +2 -0
  62. package/dist/adapters/agents/codex/codex-hooks.types.js.map +1 -0
  63. package/dist/adapters/agents/codex/codex-provider.js +2 -2
  64. package/dist/adapters/agents/codex/codex-provider.js.map +1 -1
  65. package/dist/adapters/agents/copilot/copilot-adapter.js +14 -0
  66. package/dist/adapters/agents/copilot/copilot-adapter.js.map +1 -1
  67. package/dist/adapters/agents/copilot/copilot-hook-plan.d.ts +3 -0
  68. package/dist/adapters/agents/copilot/copilot-hook-plan.js +26 -0
  69. package/dist/adapters/agents/copilot/copilot-hook-plan.js.map +1 -0
  70. package/dist/adapters/agents/copilot/copilot-hooks.constants.d.ts +3 -0
  71. package/dist/adapters/agents/copilot/copilot-hooks.constants.js +528 -0
  72. package/dist/adapters/agents/copilot/copilot-hooks.constants.js.map +1 -0
  73. package/dist/adapters/agents/copilot/copilot-hooks.d.ts +2 -0
  74. package/dist/adapters/agents/copilot/copilot-hooks.js +6 -0
  75. package/dist/adapters/agents/copilot/copilot-hooks.js.map +1 -0
  76. package/dist/adapters/agents/copilot/copilot-hooks.types.d.ts +166 -0
  77. package/dist/adapters/agents/copilot/copilot-hooks.types.js +2 -0
  78. package/dist/adapters/agents/copilot/copilot-hooks.types.js.map +1 -0
  79. package/dist/adapters/agents/copilot/copilot.types.d.ts +1 -0
  80. package/dist/adapters/agents/copilot/copilot.types.js.map +1 -1
  81. package/dist/adapters/agents/hook-groups.d.ts +2 -0
  82. package/dist/adapters/agents/hook-groups.js +17 -0
  83. package/dist/adapters/agents/hook-groups.js.map +1 -0
  84. package/dist/adapters/agents/kimi/kimi-adapter.js +16 -1
  85. package/dist/adapters/agents/kimi/kimi-adapter.js.map +1 -1
  86. package/dist/adapters/agents/kimi/kimi-hook-plan.d.ts +3 -0
  87. package/dist/adapters/agents/kimi/kimi-hook-plan.js +33 -0
  88. package/dist/adapters/agents/kimi/kimi-hook-plan.js.map +1 -0
  89. package/dist/adapters/agents/kimi/kimi-hooks.constants.d.ts +3 -0
  90. package/dist/adapters/agents/kimi/kimi-hooks.constants.js +747 -0
  91. package/dist/adapters/agents/kimi/kimi-hooks.constants.js.map +1 -0
  92. package/dist/adapters/agents/kimi/kimi-hooks.d.ts +2 -0
  93. package/dist/adapters/agents/kimi/kimi-hooks.js +6 -0
  94. package/dist/adapters/agents/kimi/kimi-hooks.js.map +1 -0
  95. package/dist/adapters/agents/kimi/kimi-hooks.types.d.ts +226 -0
  96. package/dist/adapters/agents/kimi/kimi-hooks.types.js +2 -0
  97. package/dist/adapters/agents/kimi/kimi-hooks.types.js.map +1 -0
  98. package/dist/adapters/agents/kimi/kimi-request.js +2 -0
  99. package/dist/adapters/agents/kimi/kimi-request.js.map +1 -1
  100. package/dist/adapters/agents/kimi/kimi.constants.d.ts +1 -0
  101. package/dist/adapters/agents/kimi/kimi.constants.js +1 -0
  102. package/dist/adapters/agents/kimi/kimi.constants.js.map +1 -1
  103. package/dist/adapters/agents/kimi/kimi.types.d.ts +1 -0
  104. package/dist/adapters/agents/kimi/kimi.types.js.map +1 -1
  105. package/dist/adapters/agents/native-hooks.d.ts +4 -0
  106. package/dist/adapters/agents/native-hooks.js +63 -0
  107. package/dist/adapters/agents/native-hooks.js.map +1 -0
  108. package/dist/adapters/agents/native-hooks.types.d.ts +22 -0
  109. package/dist/adapters/agents/native-hooks.types.js +2 -0
  110. package/dist/adapters/agents/native-hooks.types.js.map +1 -0
  111. package/dist/adapters/agents/settings.types.d.ts +2 -0
  112. package/dist/adapters/agents/settings.types.js.map +1 -1
  113. package/dist/adapters/decisions/system-one-provider.constants.d.ts +1 -1
  114. package/dist/adapters/decisions/system-one-provider.constants.js +1 -1
  115. package/dist/adapters/decisions/system-one-provider.constants.js.map +1 -1
  116. package/dist/adapters/decisions/system-one-provider.js +8 -21
  117. package/dist/adapters/decisions/system-one-provider.js.map +1 -1
  118. package/dist/adapters/models/anthropic-model-provider.constants.d.ts +1 -0
  119. package/dist/adapters/models/anthropic-model-provider.constants.js +4 -0
  120. package/dist/adapters/models/anthropic-model-provider.constants.js.map +1 -1
  121. package/dist/adapters/models/anthropic-model-provider.js +7 -1
  122. package/dist/adapters/models/anthropic-model-provider.js.map +1 -1
  123. package/dist/adapters/models/http-failure.d.ts +3 -0
  124. package/dist/adapters/models/http-failure.js +43 -0
  125. package/dist/adapters/models/http-failure.js.map +1 -0
  126. package/dist/adapters/models/http-provider.js +14 -20
  127. package/dist/adapters/models/http-provider.js.map +1 -1
  128. package/dist/adapters/models/model-protocol.types.d.ts +1 -0
  129. package/dist/adapters/models/model-protocol.types.js.map +1 -1
  130. package/dist/adapters/models/model.constants.d.ts +2 -0
  131. package/dist/adapters/models/model.constants.js +17 -0
  132. package/dist/adapters/models/model.constants.js.map +1 -1
  133. package/dist/adapters/models/openai-chat-stream.js +3 -1
  134. package/dist/adapters/models/openai-chat-stream.js.map +1 -1
  135. package/dist/adapters/models/openai-responses.js +4 -0
  136. package/dist/adapters/models/openai-responses.js.map +1 -1
  137. package/dist/adapters/secrets/aws.js +5 -4
  138. package/dist/adapters/secrets/aws.js.map +1 -1
  139. package/dist/adapters/secrets/azure.constants.d.ts +1 -0
  140. package/dist/adapters/secrets/azure.constants.js +2 -0
  141. package/dist/adapters/secrets/azure.constants.js.map +1 -0
  142. package/dist/adapters/secrets/azure.js +2 -1
  143. package/dist/adapters/secrets/azure.js.map +1 -1
  144. package/dist/adapters/secrets/gcp.constants.d.ts +1 -0
  145. package/dist/adapters/secrets/gcp.constants.js +2 -0
  146. package/dist/adapters/secrets/gcp.constants.js.map +1 -0
  147. package/dist/adapters/secrets/gcp.js +11 -9
  148. package/dist/adapters/secrets/gcp.js.map +1 -1
  149. package/dist/adapters/secrets/infisical.js +3 -2
  150. package/dist/adapters/secrets/infisical.js.map +1 -1
  151. package/dist/adapters/secrets/onepassword.constants.d.ts +1 -0
  152. package/dist/adapters/secrets/onepassword.constants.js +2 -0
  153. package/dist/adapters/secrets/onepassword.constants.js.map +1 -0
  154. package/dist/adapters/secrets/onepassword.js +2 -1
  155. package/dist/adapters/secrets/onepassword.js.map +1 -1
  156. package/dist/adapters/secrets/secret-source.js +3 -1
  157. package/dist/adapters/secrets/secret-source.js.map +1 -1
  158. package/dist/adapters/secrets/vault-response.js +5 -5
  159. package/dist/adapters/secrets/vault-response.js.map +1 -1
  160. package/dist/adapters/secrets/vault.js +4 -3
  161. package/dist/adapters/secrets/vault.js.map +1 -1
  162. package/dist/adapters/testing/scripted-agent.d.ts +3 -1
  163. package/dist/adapters/testing/scripted-agent.js +3 -1
  164. package/dist/adapters/testing/scripted-agent.js.map +1 -1
  165. package/dist/adapters/tools/edit-tools.js +3 -3
  166. package/dist/adapters/tools/edit-tools.js.map +1 -1
  167. package/dist/adapters/tools/git-tools.js +16 -1
  168. package/dist/adapters/tools/git-tools.js.map +1 -1
  169. package/dist/adapters/tools/mcp-launcher.constants.d.ts +1 -1
  170. package/dist/adapters/tools/mcp-launcher.constants.js +29 -7
  171. package/dist/adapters/tools/mcp-launcher.constants.js.map +1 -1
  172. package/dist/adapters/tools/mcp-resources.js +5 -1
  173. package/dist/adapters/tools/mcp-resources.js.map +1 -1
  174. package/dist/adapters/tools/mcp.constants.d.ts +0 -6
  175. package/dist/adapters/tools/mcp.constants.js +0 -6
  176. package/dist/adapters/tools/mcp.constants.js.map +1 -1
  177. package/dist/adapters/tools/mcp.js +1 -0
  178. package/dist/adapters/tools/mcp.js.map +1 -1
  179. package/dist/adapters/tools/sandbox-files.constants.d.ts +1 -0
  180. package/dist/adapters/tools/sandbox-files.constants.js +17 -0
  181. package/dist/adapters/tools/sandbox-files.constants.js.map +1 -0
  182. package/dist/adapters/tools/sandbox-files.d.ts +1 -0
  183. package/dist/adapters/tools/sandbox-files.js +14 -1
  184. package/dist/adapters/tools/sandbox-files.js.map +1 -1
  185. package/dist/adapters/tools/tools.constants.js +1 -0
  186. package/dist/adapters/tools/tools.constants.js.map +1 -1
  187. package/dist/adapters/triggers/github-webhook.js +14 -11
  188. package/dist/adapters/triggers/github-webhook.js.map +1 -1
  189. package/dist/adapters/triggers/gitlab-webhook.js +16 -13
  190. package/dist/adapters/triggers/gitlab-webhook.js.map +1 -1
  191. package/dist/adapters/triggers/slack-request.js +10 -7
  192. package/dist/adapters/triggers/slack-request.js.map +1 -1
  193. package/dist/adapters/triggers/standard-webhook.js +10 -7
  194. package/dist/adapters/triggers/standard-webhook.js.map +1 -1
  195. package/dist/application/agent-authentication.js +4 -1
  196. package/dist/application/agent-authentication.js.map +1 -1
  197. package/dist/application/agent-turn.js +20 -5
  198. package/dist/application/agent-turn.js.map +1 -1
  199. package/dist/application/cli-hooks.constants.d.ts +2 -0
  200. package/dist/application/cli-hooks.constants.js +69 -0
  201. package/dist/application/cli-hooks.constants.js.map +1 -0
  202. package/dist/application/cli-hooks.d.ts +3 -0
  203. package/dist/application/cli-hooks.js +168 -0
  204. package/dist/application/cli-hooks.js.map +1 -0
  205. package/dist/application/cli-steering.js +33 -2
  206. package/dist/application/cli-steering.js.map +1 -1
  207. package/dist/application/custom-turn.js +10 -1
  208. package/dist/application/custom-turn.js.map +1 -1
  209. package/dist/application/diagnostic-probe.d.ts +1 -1
  210. package/dist/application/diagnostic-probe.js +7 -3
  211. package/dist/application/diagnostic-probe.js.map +1 -1
  212. package/dist/application/dispatch-observation.js +4 -0
  213. package/dist/application/dispatch-observation.js.map +1 -1
  214. package/dist/application/doctor-agent.d.ts +1 -1
  215. package/dist/application/doctor-agent.js +2 -2
  216. package/dist/application/doctor-agent.js.map +1 -1
  217. package/dist/application/doctor-deadline.d.ts +1 -0
  218. package/dist/application/doctor-deadline.js +10 -0
  219. package/dist/application/doctor-deadline.js.map +1 -0
  220. package/dist/application/doctor-image.js +9 -7
  221. package/dist/application/doctor-image.js.map +1 -1
  222. package/dist/application/doctor-sandbox.js +4 -4
  223. package/dist/application/doctor-sandbox.js.map +1 -1
  224. package/dist/application/doctor.constants.d.ts +2 -0
  225. package/dist/application/doctor.constants.js +2 -0
  226. package/dist/application/doctor.constants.js.map +1 -1
  227. package/dist/application/doctor.js +12 -8
  228. package/dist/application/doctor.js.map +1 -1
  229. package/dist/application/doctor.types.d.ts +2 -0
  230. package/dist/application/doctor.types.js.map +1 -1
  231. package/dist/application/file-sandbox.js +49 -11
  232. package/dist/application/file-sandbox.js.map +1 -1
  233. package/dist/application/harness-context.js +4 -2
  234. package/dist/application/harness-context.js.map +1 -1
  235. package/dist/application/harness-hook-transforms.d.ts +8 -0
  236. package/dist/application/harness-hook-transforms.js +115 -0
  237. package/dist/application/harness-hook-transforms.js.map +1 -0
  238. package/dist/application/harness-hooks.d.ts +5 -3
  239. package/dist/application/harness-hooks.js +37 -50
  240. package/dist/application/harness-hooks.js.map +1 -1
  241. package/dist/application/harness-loop.d.ts +2 -1
  242. package/dist/application/harness-loop.js +95 -21
  243. package/dist/application/harness-loop.js.map +1 -1
  244. package/dist/application/harness-subagent.d.ts +1 -1
  245. package/dist/application/harness-subagent.js +63 -12
  246. package/dist/application/harness-subagent.js.map +1 -1
  247. package/dist/application/harness.types.d.ts +3 -0
  248. package/dist/application/harness.types.js.map +1 -1
  249. package/dist/application/hook-invocation.d.ts +4 -0
  250. package/dist/application/hook-invocation.js +59 -0
  251. package/dist/application/hook-invocation.js.map +1 -0
  252. package/dist/application/queue-worker.js +51 -9
  253. package/dist/application/queue-worker.js.map +1 -1
  254. package/dist/application/queue-worker.types.d.ts +1 -0
  255. package/dist/application/queue-worker.types.js.map +1 -1
  256. package/dist/application/recipes/native-schemas.constants.js +1439 -218
  257. package/dist/application/recipes/native-schemas.constants.js.map +1 -1
  258. package/dist/application/recovery-inspection.js +4 -1
  259. package/dist/application/recovery-inspection.js.map +1 -1
  260. package/dist/application/remote-download.js +15 -5
  261. package/dist/application/remote-download.js.map +1 -1
  262. package/dist/application/remote-paths.d.ts +1 -0
  263. package/dist/application/remote-paths.js +7 -0
  264. package/dist/application/remote-paths.js.map +1 -0
  265. package/dist/application/remote-validation.js +40 -9
  266. package/dist/application/remote-validation.js.map +1 -1
  267. package/dist/application/remote-workspace.js +17 -2
  268. package/dist/application/remote-workspace.js.map +1 -1
  269. package/dist/application/repetition-watchdog.js +3 -1
  270. package/dist/application/repetition-watchdog.js.map +1 -1
  271. package/dist/application/sandbox-attach.js +38 -9
  272. package/dist/application/sandbox-attach.js.map +1 -1
  273. package/dist/application/sandbox-dispatch.js +7 -1
  274. package/dist/application/sandbox-dispatch.js.map +1 -1
  275. package/dist/application/schedules.js +2 -0
  276. package/dist/application/schedules.js.map +1 -1
  277. package/dist/application/secrets.js +4 -0
  278. package/dist/application/secrets.js.map +1 -1
  279. package/dist/application/tool-execution.js +28 -8
  280. package/dist/application/tool-execution.js.map +1 -1
  281. package/dist/application/transport-retention.js +3 -3
  282. package/dist/application/transport-retention.js.map +1 -1
  283. package/dist/application/workspace-fingerprint.d.ts +1 -0
  284. package/dist/application/workspace-fingerprint.js +19 -4
  285. package/dist/application/workspace-fingerprint.js.map +1 -1
  286. package/dist/cli/doctor-command.js +12 -2
  287. package/dist/cli/doctor-command.js.map +1 -1
  288. package/dist/cli/image.js +2 -0
  289. package/dist/cli/image.js.map +1 -1
  290. package/dist/cli/main.constants.d.ts +14 -2
  291. package/dist/cli/main.constants.js +27 -1
  292. package/dist/cli/main.constants.js.map +1 -1
  293. package/dist/cli/project-settings.js +7 -1
  294. package/dist/cli/project-settings.js.map +1 -1
  295. package/dist/cli/recipe-yaml.js +8 -0
  296. package/dist/cli/recipe-yaml.js.map +1 -1
  297. package/dist/cli/recovery-command.js +3 -0
  298. package/dist/cli/recovery-command.js.map +1 -1
  299. package/dist/cli/recovery-unlock-command.d.ts +2 -0
  300. package/dist/cli/recovery-unlock-command.js +19 -0
  301. package/dist/cli/recovery-unlock-command.js.map +1 -0
  302. package/dist/cli/scaffold-files.js +4 -1
  303. package/dist/cli/scaffold-files.js.map +1 -1
  304. package/dist/cli/scaffold-validation.js +3 -0
  305. package/dist/cli/scaffold-validation.js.map +1 -1
  306. package/dist/cli/scaffold.js +2 -0
  307. package/dist/cli/scaffold.js.map +1 -1
  308. package/dist/domain/agent-hook.types.d.ts +28 -0
  309. package/dist/domain/agent-hook.types.js +2 -0
  310. package/dist/domain/agent-hook.types.js.map +1 -0
  311. package/dist/domain/agent-profile-hooks.d.ts +2 -0
  312. package/dist/domain/agent-profile-hooks.js +52 -0
  313. package/dist/domain/agent-profile-hooks.js.map +1 -0
  314. package/dist/domain/agent-profile-permissions.js +11 -1
  315. package/dist/domain/agent-profile-permissions.js.map +1 -1
  316. package/dist/domain/agent-profile.constants.d.ts +1 -0
  317. package/dist/domain/agent-profile.constants.js +9 -0
  318. package/dist/domain/agent-profile.constants.js.map +1 -1
  319. package/dist/domain/agent-profile.js +6 -1
  320. package/dist/domain/agent-profile.js.map +1 -1
  321. package/dist/domain/agent-profile.types.d.ts +11 -0
  322. package/dist/domain/agent-profile.types.js.map +1 -1
  323. package/dist/domain/agent.types.d.ts +2 -0
  324. package/dist/domain/agent.types.js.map +1 -1
  325. package/dist/domain/container-image.d.ts +1 -0
  326. package/dist/domain/container-image.js +8 -0
  327. package/dist/domain/container-image.js.map +1 -0
  328. package/dist/domain/context.constants.d.ts +1 -0
  329. package/dist/domain/context.constants.js +1 -0
  330. package/dist/domain/context.constants.js.map +1 -1
  331. package/dist/domain/context.js +6 -1
  332. package/dist/domain/context.js.map +1 -1
  333. package/dist/domain/egress.js +6 -1
  334. package/dist/domain/egress.js.map +1 -1
  335. package/dist/domain/glob.js +1 -1
  336. package/dist/domain/glob.js.map +1 -1
  337. package/dist/domain/harness.js +4 -1
  338. package/dist/domain/harness.js.map +1 -1
  339. package/dist/domain/hook-command.d.ts +2 -0
  340. package/dist/domain/hook-command.js +26 -0
  341. package/dist/domain/hook-command.js.map +1 -0
  342. package/dist/domain/hook-command.types.d.ts +7 -0
  343. package/dist/domain/hook-command.types.js +2 -0
  344. package/dist/domain/hook-command.types.js.map +1 -0
  345. package/dist/domain/hook-decision.d.ts +2 -0
  346. package/dist/domain/hook-decision.js +38 -0
  347. package/dist/domain/hook-decision.js.map +1 -0
  348. package/dist/domain/hook.constants.d.ts +3 -0
  349. package/dist/domain/hook.constants.js +31 -1
  350. package/dist/domain/hook.constants.js.map +1 -1
  351. package/dist/domain/hook.js +49 -5
  352. package/dist/domain/hook.js.map +1 -1
  353. package/dist/domain/hook.types.d.ts +82 -5
  354. package/dist/domain/hook.types.js.map +1 -1
  355. package/dist/domain/mcp-server.constants.d.ts +6 -0
  356. package/dist/domain/mcp-server.constants.js +6 -0
  357. package/dist/domain/mcp-server.constants.js.map +1 -1
  358. package/dist/domain/mcp-server.js +1 -0
  359. package/dist/domain/mcp-server.js.map +1 -1
  360. package/dist/domain/permissions.types.d.ts +1 -0
  361. package/dist/domain/permissions.types.js.map +1 -1
  362. package/dist/domain/pricing.js +4 -2
  363. package/dist/domain/pricing.js.map +1 -1
  364. package/dist/domain/redaction.js +6 -3
  365. package/dist/domain/redaction.js.map +1 -1
  366. package/dist/domain/secret-fault.d.ts +4 -0
  367. package/dist/domain/secret-fault.js +11 -0
  368. package/dist/domain/secret-fault.js.map +1 -0
  369. package/dist/domain/secrets.js +3 -2
  370. package/dist/domain/secrets.js.map +1 -1
  371. package/dist/domain/steering.js +2 -0
  372. package/dist/domain/steering.js.map +1 -1
  373. package/dist/domain/steering.types.d.ts +1 -1
  374. package/dist/domain/steering.types.js.map +1 -1
  375. package/dist/domain/transport.js +5 -1
  376. package/dist/domain/transport.js.map +1 -1
  377. package/dist/domain/trigger-payload.d.ts +4 -0
  378. package/dist/domain/trigger-payload.js +15 -0
  379. package/dist/domain/trigger-payload.js.map +1 -0
  380. package/dist/domain/workflow/checkpoint.js +19 -2
  381. package/dist/domain/workflow/checkpoint.js.map +1 -1
  382. package/dist/domain/workflow/retry.constants.d.ts +1 -0
  383. package/dist/domain/workflow/retry.constants.js +1 -0
  384. package/dist/domain/workflow/retry.constants.js.map +1 -1
  385. package/dist/domain/workflow/retry.js +6 -2
  386. package/dist/domain/workflow/retry.js.map +1 -1
  387. package/dist/domain/workflow/task-runner.js +5 -3
  388. package/dist/domain/workflow/task-runner.js.map +1 -1
  389. package/dist/domain/workflow/workflow-state.js +2 -1
  390. package/dist/domain/workflow/workflow-state.js.map +1 -1
  391. package/dist/domain/workflow.types.d.ts +1 -0
  392. package/dist/domain/workflow.types.js.map +1 -1
  393. package/dist/index.d.ts +15 -1
  394. package/dist/index.js +6 -0
  395. package/dist/index.js.map +1 -1
  396. package/dist/infrastructure/conversations/transcript-store.js +32 -5
  397. package/dist/infrastructure/conversations/transcript-store.js.map +1 -1
  398. package/dist/infrastructure/files.d.ts +1 -0
  399. package/dist/infrastructure/files.js +8 -4
  400. package/dist/infrastructure/files.js.map +1 -1
  401. package/dist/infrastructure/git/integration-candidate.js +3 -2
  402. package/dist/infrastructure/git/integration-candidate.js.map +1 -1
  403. package/dist/infrastructure/git/lock-recovery.d.ts +3 -0
  404. package/dist/infrastructure/git/lock-recovery.js +58 -0
  405. package/dist/infrastructure/git/lock-recovery.js.map +1 -0
  406. package/dist/infrastructure/git/lock-recovery.types.d.ts +11 -0
  407. package/dist/infrastructure/git/lock-recovery.types.js +2 -0
  408. package/dist/infrastructure/git/lock-recovery.types.js.map +1 -0
  409. package/dist/infrastructure/git/managed-worktree.js +5 -8
  410. package/dist/infrastructure/git/managed-worktree.js.map +1 -1
  411. package/dist/infrastructure/git/verification-command.js +35 -30
  412. package/dist/infrastructure/git/verification-command.js.map +1 -1
  413. package/dist/infrastructure/git/workspace-lease.js +12 -5
  414. package/dist/infrastructure/git/workspace-lease.js.map +1 -1
  415. package/dist/infrastructure/hook-configuration.constants.d.ts +1 -0
  416. package/dist/infrastructure/hook-configuration.constants.js +59 -0
  417. package/dist/infrastructure/hook-configuration.constants.js.map +1 -0
  418. package/dist/infrastructure/hook-configuration.d.ts +3 -0
  419. package/dist/infrastructure/hook-configuration.js +16 -0
  420. package/dist/infrastructure/hook-configuration.js.map +1 -0
  421. package/dist/infrastructure/hook-configuration.types.d.ts +14 -0
  422. package/dist/infrastructure/hook-configuration.types.js +2 -0
  423. package/dist/infrastructure/hook-configuration.types.js.map +1 -0
  424. package/dist/infrastructure/http-transport.constants.d.ts +1 -0
  425. package/dist/infrastructure/http-transport.constants.js +14 -0
  426. package/dist/infrastructure/http-transport.constants.js.map +1 -0
  427. package/dist/infrastructure/http-transport.d.ts +7 -0
  428. package/dist/infrastructure/http-transport.js +19 -0
  429. package/dist/infrastructure/http-transport.js.map +1 -0
  430. package/dist/infrastructure/input-failure.d.ts +4 -0
  431. package/dist/infrastructure/input-failure.js +14 -0
  432. package/dist/infrastructure/input-failure.js.map +1 -0
  433. package/dist/infrastructure/inspection-file.d.ts +1 -0
  434. package/dist/infrastructure/inspection-file.js +8 -2
  435. package/dist/infrastructure/inspection-file.js.map +1 -1
  436. package/dist/infrastructure/local-transport.js +16 -11
  437. package/dist/infrastructure/local-transport.js.map +1 -1
  438. package/dist/infrastructure/process.constants.d.ts +1 -0
  439. package/dist/infrastructure/process.constants.js +1 -0
  440. package/dist/infrastructure/process.constants.js.map +1 -1
  441. package/dist/infrastructure/process.d.ts +1 -0
  442. package/dist/infrastructure/process.js +48 -8
  443. package/dist/infrastructure/process.js.map +1 -1
  444. package/dist/infrastructure/reservation-ledger.d.ts +2 -0
  445. package/dist/infrastructure/reservation-ledger.js +84 -0
  446. package/dist/infrastructure/reservation-ledger.js.map +1 -0
  447. package/dist/infrastructure/reservation-recovery.d.ts +4 -0
  448. package/dist/infrastructure/reservation-recovery.js +28 -0
  449. package/dist/infrastructure/reservation-recovery.js.map +1 -0
  450. package/dist/infrastructure/s3-tombstones.d.ts +3 -0
  451. package/dist/infrastructure/s3-tombstones.js +46 -0
  452. package/dist/infrastructure/s3-tombstones.js.map +1 -0
  453. package/dist/infrastructure/s3-tombstones.types.d.ts +6 -0
  454. package/dist/infrastructure/s3-tombstones.types.js +2 -0
  455. package/dist/infrastructure/s3-tombstones.types.js.map +1 -0
  456. package/dist/infrastructure/s3-transport.d.ts +2 -0
  457. package/dist/infrastructure/s3-transport.js +4 -2
  458. package/dist/infrastructure/s3-transport.js.map +1 -1
  459. package/dist/infrastructure/sse.js +6 -3
  460. package/dist/infrastructure/sse.js.map +1 -1
  461. package/dist/infrastructure/task-queue-bullmq-connection.d.ts +3 -0
  462. package/dist/infrastructure/task-queue-bullmq-connection.js +32 -0
  463. package/dist/infrastructure/task-queue-bullmq-connection.js.map +1 -0
  464. package/dist/infrastructure/task-queue-bullmq-connection.types.d.ts +8 -0
  465. package/dist/infrastructure/task-queue-bullmq-connection.types.js +2 -0
  466. package/dist/infrastructure/task-queue-bullmq-connection.types.js.map +1 -0
  467. package/dist/infrastructure/task-queue-bullmq-resources.js +21 -15
  468. package/dist/infrastructure/task-queue-bullmq-resources.js.map +1 -1
  469. package/dist/infrastructure/task-queue-bullmq-state.d.ts +1 -0
  470. package/dist/infrastructure/task-queue-bullmq-state.js +1 -0
  471. package/dist/infrastructure/task-queue-bullmq-state.js.map +1 -1
  472. package/dist/infrastructure/task-queue-bullmq.constants.d.ts +2 -1
  473. package/dist/infrastructure/task-queue-bullmq.constants.js +2 -1
  474. package/dist/infrastructure/task-queue-bullmq.constants.js.map +1 -1
  475. package/dist/infrastructure/task-queue-bullmq.js +10 -1
  476. package/dist/infrastructure/task-queue-bullmq.js.map +1 -1
  477. package/dist/infrastructure/task-queue.js +13 -4
  478. package/dist/infrastructure/task-queue.js.map +1 -1
  479. package/dist/infrastructure/transfer-copy.d.ts +1 -0
  480. package/dist/infrastructure/transfer-copy.js +16 -1
  481. package/dist/infrastructure/transfer-copy.js.map +1 -1
  482. package/dist/infrastructure/transport-archive.d.ts +3 -3
  483. package/dist/infrastructure/transport-archive.js +71 -48
  484. package/dist/infrastructure/transport-archive.js.map +1 -1
  485. package/dist/infrastructure/transport-archive.types.d.ts +3 -0
  486. package/dist/infrastructure/transport-archive.types.js.map +1 -1
  487. package/dist/infrastructure/transport-checkpoint.js +14 -4
  488. package/dist/infrastructure/transport-checkpoint.js.map +1 -1
  489. package/dist/infrastructure/transport-envelope.d.ts +1 -0
  490. package/dist/infrastructure/transport-envelope.js +22 -5
  491. package/dist/infrastructure/transport-envelope.js.map +1 -1
  492. package/dist/infrastructure/transport-reservations.constants.d.ts +2 -0
  493. package/dist/infrastructure/transport-reservations.constants.js +3 -0
  494. package/dist/infrastructure/transport-reservations.constants.js.map +1 -0
  495. package/dist/infrastructure/transport-reservations.d.ts +1 -2
  496. package/dist/infrastructure/transport-reservations.js +18 -22
  497. package/dist/infrastructure/transport-reservations.js.map +1 -1
  498. package/dist/infrastructure/transport-reservations.types.d.ts +23 -2
  499. package/dist/infrastructure/transport-reservations.types.js.map +1 -1
  500. package/dist/infrastructure/trigger-server.js +12 -9
  501. package/dist/infrastructure/trigger-server.js.map +1 -1
  502. package/dist/infrastructure/trigger-server.types.d.ts +1 -1
  503. package/dist/infrastructure/trigger-server.types.js.map +1 -1
  504. package/dist/infrastructure/workflow-checkpoint.constants.d.ts +1 -0
  505. package/dist/infrastructure/workflow-checkpoint.constants.js +1 -0
  506. package/dist/infrastructure/workflow-checkpoint.constants.js.map +1 -1
  507. package/dist/infrastructure/workspace-lock.constants.d.ts +2 -1
  508. package/dist/infrastructure/workspace-lock.constants.js +2 -1
  509. package/dist/infrastructure/workspace-lock.constants.js.map +1 -1
  510. package/dist/infrastructure/workspace-lock.js +48 -10
  511. package/dist/infrastructure/workspace-lock.js.map +1 -1
  512. package/dist/providers/cloud-cache.js +14 -9
  513. package/dist/providers/cloud-cache.js.map +1 -1
  514. package/dist/providers/cloud-cache.types.d.ts +1 -0
  515. package/dist/providers/cloud-cache.types.js.map +1 -1
  516. package/dist/providers/cloud-files.js +3 -4
  517. package/dist/providers/cloud-files.js.map +1 -1
  518. package/dist/providers/cloud-input.constants.d.ts +2 -2
  519. package/dist/providers/cloud-input.constants.js +2 -1
  520. package/dist/providers/cloud-input.constants.js.map +1 -1
  521. package/dist/providers/cloud-input.d.ts +2 -2
  522. package/dist/providers/cloud-input.js +14 -3
  523. package/dist/providers/cloud-input.js.map +1 -1
  524. package/dist/providers/container-command.js +30 -5
  525. package/dist/providers/container-command.js.map +1 -1
  526. package/dist/providers/container-egress.constants.d.ts +7 -0
  527. package/dist/providers/container-egress.constants.js +8 -0
  528. package/dist/providers/container-egress.constants.js.map +1 -0
  529. package/dist/providers/container-egress.d.ts +7 -0
  530. package/dist/providers/container-egress.js +101 -0
  531. package/dist/providers/container-egress.js.map +1 -0
  532. package/dist/providers/container-files.js +10 -11
  533. package/dist/providers/container-files.js.map +1 -1
  534. package/dist/providers/container-mounts.js +3 -0
  535. package/dist/providers/container-mounts.js.map +1 -1
  536. package/dist/providers/container-network.js +16 -1
  537. package/dist/providers/container-network.js.map +1 -1
  538. package/dist/providers/container-plan.js +7 -10
  539. package/dist/providers/container-plan.js.map +1 -1
  540. package/dist/providers/container-recovery.js +8 -3
  541. package/dist/providers/container-recovery.js.map +1 -1
  542. package/dist/providers/container.js +36 -5
  543. package/dist/providers/container.js.map +1 -1
  544. package/dist/providers/container.types.d.ts +1 -0
  545. package/dist/providers/container.types.js.map +1 -1
  546. package/dist/providers/daytona-command.constants.js +4 -1
  547. package/dist/providers/daytona-command.constants.js.map +1 -1
  548. package/dist/providers/daytona-command.js +39 -16
  549. package/dist/providers/daytona-command.js.map +1 -1
  550. package/dist/providers/daytona-files.js +5 -5
  551. package/dist/providers/daytona-files.js.map +1 -1
  552. package/dist/providers/daytona-output.js +11 -3
  553. package/dist/providers/daytona-output.js.map +1 -1
  554. package/dist/providers/daytona.js +11 -9
  555. package/dist/providers/daytona.js.map +1 -1
  556. package/dist/providers/egress/address.d.ts +3 -0
  557. package/dist/providers/egress/address.js +26 -0
  558. package/dist/providers/egress/address.js.map +1 -0
  559. package/dist/providers/egress/egress.constants.d.ts +22 -0
  560. package/dist/providers/egress/egress.constants.js +23 -0
  561. package/dist/providers/egress/egress.constants.js.map +1 -0
  562. package/dist/providers/egress/egress.types.d.ts +11 -0
  563. package/dist/providers/egress/egress.types.js +2 -0
  564. package/dist/providers/egress/egress.types.js.map +1 -0
  565. package/dist/providers/egress/firewall.d.ts +3 -0
  566. package/dist/providers/egress/firewall.js +29 -0
  567. package/dist/providers/egress/firewall.js.map +1 -0
  568. package/dist/providers/egress/main.d.ts +1 -0
  569. package/dist/providers/egress/main.js +90 -0
  570. package/dist/providers/egress/main.js.map +1 -0
  571. package/dist/providers/egress/policy.d.ts +5 -0
  572. package/dist/providers/egress/policy.js +54 -0
  573. package/dist/providers/egress/policy.js.map +1 -0
  574. package/dist/providers/egress/proxy.d.ts +2 -0
  575. package/dist/providers/egress/proxy.js +129 -0
  576. package/dist/providers/egress/proxy.js.map +1 -0
  577. package/dist/providers/egress/tls-hello.d.ts +1 -0
  578. package/dist/providers/egress/tls-hello.js +75 -0
  579. package/dist/providers/egress/tls-hello.js.map +1 -0
  580. package/dist/providers/firecracker-command.js +12 -6
  581. package/dist/providers/firecracker-command.js.map +1 -1
  582. package/dist/providers/local-files.d.ts +2 -0
  583. package/dist/providers/local-files.js +24 -0
  584. package/dist/providers/local-files.js.map +1 -0
  585. package/dist/providers/local.js +2 -20
  586. package/dist/providers/local.js.map +1 -1
  587. package/dist/providers/vercel-command.js +33 -9
  588. package/dist/providers/vercel-command.js.map +1 -1
  589. package/dist/providers/vercel.js +11 -9
  590. package/dist/providers/vercel.js.map +1 -1
  591. package/dist/testing.d.ts +1 -1
  592. package/dist/testing.js +1 -1
  593. package/dist/testing.js.map +1 -1
  594. package/package.json +2 -2
  595. package/recipe-configuration.schema.json +2164 -35
  596. package/recipe.schema.json +2512 -404
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-configuration.js","sourceRoot":"","sources":["../../src/infrastructure/hook-configuration.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAE5E,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,OAAqB,EACrB,IAA2B,EAC3B,MAAmB;IAEnB,MAAM,OAAO,GAAG,KAAK,EAAE,MAAe,EAAE,MAAoB,EAAE,EAAE;QAC9D,MAAM,cAAc,CAClB;YACE,UAAU,EAAE,MAAM;YAClB,SAAS,EAAE,CAAC,IAAI,EAAE,uBAAuB,CAAC;YAC1C,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YAC3D,UAAU,EAAE,MAAM;YAClB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9B,EACD,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAC7B,CAAC;IACJ,CAAC,CAAC;IACF,MAAM,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["import type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport type { HookConfigurationEdit } from \"./hook-configuration.types.ts\";\nimport { requireSuccess } from \"./process.ts\";\nimport { hookConfigurationScript } from \"./hook-configuration.constants.ts\";\n\nexport async function installHookConfiguration(\n sandbox: SandboxLease,\n edit: HookConfigurationEdit,\n signal: AbortSignal,\n): Promise<() => Promise<void>> {\n const execute = async (remove: boolean, signal?: AbortSignal) => {\n await requireSuccess(\n {\n executable: \"node\",\n arguments: [\"-e\", hookConfigurationScript],\n stdin: JSON.stringify({ home: sandbox.home, edit, remove }),\n deadlineMs: 10_000,\n ...(signal ? { signal } : {}),\n },\n sandbox.invoke.bind(sandbox),\n );\n };\n await execute(false, signal);\n return () => execute(true);\n}\n"]}
@@ -0,0 +1,14 @@
1
+ export type HookConfigurationEdit = {
2
+ readonly path: string;
3
+ } & ({
4
+ readonly kind: "exclusive";
5
+ readonly content: string;
6
+ } | {
7
+ readonly kind: "append";
8
+ readonly content: string;
9
+ readonly rejectPattern?: string;
10
+ } | {
11
+ readonly kind: "entry";
12
+ readonly key: string;
13
+ readonly value: unknown;
14
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=hook-configuration.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-configuration.types.js","sourceRoot":"","sources":["../../src/infrastructure/hook-configuration.types.ts"],"names":[],"mappings":"","sourcesContent":["export type HookConfigurationEdit = {\n readonly path: string;\n} & (\n | { readonly kind: \"exclusive\"; readonly content: string }\n | {\n readonly kind: \"append\";\n readonly content: string;\n readonly rejectPattern?: string;\n }\n | { readonly kind: \"entry\"; readonly key: string; readonly value: unknown }\n);\n"]}
@@ -0,0 +1 @@
1
+ export declare const httpTransportCodes: ReadonlySet<string>;
@@ -0,0 +1,14 @@
1
+ export const httpTransportCodes = new Set([
2
+ "ENOTFOUND",
3
+ "EAI_AGAIN",
4
+ "ECONNREFUSED",
5
+ "ECONNRESET",
6
+ "ETIMEDOUT",
7
+ "CERT_HAS_EXPIRED",
8
+ "DEPTH_ZERO_SELF_SIGNED_CERT",
9
+ "UNABLE_TO_VERIFY_LEAF_SIGNATURE",
10
+ "UND_ERR_CONNECT_TIMEOUT",
11
+ "UND_ERR_SOCKET",
12
+ "UND_ERR_HEADERS_TIMEOUT",
13
+ ]);
14
+ //# sourceMappingURL=http-transport.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-transport.constants.js","sourceRoot":"","sources":["../../src/infrastructure/http-transport.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAC;IAC7D,WAAW;IACX,WAAW;IACX,cAAc;IACd,YAAY;IACZ,WAAW;IACX,kBAAkB;IAClB,6BAA6B;IAC7B,iCAAiC;IACjC,yBAAyB;IACzB,gBAAgB;IAChB,yBAAyB;CAC1B,CAAC,CAAC","sourcesContent":["export const httpTransportCodes: ReadonlySet<string> = new Set([\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n \"ECONNREFUSED\",\n \"ECONNRESET\",\n \"ETIMEDOUT\",\n \"CERT_HAS_EXPIRED\",\n \"DEPTH_ZERO_SELF_SIGNED_CERT\",\n \"UNABLE_TO_VERIFY_LEAF_SIGNATURE\",\n \"UND_ERR_CONNECT_TIMEOUT\",\n \"UND_ERR_SOCKET\",\n \"UND_ERR_HEADERS_TIMEOUT\",\n]);\n"]}
@@ -0,0 +1,7 @@
1
+ export declare function httpTransportFailure(error: unknown): {
2
+ unavailable: string;
3
+ transportCode: string;
4
+ } | {
5
+ unavailable: string;
6
+ transportCode?: never;
7
+ };
@@ -0,0 +1,19 @@
1
+ import { httpTransportCodes } from "./http-transport.constants.js";
2
+ export function httpTransportFailure(error) {
3
+ for (const value of [
4
+ error,
5
+ error instanceof Error ? error.cause : undefined,
6
+ ]) {
7
+ if (value &&
8
+ typeof value === "object" &&
9
+ "code" in value &&
10
+ typeof value.code === "string" &&
11
+ httpTransportCodes.has(value.code))
12
+ return {
13
+ unavailable: "HTTP transport failure",
14
+ transportCode: value.code,
15
+ };
16
+ }
17
+ return { unavailable: "HTTP transport failure" };
18
+ }
19
+ //# sourceMappingURL=http-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-transport.js","sourceRoot":"","sources":["../../src/infrastructure/http-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,KAAK,MAAM,KAAK,IAAI;QAClB,KAAK;QACL,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;KACjD,EAAE,CAAC;QACF,IACE,KAAK;YACL,OAAO,KAAK,KAAK,QAAQ;YACzB,MAAM,IAAI,KAAK;YACf,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;YAC9B,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;YAElC,OAAO;gBACL,WAAW,EAAE,wBAAwB;gBACrC,aAAa,EAAE,KAAK,CAAC,IAAI;aAC1B,CAAC;IACN,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,CAAC;AACnD,CAAC","sourcesContent":["import { httpTransportCodes } from \"./http-transport.constants.ts\";\n\nexport function httpTransportFailure(error: unknown) {\n for (const value of [\n error,\n error instanceof Error ? error.cause : undefined,\n ]) {\n if (\n value &&\n typeof value === \"object\" &&\n \"code\" in value &&\n typeof value.code === \"string\" &&\n httpTransportCodes.has(value.code)\n )\n return {\n unavailable: \"HTTP transport failure\",\n transportCode: value.code,\n };\n }\n return { unavailable: \"HTTP transport failure\" };\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { Readable } from "node:stream";
2
+ import { OutpostError } from "../domain/errors.ts";
3
+ export declare function observeInputFailure(input: Readable, handler: (error: OutpostError) => void): () => void;
4
+ export declare function reportInputFailure(input: Readable, cause: unknown): boolean;
@@ -0,0 +1,14 @@
1
+ import { OutpostError } from "../domain/errors.js";
2
+ const handlers = new WeakMap();
3
+ export function observeInputFailure(input, handler) {
4
+ handlers.set(input, handler);
5
+ return () => handlers.delete(input);
6
+ }
7
+ export function reportInputFailure(input, cause) {
8
+ const handler = handlers.get(input);
9
+ if (!handler)
10
+ return false;
11
+ handler(new OutpostError("steering", "Live input delivery could not be confirmed", {}, cause));
12
+ return true;
13
+ }
14
+ //# sourceMappingURL=input-failure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-failure.js","sourceRoot":"","sources":["../../src/infrastructure/input-failure.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,QAAQ,GAAG,IAAI,OAAO,EAA2C,CAAC;AAExE,MAAM,UAAU,mBAAmB,CACjC,KAAe,EACf,OAAsC;IAEtC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC7B,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAe,EAAE,KAAc;IAChE,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,OAAO,CACL,IAAI,YAAY,CACd,UAAU,EACV,4CAA4C,EAC5C,EAAE,EACF,KAAK,CACN,CACF,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import type { Readable } from \"node:stream\";\nimport { OutpostError } from \"../domain/errors.ts\";\n\nconst handlers = new WeakMap<Readable, (error: OutpostError) => void>();\n\nexport function observeInputFailure(\n input: Readable,\n handler: (error: OutpostError) => void,\n): () => void {\n handlers.set(input, handler);\n return () => handlers.delete(input);\n}\n\nexport function reportInputFailure(input: Readable, cause: unknown): boolean {\n const handler = handlers.get(input);\n if (!handler) return false;\n handler(\n new OutpostError(\n \"steering\",\n \"Live input delivery could not be confirmed\",\n {},\n cause,\n ),\n );\n return true;\n}\n"]}
@@ -4,3 +4,4 @@ export declare class InspectionFileChanged extends Error {
4
4
  constructor();
5
5
  }
6
6
  export declare function readInspectionFile(path: string, maxBytes: number, expected?: Stats): Promise<Buffer>;
7
+ export declare function readInspectionPrefix(path: string, maxBytes: number, expected: Stats): Promise<Buffer>;
@@ -17,20 +17,26 @@ function unchanged(before, after) {
17
17
  before.ctimeMs === after.ctimeMs);
18
18
  }
19
19
  export async function readInspectionFile(path, maxBytes, expected) {
20
+ return inspectFile(path, maxBytes, false, expected);
21
+ }
22
+ export async function readInspectionPrefix(path, maxBytes, expected) {
23
+ return inspectFile(path, maxBytes, true, expected);
24
+ }
25
+ async function inspectFile(path, maxBytes, prefix, expected) {
20
26
  positive(maxBytes, "maxBytes");
21
27
  const before = await lstat(path);
22
28
  if (expected && !unchanged(expected, before))
23
29
  throw new InspectionFileChanged();
24
30
  if (!before.isFile() || !(await isDirectInspectionPath(path)))
25
31
  throw new Error("Inspection path changed");
26
- if (before.size > maxBytes)
32
+ if (!prefix && before.size > maxBytes)
27
33
  throw new Error("Inspection file is too large");
28
34
  const file = await open(path, inspectionFileFlags);
29
35
  try {
30
36
  const opened = await file.stat();
31
37
  if (!opened.isFile() || !unchanged(before, opened))
32
38
  throw new InspectionFileChanged();
33
- const buffer = Buffer.alloc(maxBytes + 1);
39
+ const buffer = Buffer.alloc(prefix ? maxBytes : maxBytes + 1);
34
40
  let length = 0;
35
41
  while (length < buffer.length) {
36
42
  const { bytesRead } = await file.read(buffer, length, buffer.length - length, length);
@@ -1 +1 @@
1
- {"version":3,"file":"inspection-file.js","sourceRoot":"","sources":["../../src/infrastructure/inspection-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,+EAA+E;AAC/E,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C;QACE,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,SAAS,SAAS,CAAC,MAAa,EAAE,KAAY;IAC5C,OAAO,CACL,MAAM,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG;QACxB,MAAM,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG;QACxB,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI;QAC1B,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO;QAChC,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,CACjC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAY,EACZ,QAAgB,EAChB,QAAgB;IAEhB,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,QAAQ,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1C,MAAM,IAAI,qBAAqB,EAAE,CAAC;IACpC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,IAAI,GAAG,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC5E,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;YAChD,MAAM,IAAI,qBAAqB,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;QAC1C,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,OAAO,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC9B,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CACnC,MAAM,EACN,MAAM,EACN,MAAM,CAAC,MAAM,GAAG,MAAM,EACtB,MAAM,CACP,CAAC;YACF,IAAI,CAAC,SAAS;gBAAE,MAAM;YACtB,MAAM,IAAI,SAAS,CAAC;QACtB,CAAC;QACD,IAAI,MAAM,GAAG,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACvE,IACE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YACrC,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;YAErC,MAAM,IAAI,qBAAqB,EAAE,CAAC;QACpC,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;YAAS,CAAC;QACT,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;AACH,CAAC","sourcesContent":["import { lstat, open } from \"node:fs/promises\";\nimport type { Stats } from \"node:fs\";\nimport { positive } from \"../domain/errors.ts\";\nimport { inspectionFileFlags } from \"./inspection-file.constants.ts\";\nimport { isDirectInspectionPath } from \"./inspection-path.ts\";\n\n/** Raised when the inspected path was replaced or modified during the read. */\nexport class InspectionFileChanged extends Error {\n constructor() {\n super(\"Inspection file changed\");\n this.name = \"InspectionFileChanged\";\n }\n}\n\nfunction unchanged(before: Stats, after: Stats): boolean {\n return (\n before.dev === after.dev &&\n before.ino === after.ino &&\n before.size === after.size &&\n before.mtimeMs === after.mtimeMs &&\n before.ctimeMs === after.ctimeMs\n );\n}\n\nexport async function readInspectionFile(\n path: string,\n maxBytes: number,\n expected?: Stats,\n): Promise<Buffer> {\n positive(maxBytes, \"maxBytes\");\n const before = await lstat(path);\n if (expected && !unchanged(expected, before))\n throw new InspectionFileChanged();\n if (!before.isFile() || !(await isDirectInspectionPath(path)))\n throw new Error(\"Inspection path changed\");\n if (before.size > maxBytes) throw new Error(\"Inspection file is too large\");\n const file = await open(path, inspectionFileFlags);\n try {\n const opened = await file.stat();\n if (!opened.isFile() || !unchanged(before, opened))\n throw new InspectionFileChanged();\n const buffer = Buffer.alloc(maxBytes + 1);\n let length = 0;\n while (length < buffer.length) {\n const { bytesRead } = await file.read(\n buffer,\n length,\n buffer.length - length,\n length,\n );\n if (!bytesRead) break;\n length += bytesRead;\n }\n if (length > maxBytes) throw new Error(\"Inspection file is too large\");\n if (\n !unchanged(opened, await file.stat()) ||\n !unchanged(opened, await lstat(path))\n )\n throw new InspectionFileChanged();\n return buffer.subarray(0, length);\n } finally {\n await file.close();\n }\n}\n"]}
1
+ {"version":3,"file":"inspection-file.js","sourceRoot":"","sources":["../../src/infrastructure/inspection-file.ts"],"names":[],"mappings":"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","sourcesContent":["import { lstat, open } from \"node:fs/promises\";\nimport type { Stats } from \"node:fs\";\nimport { positive } from \"../domain/errors.ts\";\nimport { inspectionFileFlags } from \"./inspection-file.constants.ts\";\nimport { isDirectInspectionPath } from \"./inspection-path.ts\";\n\n/** Raised when the inspected path was replaced or modified during the read. */\nexport class InspectionFileChanged extends Error {\n constructor() {\n super(\"Inspection file changed\");\n this.name = \"InspectionFileChanged\";\n }\n}\n\nfunction unchanged(before: Stats, after: Stats): boolean {\n return (\n before.dev === after.dev &&\n before.ino === after.ino &&\n before.size === after.size &&\n before.mtimeMs === after.mtimeMs &&\n before.ctimeMs === after.ctimeMs\n );\n}\n\nexport async function readInspectionFile(\n path: string,\n maxBytes: number,\n expected?: Stats,\n): Promise<Buffer> {\n return inspectFile(path, maxBytes, false, expected);\n}\n\nexport async function readInspectionPrefix(\n path: string,\n maxBytes: number,\n expected: Stats,\n): Promise<Buffer> {\n return inspectFile(path, maxBytes, true, expected);\n}\n\nasync function inspectFile(\n path: string,\n maxBytes: number,\n prefix: boolean,\n expected?: Stats,\n): Promise<Buffer> {\n positive(maxBytes, \"maxBytes\");\n const before = await lstat(path);\n if (expected && !unchanged(expected, before))\n throw new InspectionFileChanged();\n if (!before.isFile() || !(await isDirectInspectionPath(path)))\n throw new Error(\"Inspection path changed\");\n if (!prefix && before.size > maxBytes)\n throw new Error(\"Inspection file is too large\");\n const file = await open(path, inspectionFileFlags);\n try {\n const opened = await file.stat();\n if (!opened.isFile() || !unchanged(before, opened))\n throw new InspectionFileChanged();\n const buffer = Buffer.alloc(prefix ? maxBytes : maxBytes + 1);\n let length = 0;\n while (length < buffer.length) {\n const { bytesRead } = await file.read(\n buffer,\n length,\n buffer.length - length,\n length,\n );\n if (!bytesRead) break;\n length += bytesRead;\n }\n if (length > maxBytes) throw new Error(\"Inspection file is too large\");\n if (\n !unchanged(opened, await file.stat()) ||\n !unchanged(opened, await lstat(path))\n )\n throw new InspectionFileChanged();\n return buffer.subarray(0, length);\n } finally {\n await file.close();\n }\n}\n"]}
@@ -5,8 +5,8 @@ import { setTimeout } from "node:timers/promises";
5
5
  import { TransportConflict, transportKey, transportCondition, } from "../domain/transport.js";
6
6
  import { lock } from "./git/lock.js";
7
7
  import { OutpostError } from "../domain/errors.js";
8
- import { InspectionFileChanged, readInspectionFile, } from "./inspection-file.js";
9
- import { decodeObject, encodeObject, readLimit } from "./transport-envelope.js";
8
+ import { InspectionFileChanged, readInspectionFile, readInspectionPrefix, } from "./inspection-file.js";
9
+ import { decodeObject, decodeObjectEntry, encodeObject, readLimit, } from "./transport-envelope.js";
10
10
  import { transportDefaults } from "./transport.constants.js";
11
11
  async function privateDirectory(path, target = true) {
12
12
  const parent = dirname(path);
@@ -41,17 +41,18 @@ async function replaceFile(source, target, signal) {
41
41
  export function createLocalTransport(options) {
42
42
  const root = resolve(options.directory), objects = join(root, "objects");
43
43
  const path = (key) => join(objects, `${transportKey(key)}.object`);
44
- const read = async (key, options = {}) => {
45
- options.signal?.throwIfAborted();
46
- const limit = readLimit(options.maxBytes);
44
+ async function inspect(key, limit, signal, headerOnly = false) {
45
+ signal?.throwIfAborted();
47
46
  try {
48
47
  const target = path(key);
49
48
  for (let attempt = 1;; attempt++) {
50
49
  const info = await lstat(target);
51
50
  try {
52
- const data = await readInspectionFile(target, Math.min(info.size, limit + transportDefaults.headerBytes) || 1, info);
53
- options.signal?.throwIfAborted();
54
- return decodeObject(data, key, limit);
51
+ const data = await (headerOnly ? readInspectionPrefix : readInspectionFile)(target, headerOnly
52
+ ? transportDefaults.headerBytes
53
+ : Math.min(info.size, limit + transportDefaults.headerBytes) || 1, info);
54
+ signal?.throwIfAborted();
55
+ return { data, size: info.size };
55
56
  }
56
57
  catch (error) {
57
58
  // Writers replace objects atomically; read the replacement instead.
@@ -69,6 +70,11 @@ export function createLocalTransport(options) {
69
70
  return undefined;
70
71
  throw error;
71
72
  }
73
+ }
74
+ const read = async (key, options = {}) => {
75
+ const limit = readLimit(options.maxBytes);
76
+ const object = await inspect(key, limit, options.signal);
77
+ return object ? decodeObject(object.data, key, limit) : undefined;
72
78
  };
73
79
  async function mutate(key, options, action) {
74
80
  transportKey(key);
@@ -165,10 +171,9 @@ export function createLocalTransport(options) {
165
171
  for await (const key of scan(objects, "")) {
166
172
  if (!key.startsWith(prefix))
167
173
  continue;
168
- const object = await read(key, options.signal ? { signal: options.signal } : {});
174
+ const object = await inspect(key, transportDefaults.maxBytes, options.signal, true);
169
175
  if (object) {
170
- const { bytes: _bytes, ...entry } = object;
171
- yield entry;
176
+ yield decodeObjectEntry(object.data, key, object.size, transportDefaults.maxBytes);
172
177
  }
173
178
  }
174
179
  },
@@ -1 +1 @@
1
- {"version":3,"file":"local-transport.js","sourceRoot":"","sources":["../../src/infrastructure/local-transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, lstat, open, rename, rm, readdir } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport { setTimeout } from \"node:timers/promises\";\nimport {\n TransportConflict,\n transportKey,\n transportCondition,\n} from \"../domain/transport.ts\";\nimport type {\n Transport,\n TransportWriteOptions,\n} from \"../domain/transport.types.ts\";\nimport type { LocalTransportOptions } from \"./local-transport.types.ts\";\nimport { lock } from \"./git/lock.ts\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport {\n InspectionFileChanged,\n readInspectionFile,\n} from \"./inspection-file.ts\";\nimport { decodeObject, encodeObject, readLimit } from \"./transport-envelope.ts\";\nimport { transportDefaults } from \"./transport.constants.ts\";\n\nasync function privateDirectory(path: string, target = true): Promise<void> {\n const parent = dirname(path);\n if (parent !== path) {\n await privateDirectory(parent, false);\n await mkdir(path, { recursive: true, mode: 0o700 });\n }\n const info = await lstat(path);\n if (info.isDirectory()) return;\n // Root-owned ancestor links belong to the system layout, such as /var on macOS.\n if (!target && info.isSymbolicLink() && info.uid === 0) return;\n throw new Error(\"Transport directories must not be symlinks\");\n}\n\nconst lockedReplacement = new Set([\"EPERM\", \"EACCES\", \"EBUSY\"]);\n\nasync function replaceFile(\n source: string,\n target: string,\n signal?: AbortSignal,\n): Promise<void> {\n for (let attempt = 1; ; attempt++) {\n try {\n return await rename(source, target);\n } catch (error) {\n // Windows refuses to replace a file while a concurrent reader holds it open.\n if (\n process.platform !== \"win32\" ||\n attempt >= transportDefaults.replaceAttempts ||\n !lockedReplacement.has((error as NodeJS.ErrnoException).code ?? \"\")\n )\n throw error;\n await setTimeout(transportDefaults.retryMs, undefined, { signal });\n }\n }\n}\n\nexport function createLocalTransport(\n options: LocalTransportOptions,\n): Transport {\n const root = resolve(options.directory),\n objects = join(root, \"objects\");\n const path = (key: string) => join(objects, `${transportKey(key)}.object`);\n const read: Transport[\"read\"] = async (key, options = {}) => {\n options.signal?.throwIfAborted();\n const limit = readLimit(options.maxBytes);\n try {\n const target = path(key);\n for (let attempt = 1; ; attempt++) {\n const info = await lstat(target);\n try {\n const data = await readInspectionFile(\n target,\n Math.min(info.size, limit + transportDefaults.headerBytes) || 1,\n info,\n );\n options.signal?.throwIfAborted();\n return decodeObject(data, key, limit);\n } catch (error) {\n // Writers replace objects atomically; read the replacement instead.\n if (\n !(error instanceof InspectionFileChanged) ||\n attempt >= transportDefaults.replacedReadAttempts\n )\n throw error;\n }\n }\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n )\n return undefined;\n throw error;\n }\n };\n async function mutate<T>(\n key: string,\n options: TransportWriteOptions,\n action: () => Promise<T>,\n ): Promise<T> {\n transportKey(key);\n transportCondition(options.ifRevision);\n await privateDirectory(root);\n const signal = AbortSignal.any([\n AbortSignal.timeout(transportDefaults.lockMs),\n ...(options.signal ? [options.signal] : []),\n ]);\n let release: (() => Promise<void>) | undefined;\n while (!release) {\n signal.throwIfAborted();\n try {\n release = await lock(root, key);\n } catch (error) {\n if (!(error instanceof OutpostError) || error.code !== \"conflict\")\n throw error;\n await setTimeout(transportDefaults.retryMs, undefined, { signal });\n }\n }\n try {\n if ((await read(key))?.revision !== (options.ifRevision ?? undefined))\n throw new TransportConflict(key);\n options.signal?.throwIfAborted();\n return await action();\n } finally {\n await release();\n }\n }\n return {\n name: \"local\",\n read,\n write(key, input, options) {\n const bytes = Buffer.from(input);\n return mutate(key, options, async () => {\n const target = path(key);\n await privateDirectory(dirname(target));\n const { entry, data } = encodeObject(key, bytes);\n const temporary = `${target}.${randomUUID()}.tmp`;\n try {\n const file = await open(temporary, \"wx\", 0o600);\n try {\n await file.writeFile(data, { signal: options.signal });\n await file.sync();\n } finally {\n await file.close();\n }\n options.signal?.throwIfAborted();\n await replaceFile(temporary, target, options.signal);\n if (process.platform !== \"win32\") {\n const parent = await open(dirname(target), \"r\");\n try {\n await parent.sync();\n } finally {\n await parent.close();\n }\n }\n return entry;\n } finally {\n await rm(temporary, { force: true });\n }\n });\n },\n remove(key, options) {\n if (options.ifRevision === null)\n return Promise.reject(\n new Error(\"Transport removal requires an existing revision\"),\n );\n return mutate(key, options, () => rm(path(key), { force: true }));\n },\n async *list(prefix = \"\", options = {}) {\n if (prefix) transportKey(prefix.replace(/\\/$/, \"\"));\n async function* scan(\n directory: string,\n base: string,\n ): AsyncIterable<string> {\n const entries = await readdir(directory, { withFileTypes: true }).catch(\n (error) => {\n if (error.code === \"ENOENT\") return [];\n throw error;\n },\n );\n for (const entry of entries) {\n options.signal?.throwIfAborted();\n const name = `${base}${entry.name}`;\n if (entry.isDirectory())\n yield* scan(join(directory, entry.name), `${name}/`);\n if (entry.isFile() && name.endsWith(\".object\"))\n yield name.slice(0, -7);\n if (entry.isSymbolicLink())\n throw new Error(\"Transport objects must not be symlinks\");\n }\n }\n for await (const key of scan(objects, \"\")) {\n if (!key.startsWith(prefix)) continue;\n const object = await read(\n key,\n options.signal ? { signal: options.signal } : {},\n );\n if (object) {\n const { bytes: _bytes, ...entry } = object;\n yield entry;\n }\n }\n },\n };\n}\n"]}
1
+ {"version":3,"file":"local-transport.js","sourceRoot":"","sources":["../../src/infrastructure/local-transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, lstat, open, rename, rm, readdir } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport { setTimeout } from \"node:timers/promises\";\nimport {\n TransportConflict,\n transportKey,\n transportCondition,\n} from \"../domain/transport.ts\";\nimport type {\n Transport,\n TransportWriteOptions,\n} from \"../domain/transport.types.ts\";\nimport type { LocalTransportOptions } from \"./local-transport.types.ts\";\nimport { lock } from \"./git/lock.ts\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport {\n InspectionFileChanged,\n readInspectionFile,\n readInspectionPrefix,\n} from \"./inspection-file.ts\";\nimport {\n decodeObject,\n decodeObjectEntry,\n encodeObject,\n readLimit,\n} from \"./transport-envelope.ts\";\nimport { transportDefaults } from \"./transport.constants.ts\";\n\nasync function privateDirectory(path: string, target = true): Promise<void> {\n const parent = dirname(path);\n if (parent !== path) {\n await privateDirectory(parent, false);\n await mkdir(path, { recursive: true, mode: 0o700 });\n }\n const info = await lstat(path);\n if (info.isDirectory()) return;\n // Root-owned ancestor links belong to the system layout, such as /var on macOS.\n if (!target && info.isSymbolicLink() && info.uid === 0) return;\n throw new Error(\"Transport directories must not be symlinks\");\n}\n\nconst lockedReplacement = new Set([\"EPERM\", \"EACCES\", \"EBUSY\"]);\n\nasync function replaceFile(\n source: string,\n target: string,\n signal?: AbortSignal,\n): Promise<void> {\n for (let attempt = 1; ; attempt++) {\n try {\n return await rename(source, target);\n } catch (error) {\n // Windows refuses to replace a file while a concurrent reader holds it open.\n if (\n process.platform !== \"win32\" ||\n attempt >= transportDefaults.replaceAttempts ||\n !lockedReplacement.has((error as NodeJS.ErrnoException).code ?? \"\")\n )\n throw error;\n await setTimeout(transportDefaults.retryMs, undefined, { signal });\n }\n }\n}\n\nexport function createLocalTransport(\n options: LocalTransportOptions,\n): Transport {\n const root = resolve(options.directory),\n objects = join(root, \"objects\");\n const path = (key: string) => join(objects, `${transportKey(key)}.object`);\n async function inspect(\n key: string,\n limit: number,\n signal?: AbortSignal,\n headerOnly = false,\n ) {\n signal?.throwIfAborted();\n try {\n const target = path(key);\n for (let attempt = 1; ; attempt++) {\n const info = await lstat(target);\n try {\n const data = await (\n headerOnly ? readInspectionPrefix : readInspectionFile\n )(\n target,\n headerOnly\n ? transportDefaults.headerBytes\n : Math.min(info.size, limit + transportDefaults.headerBytes) || 1,\n info,\n );\n signal?.throwIfAborted();\n return { data, size: info.size };\n } catch (error) {\n // Writers replace objects atomically; read the replacement instead.\n if (\n !(error instanceof InspectionFileChanged) ||\n attempt >= transportDefaults.replacedReadAttempts\n )\n throw error;\n }\n }\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n )\n return undefined;\n throw error;\n }\n }\n const read: Transport[\"read\"] = async (key, options = {}) => {\n const limit = readLimit(options.maxBytes);\n const object = await inspect(key, limit, options.signal);\n return object ? decodeObject(object.data, key, limit) : undefined;\n };\n async function mutate<T>(\n key: string,\n options: TransportWriteOptions,\n action: () => Promise<T>,\n ): Promise<T> {\n transportKey(key);\n transportCondition(options.ifRevision);\n await privateDirectory(root);\n const signal = AbortSignal.any([\n AbortSignal.timeout(transportDefaults.lockMs),\n ...(options.signal ? [options.signal] : []),\n ]);\n let release: (() => Promise<void>) | undefined;\n while (!release) {\n signal.throwIfAborted();\n try {\n release = await lock(root, key);\n } catch (error) {\n if (!(error instanceof OutpostError) || error.code !== \"conflict\")\n throw error;\n await setTimeout(transportDefaults.retryMs, undefined, { signal });\n }\n }\n try {\n if ((await read(key))?.revision !== (options.ifRevision ?? undefined))\n throw new TransportConflict(key);\n options.signal?.throwIfAborted();\n return await action();\n } finally {\n await release();\n }\n }\n return {\n name: \"local\",\n read,\n write(key, input, options) {\n const bytes = Buffer.from(input);\n return mutate(key, options, async () => {\n const target = path(key);\n await privateDirectory(dirname(target));\n const { entry, data } = encodeObject(key, bytes);\n const temporary = `${target}.${randomUUID()}.tmp`;\n try {\n const file = await open(temporary, \"wx\", 0o600);\n try {\n await file.writeFile(data, { signal: options.signal });\n await file.sync();\n } finally {\n await file.close();\n }\n options.signal?.throwIfAborted();\n await replaceFile(temporary, target, options.signal);\n if (process.platform !== \"win32\") {\n const parent = await open(dirname(target), \"r\");\n try {\n await parent.sync();\n } finally {\n await parent.close();\n }\n }\n return entry;\n } finally {\n await rm(temporary, { force: true });\n }\n });\n },\n remove(key, options) {\n if (options.ifRevision === null)\n return Promise.reject(\n new Error(\"Transport removal requires an existing revision\"),\n );\n return mutate(key, options, () => rm(path(key), { force: true }));\n },\n async *list(prefix = \"\", options = {}) {\n if (prefix) transportKey(prefix.replace(/\\/$/, \"\"));\n async function* scan(\n directory: string,\n base: string,\n ): AsyncIterable<string> {\n const entries = await readdir(directory, { withFileTypes: true }).catch(\n (error) => {\n if (error.code === \"ENOENT\") return [];\n throw error;\n },\n );\n for (const entry of entries) {\n options.signal?.throwIfAborted();\n const name = `${base}${entry.name}`;\n if (entry.isDirectory())\n yield* scan(join(directory, entry.name), `${name}/`);\n if (entry.isFile() && name.endsWith(\".object\"))\n yield name.slice(0, -7);\n if (entry.isSymbolicLink())\n throw new Error(\"Transport objects must not be symlinks\");\n }\n }\n for await (const key of scan(objects, \"\")) {\n if (!key.startsWith(prefix)) continue;\n const object = await inspect(\n key,\n transportDefaults.maxBytes,\n options.signal,\n true,\n );\n if (object) {\n yield decodeObjectEntry(\n object.data,\n key,\n object.size,\n transportDefaults.maxBytes,\n );\n }\n }\n },\n };\n}\n"]}
@@ -2,5 +2,6 @@ export declare const processDefaults: Readonly<{
2
2
  deadlineMs: 600000;
3
3
  retainBytes: 65536;
4
4
  killGraceMs: 500;
5
+ outputDrainMs: 500;
5
6
  }>;
6
7
  export declare const outputChannels: readonly ["stdout", "stderr"];
@@ -2,6 +2,7 @@ export const processDefaults = Object.freeze({
2
2
  deadlineMs: 600_000,
3
3
  retainBytes: 65_536,
4
4
  killGraceMs: 500,
5
+ outputDrainMs: 500,
5
6
  });
6
7
  export const outputChannels = ["stdout", "stderr"];
7
8
  //# sourceMappingURL=process.constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"process.constants.js","sourceRoot":"","sources":["../../src/infrastructure/process.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3C,UAAU,EAAE,OAAO;IACnB,WAAW,EAAE,MAAM;IACnB,WAAW,EAAE,GAAG;CACjB,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC","sourcesContent":["export const processDefaults = Object.freeze({\n deadlineMs: 600_000,\n retainBytes: 65_536,\n killGraceMs: 500,\n});\nexport const outputChannels = [\"stdout\", \"stderr\"] as const;\n"]}
1
+ {"version":3,"file":"process.constants.js","sourceRoot":"","sources":["../../src/infrastructure/process.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3C,UAAU,EAAE,OAAO;IACnB,WAAW,EAAE,MAAM;IACnB,WAAW,EAAE,GAAG;IAChB,aAAa,EAAE,GAAG;CACnB,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAU,CAAC","sourcesContent":["export const processDefaults = Object.freeze({\n deadlineMs: 600_000,\n retainBytes: 65_536,\n killGraceMs: 500,\n outputDrainMs: 500,\n});\nexport const outputChannels = [\"stdout\", \"stderr\"] as const;\n"]}
@@ -2,6 +2,7 @@ import type { Command, CommandResult } from "../domain/command.types.ts";
2
2
  import type { Executor } from "./process.types.ts";
3
3
  export type { Executor } from "./process.types.ts";
4
4
  export declare const executeProcess: Executor;
5
+ export declare const executeProcessWithEnvironment: (command: Command, environment: NodeJS.ProcessEnv) => Promise<CommandResult>;
5
6
  export declare function requireSuccess(command: Command, executor?: Executor): Promise<CommandResult>;
6
7
  export declare function shell(script: string): Pick<Command, "executable" | "arguments">;
7
8
  export declare function quote(value: string): string;
@@ -3,7 +3,11 @@ import { StringDecoder } from "node:string_decoder";
3
3
  import { OutpostError, positive } from "../domain/errors.js";
4
4
  import { outputChannels, processDefaults } from "./process.constants.js";
5
5
  import { restoreTerminal } from "./terminal.js";
6
- export const executeProcess = (command) => {
6
+ export const executeProcess = (command) => executeProcessWithEnvironment(command, {
7
+ ...process.env,
8
+ ...command.variables,
9
+ });
10
+ export const executeProcessWithEnvironment = (command, environment) => {
7
11
  command.signal?.throwIfAborted();
8
12
  const deadline = command.deadlineMs ?? processDefaults.deadlineMs;
9
13
  positive(deadline, "deadlineMs");
@@ -13,7 +17,7 @@ export const executeProcess = (command) => {
13
17
  const interactive = command.interactive === true;
14
18
  const child = spawn(command.executable, [...(command.arguments ?? [])], {
15
19
  cwd: command.directory,
16
- env: { ...process.env, ...command.variables },
20
+ env: environment,
17
21
  shell: false,
18
22
  windowsHide: true,
19
23
  detached: !interactive && process.platform !== "win32",
@@ -24,6 +28,7 @@ export const executeProcess = (command) => {
24
28
  stderr: new StringDecoder("utf8"),
25
29
  };
26
30
  const output = { stdout: "", stderr: "" };
31
+ let settled = false, exited = false, closed = false, status = null, drainage;
27
32
  let failed = false, reason, escalation;
28
33
  function kill(hard) {
29
34
  if (!child.pid)
@@ -50,12 +55,17 @@ export const executeProcess = (command) => {
50
55
  }
51
56
  }
52
57
  function interrupt(error) {
53
- if (failed)
58
+ if (failed || settled)
54
59
  return;
55
60
  failed = true;
56
61
  reason = error;
57
62
  kill(false);
58
- escalation = setTimeout(() => kill(true), processDefaults.killGraceMs);
63
+ escalation = setTimeout(() => {
64
+ escalation = undefined;
65
+ kill(true);
66
+ if (closed)
67
+ finish();
68
+ }, processDefaults.killGraceMs);
59
69
  }
60
70
  const abort = () => interrupt(command.signal?.reason ??
61
71
  new OutpostError("aborted", "Command cancelled"));
@@ -63,6 +73,8 @@ export const executeProcess = (command) => {
63
73
  deadlineMs: deadline,
64
74
  })), deadline);
65
75
  const consume = (channel, text) => {
76
+ if (settled)
77
+ return;
66
78
  output[channel] = (output[channel] + text).slice(-limit);
67
79
  try {
68
80
  command.observe?.(channel, text);
@@ -84,25 +96,53 @@ export const executeProcess = (command) => {
84
96
  command.signal?.addEventListener("abort", abort, { once: true });
85
97
  if (command.signal?.aborted)
86
98
  abort();
87
- child.on("close", (status) => {
88
- if (interactive)
89
- restoreTerminal();
99
+ function disconnectInput() {
90
100
  if (child.stdin) {
91
101
  command.terminal?.input?.unpipe(child.stdin);
92
102
  command.input?.unpipe(child.stdin);
103
+ child.stdin.destroy();
93
104
  }
105
+ }
106
+ function finish() {
107
+ if (settled || escalation)
108
+ return;
109
+ if (interactive)
110
+ restoreTerminal();
111
+ disconnectInput();
94
112
  clearTimeout(timer);
95
- clearTimeout(escalation);
113
+ clearTimeout(drainage);
96
114
  command.signal?.removeEventListener("abort", abort);
97
115
  for (const channel of outputChannels) {
98
116
  const tail = decoder[channel].end();
99
117
  if (tail)
100
118
  consume(channel, tail);
101
119
  }
120
+ if (escalation)
121
+ return;
122
+ settled = true;
123
+ child.stdout?.destroy();
124
+ child.stderr?.destroy();
102
125
  if (failed)
103
126
  reject(reason);
104
127
  else
105
128
  resolve({ status: status ?? 1, ...output });
129
+ }
130
+ child.on("exit", (code) => {
131
+ exited = true;
132
+ status = code;
133
+ clearTimeout(timer);
134
+ command.signal?.removeEventListener("abort", abort);
135
+ disconnectInput();
136
+ drainage = setTimeout(() => {
137
+ closed = true;
138
+ finish();
139
+ }, processDefaults.outputDrainMs);
140
+ });
141
+ child.on("close", (code) => {
142
+ closed = true;
143
+ if (!exited)
144
+ status = code;
145
+ finish();
106
146
  });
107
147
  connectStdin(child.stdin, command);
108
148
  if (child.stdout && command.terminal?.output)
@@ -1 +1 @@
1
- {"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/infrastructure/process.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport type { Writable } from \"node:stream\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport type {\n Channel,\n Command,\n CommandResult,\n} from \"../domain/command.types.ts\";\nimport { OutpostError, positive } from \"../domain/errors.ts\";\nimport { outputChannels, processDefaults } from \"./process.constants.ts\";\nimport type { Executor } from \"./process.types.ts\";\nimport { restoreTerminal } from \"./terminal.ts\";\n\nexport type { Executor } from \"./process.types.ts\";\n\nexport const executeProcess: Executor = (command) => {\n command.signal?.throwIfAborted();\n const deadline = command.deadlineMs ?? processDefaults.deadlineMs;\n positive(deadline, \"deadlineMs\");\n const limit = command.retain ?? processDefaults.retainBytes;\n positive(limit, \"retain\");\n return new Promise((resolve, reject) => {\n const interactive = command.interactive === true;\n const child = spawn(command.executable, [...(command.arguments ?? [])], {\n cwd: command.directory,\n env: { ...process.env, ...command.variables },\n shell: false,\n windowsHide: true,\n detached: !interactive && process.platform !== \"win32\",\n stdio:\n interactive && !command.terminal ? \"inherit\" : [\"pipe\", \"pipe\", \"pipe\"],\n });\n const decoder = {\n stdout: new StringDecoder(\"utf8\"),\n stderr: new StringDecoder(\"utf8\"),\n };\n const output = { stdout: \"\", stderr: \"\" };\n let failed = false,\n reason: unknown,\n escalation: ReturnType<typeof setTimeout> | undefined;\n function kill(hard: boolean): void {\n if (!child.pid) return;\n if (process.platform === \"win32\") {\n const killer = spawn(\n \"taskkill\",\n [\"/PID\", String(child.pid), \"/T\", \"/F\"],\n { windowsHide: true, stdio: \"ignore\" },\n );\n killer.on(\"error\", () => {\n child.kill();\n });\n killer.on(\"exit\", (status) => {\n if (status !== 0) child.kill();\n });\n if (hard) child.kill();\n } else {\n try {\n process.kill(\n interactive ? child.pid : -child.pid,\n hard ? \"SIGKILL\" : \"SIGTERM\",\n );\n } catch {\n child.kill(hard ? \"SIGKILL\" : \"SIGTERM\");\n }\n }\n }\n function interrupt(error: unknown): void {\n if (failed) return;\n failed = true;\n reason = error;\n kill(false);\n escalation = setTimeout(() => kill(true), processDefaults.killGraceMs);\n }\n const abort = () =>\n interrupt(\n command.signal?.reason ??\n new OutpostError(\"aborted\", \"Command cancelled\"),\n );\n const timer = setTimeout(\n () =>\n interrupt(\n new OutpostError(\"timeout\", `Command exceeded ${deadline} ms`, {\n deadlineMs: deadline,\n }),\n ),\n deadline,\n );\n const consume = (channel: Channel, text: string) => {\n output[channel] = (output[channel] + text).slice(-limit);\n try {\n command.observe?.(channel, text);\n } catch (error) {\n interrupt(error);\n }\n };\n child.stdout?.on(\"data\", (data: Buffer) =>\n consume(\"stdout\", decoder.stdout.write(data)),\n );\n child.stderr?.on(\"data\", (data: Buffer) =>\n consume(\"stderr\", decoder.stderr.write(data)),\n );\n child.stdin?.on(\"error\", (error) => {\n if ((error as NodeJS.ErrnoException).code !== \"EPIPE\") interrupt(error);\n });\n child.on(\"error\", (error) => {\n failed = true;\n reason = error;\n });\n command.signal?.addEventListener(\"abort\", abort, { once: true });\n if (command.signal?.aborted) abort();\n child.on(\"close\", (status) => {\n if (interactive) restoreTerminal();\n if (child.stdin) {\n command.terminal?.input?.unpipe(child.stdin);\n command.input?.unpipe(child.stdin);\n }\n clearTimeout(timer);\n clearTimeout(escalation);\n command.signal?.removeEventListener(\"abort\", abort);\n for (const channel of outputChannels) {\n const tail = decoder[channel].end();\n if (tail) consume(channel, tail);\n }\n if (failed) reject(reason);\n else resolve({ status: status ?? 1, ...output });\n });\n connectStdin(child.stdin, command);\n if (child.stdout && command.terminal?.output)\n child.stdout.pipe(command.terminal.output, { end: false });\n if (child.stderr && command.terminal?.error)\n child.stderr.pipe(command.terminal.error, { end: false });\n });\n};\n\nfunction connectStdin(stdin: Writable | null, command: Command): void {\n if (!stdin) return;\n if (command.terminal?.input) {\n command.terminal.input.pipe(stdin);\n return;\n }\n if (!command.input) {\n stdin.end(command.stdin);\n return;\n }\n if (command.stdin) stdin.write(command.stdin);\n command.input.pipe(stdin);\n}\n\nexport async function requireSuccess(\n command: Command,\n executor = executeProcess,\n): Promise<CommandResult> {\n const result = await executor(command);\n if (result.status !== 0)\n throw new OutpostError(\n \"process\",\n `${command.executable} exited with status ${result.status}`,\n { ...result },\n );\n return result;\n}\n\nexport function shell(\n script: string,\n): Pick<Command, \"executable\" | \"arguments\"> {\n return process.platform === \"win32\"\n ? {\n executable: \"powershell.exe\",\n arguments: [\"-NoProfile\", \"-NonInteractive\", \"-Command\", script],\n }\n : { executable: \"sh\", arguments: [\"-c\", script] };\n}\n\nexport function quote(value: string): string {\n if (value.includes(\"\\0\"))\n throw new OutpostError(\n \"configuration\",\n \"A command argument cannot contain NUL\",\n );\n return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n"]}
1
+ {"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/infrastructure/process.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport type { Writable } from \"node:stream\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport type {\n Channel,\n Command,\n CommandResult,\n} from \"../domain/command.types.ts\";\nimport { OutpostError, positive } from \"../domain/errors.ts\";\nimport { outputChannels, processDefaults } from \"./process.constants.ts\";\nimport type { Executor } from \"./process.types.ts\";\nimport { restoreTerminal } from \"./terminal.ts\";\n\nexport type { Executor } from \"./process.types.ts\";\n\nexport const executeProcess: Executor = (command) =>\n executeProcessWithEnvironment(command, {\n ...process.env,\n ...command.variables,\n });\n\nexport const executeProcessWithEnvironment = (\n command: Command,\n environment: NodeJS.ProcessEnv,\n): Promise<CommandResult> => {\n command.signal?.throwIfAborted();\n const deadline = command.deadlineMs ?? processDefaults.deadlineMs;\n positive(deadline, \"deadlineMs\");\n const limit = command.retain ?? processDefaults.retainBytes;\n positive(limit, \"retain\");\n return new Promise((resolve, reject) => {\n const interactive = command.interactive === true;\n const child = spawn(command.executable, [...(command.arguments ?? [])], {\n cwd: command.directory,\n env: environment,\n shell: false,\n windowsHide: true,\n detached: !interactive && process.platform !== \"win32\",\n stdio:\n interactive && !command.terminal ? \"inherit\" : [\"pipe\", \"pipe\", \"pipe\"],\n });\n const decoder = {\n stdout: new StringDecoder(\"utf8\"),\n stderr: new StringDecoder(\"utf8\"),\n };\n const output = { stdout: \"\", stderr: \"\" };\n let settled = false,\n exited = false,\n closed = false,\n status: number | null = null,\n drainage: ReturnType<typeof setTimeout> | undefined;\n let failed = false,\n reason: unknown,\n escalation: ReturnType<typeof setTimeout> | undefined;\n function kill(hard: boolean): void {\n if (!child.pid) return;\n if (process.platform === \"win32\") {\n const killer = spawn(\n \"taskkill\",\n [\"/PID\", String(child.pid), \"/T\", \"/F\"],\n { windowsHide: true, stdio: \"ignore\" },\n );\n killer.on(\"error\", () => {\n child.kill();\n });\n killer.on(\"exit\", (status) => {\n if (status !== 0) child.kill();\n });\n if (hard) child.kill();\n } else {\n try {\n process.kill(\n interactive ? child.pid : -child.pid,\n hard ? \"SIGKILL\" : \"SIGTERM\",\n );\n } catch {\n child.kill(hard ? \"SIGKILL\" : \"SIGTERM\");\n }\n }\n }\n function interrupt(error: unknown): void {\n if (failed || settled) return;\n failed = true;\n reason = error;\n kill(false);\n escalation = setTimeout(() => {\n escalation = undefined;\n kill(true);\n if (closed) finish();\n }, processDefaults.killGraceMs);\n }\n const abort = () =>\n interrupt(\n command.signal?.reason ??\n new OutpostError(\"aborted\", \"Command cancelled\"),\n );\n const timer = setTimeout(\n () =>\n interrupt(\n new OutpostError(\"timeout\", `Command exceeded ${deadline} ms`, {\n deadlineMs: deadline,\n }),\n ),\n deadline,\n );\n const consume = (channel: Channel, text: string) => {\n if (settled) return;\n output[channel] = (output[channel] + text).slice(-limit);\n try {\n command.observe?.(channel, text);\n } catch (error) {\n interrupt(error);\n }\n };\n child.stdout?.on(\"data\", (data: Buffer) =>\n consume(\"stdout\", decoder.stdout.write(data)),\n );\n child.stderr?.on(\"data\", (data: Buffer) =>\n consume(\"stderr\", decoder.stderr.write(data)),\n );\n child.stdin?.on(\"error\", (error) => {\n if ((error as NodeJS.ErrnoException).code !== \"EPIPE\") interrupt(error);\n });\n child.on(\"error\", (error) => {\n failed = true;\n reason = error;\n });\n command.signal?.addEventListener(\"abort\", abort, { once: true });\n if (command.signal?.aborted) abort();\n function disconnectInput(): void {\n if (child.stdin) {\n command.terminal?.input?.unpipe(child.stdin);\n command.input?.unpipe(child.stdin);\n child.stdin.destroy();\n }\n }\n function finish(): void {\n if (settled || escalation) return;\n if (interactive) restoreTerminal();\n disconnectInput();\n clearTimeout(timer);\n clearTimeout(drainage);\n command.signal?.removeEventListener(\"abort\", abort);\n for (const channel of outputChannels) {\n const tail = decoder[channel].end();\n if (tail) consume(channel, tail);\n }\n if (escalation) return;\n settled = true;\n child.stdout?.destroy();\n child.stderr?.destroy();\n if (failed) reject(reason);\n else resolve({ status: status ?? 1, ...output });\n }\n child.on(\"exit\", (code) => {\n exited = true;\n status = code;\n clearTimeout(timer);\n command.signal?.removeEventListener(\"abort\", abort);\n disconnectInput();\n drainage = setTimeout(() => {\n closed = true;\n finish();\n }, processDefaults.outputDrainMs);\n });\n child.on(\"close\", (code) => {\n closed = true;\n if (!exited) status = code;\n finish();\n });\n connectStdin(child.stdin, command);\n if (child.stdout && command.terminal?.output)\n child.stdout.pipe(command.terminal.output, { end: false });\n if (child.stderr && command.terminal?.error)\n child.stderr.pipe(command.terminal.error, { end: false });\n });\n};\n\nfunction connectStdin(stdin: Writable | null, command: Command): void {\n if (!stdin) return;\n if (command.terminal?.input) {\n command.terminal.input.pipe(stdin);\n return;\n }\n if (!command.input) {\n stdin.end(command.stdin);\n return;\n }\n if (command.stdin) stdin.write(command.stdin);\n command.input.pipe(stdin);\n}\n\nexport async function requireSuccess(\n command: Command,\n executor = executeProcess,\n): Promise<CommandResult> {\n const result = await executor(command);\n if (result.status !== 0)\n throw new OutpostError(\n \"process\",\n `${command.executable} exited with status ${result.status}`,\n { ...result },\n );\n return result;\n}\n\nexport function shell(\n script: string,\n): Pick<Command, \"executable\" | \"arguments\"> {\n return process.platform === \"win32\"\n ? {\n executable: \"powershell.exe\",\n arguments: [\"-NoProfile\", \"-NonInteractive\", \"-Command\", script],\n }\n : { executable: \"sh\", arguments: [\"-c\", script] };\n}\n\nexport function quote(value: string): string {\n if (value.includes(\"\\0\"))\n throw new OutpostError(\n \"configuration\",\n \"A command argument cannot contain NUL\",\n );\n return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { ReservationLedger } from "./transport-reservations.types.ts";
2
+ export declare function reservationLedger(value: unknown): ReservationLedger;
@@ -0,0 +1,84 @@
1
+ import { invariant } from "../domain/errors.js";
2
+ import { reservationIdPattern } from "./transport-reservations.constants.js";
3
+ function record(value) {
4
+ invariant(value &&
5
+ typeof value === "object" &&
6
+ "bytes" in value &&
7
+ typeof value.bytes === "number" &&
8
+ Number.isSafeInteger(value.bytes) &&
9
+ value.bytes >= 0, "Invalid reservation entry");
10
+ if (!("owner" in value))
11
+ return { bytes: value.bytes };
12
+ const owner = value.owner;
13
+ invariant(owner &&
14
+ typeof owner === "object" &&
15
+ "id" in owner &&
16
+ typeof owner.id === "string" &&
17
+ reservationIdPattern.test(owner.id) &&
18
+ "host" in owner &&
19
+ typeof owner.host === "string" &&
20
+ owner.host.length > 0 &&
21
+ "pid" in owner &&
22
+ typeof owner.pid === "number" &&
23
+ Number.isSafeInteger(owner.pid) &&
24
+ owner.pid > 0 &&
25
+ "createdAt" in owner &&
26
+ typeof owner.createdAt === "string" &&
27
+ Number.isFinite(Date.parse(owner.createdAt)) &&
28
+ "repository" in owner &&
29
+ typeof owner.repository === "string", "Invalid reservation owner");
30
+ let identity;
31
+ if ("identity" in owner) {
32
+ const value = owner.identity;
33
+ invariant(value &&
34
+ typeof value === "object" &&
35
+ "host" in value &&
36
+ typeof value.host === "string" &&
37
+ value.host.length > 0 &&
38
+ "boot" in value &&
39
+ typeof value.boot === "string" &&
40
+ value.boot.length > 0 &&
41
+ "namespace" in value &&
42
+ typeof value.namespace === "string" &&
43
+ value.namespace.length > 0 &&
44
+ "started" in value &&
45
+ typeof value.started === "string" &&
46
+ /^\d+$/.test(value.started), "Invalid reservation identity");
47
+ identity = {
48
+ host: value.host,
49
+ boot: value.boot,
50
+ namespace: value.namespace,
51
+ started: value.started,
52
+ };
53
+ }
54
+ return {
55
+ bytes: value.bytes,
56
+ owner: {
57
+ id: owner.id,
58
+ host: owner.host,
59
+ pid: owner.pid,
60
+ createdAt: owner.createdAt,
61
+ repository: owner.repository,
62
+ ...(identity ? { identity } : {}),
63
+ },
64
+ };
65
+ }
66
+ export function reservationLedger(value) {
67
+ if (value === undefined)
68
+ return { format: 2, reservations: {} };
69
+ invariant(value &&
70
+ typeof value === "object" &&
71
+ "format" in value &&
72
+ (value.format === 1 || value.format === 2) &&
73
+ "reservations" in value &&
74
+ value.reservations &&
75
+ typeof value.reservations === "object" &&
76
+ !Array.isArray(value.reservations), "Invalid reservation ledger");
77
+ const legacy = value.format === 1;
78
+ const entries = Object.entries(value.reservations).map(([id, entry]) => {
79
+ invariant(reservationIdPattern.test(id), "Invalid reservation identifier");
80
+ return [id, record(legacy ? { bytes: entry } : entry)];
81
+ });
82
+ return { format: 2, reservations: Object.fromEntries(entries) };
83
+ }
84
+ //# sourceMappingURL=reservation-ledger.js.map