@the-open-engine/zeroshot 6.38.0 → 6.39.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/cli/event-copy.js +8 -7
  2. package/cli/event-copy.ts +12 -0
  3. package/cli/index.js +7 -31
  4. package/cli/json-export.js +61 -64
  5. package/cli/json-export.ts +112 -0
  6. package/cli/message-formatter-utils.js +68 -56
  7. package/cli/message-formatter-utils.ts +121 -0
  8. package/cli/message-formatters-normal.js +124 -259
  9. package/cli/message-formatters-normal.ts +250 -0
  10. package/cli/message-formatters-watch.js +81 -84
  11. package/cli/message-formatters-watch.ts +189 -0
  12. package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
  13. package/lib/agent-cli-provider/adapters/codex.js +3 -1
  14. package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
  15. package/lib/cluster/generated/protocol-schema.cjs +1 -1
  16. package/lib/cluster/generated/protocol-schema.mjs +1 -1
  17. package/lib/cluster/generated/protocol.d.cts +8 -0
  18. package/lib/cluster/generated/protocol.d.mts +8 -0
  19. package/lib/cluster/generated/protocol.d.ts +8 -0
  20. package/lib/clusters-registry.d.ts +23 -0
  21. package/lib/clusters-registry.js +17 -29
  22. package/lib/completion.d.ts +12 -0
  23. package/lib/completion.js +84 -94
  24. package/lib/compose-utils.d.ts +32 -0
  25. package/lib/compose-utils.js +57 -72
  26. package/lib/detached-startup.d.ts +83 -0
  27. package/lib/detached-startup.js +231 -302
  28. package/lib/docker-config.d.ts +43 -0
  29. package/lib/docker-config.js +150 -325
  30. package/lib/docker-env-auth.d.ts +17 -0
  31. package/lib/docker-env-auth.js +75 -0
  32. package/lib/git-remote-utils.d.ts +48 -0
  33. package/lib/git-remote-utils.js +147 -213
  34. package/lib/id-detector.d.ts +15 -0
  35. package/lib/id-detector.js +37 -41
  36. package/lib/path-check.d.ts +30 -0
  37. package/lib/path-check.js +42 -45
  38. package/lib/process-liveness.d.ts +16 -0
  39. package/lib/process-liveness.js +19 -12
  40. package/lib/provider-credential-path.d.ts +16 -0
  41. package/lib/provider-credential-path.js +31 -29
  42. package/lib/provider-defaults.d.ts +30 -0
  43. package/lib/provider-defaults.js +47 -42
  44. package/lib/provider-detection.d.ts +11 -0
  45. package/lib/provider-detection.js +91 -54
  46. package/lib/provider-names.d.ts +38 -0
  47. package/lib/provider-names.js +56 -64
  48. package/lib/repo-settings.d.ts +28 -0
  49. package/lib/repo-settings.js +83 -59
  50. package/lib/run-mode.d.ts +21 -0
  51. package/lib/run-mode.js +21 -20
  52. package/lib/run-plan.d.ts +28 -0
  53. package/lib/run-plan.js +17 -16
  54. package/lib/settings/claude-auth.d.ts +35 -0
  55. package/lib/settings/claude-auth.js +30 -47
  56. package/lib/settings-defaults.d.ts +20 -0
  57. package/lib/settings-defaults.js +149 -0
  58. package/lib/settings-error.d.ts +7 -0
  59. package/lib/settings-error.js +8 -0
  60. package/lib/settings-issue-providers.d.ts +10 -0
  61. package/lib/settings-issue-providers.js +12 -0
  62. package/lib/settings-models.d.ts +22 -0
  63. package/lib/settings-models.js +93 -0
  64. package/lib/settings-storage.d.ts +23 -0
  65. package/lib/settings-storage.js +205 -0
  66. package/lib/settings-validation.d.ts +7 -0
  67. package/lib/settings-validation.js +182 -0
  68. package/lib/settings.d.ts +29 -0
  69. package/lib/settings.js +41 -736
  70. package/lib/setup-apply-types.d.ts +66 -0
  71. package/lib/setup-apply-types.js +2 -0
  72. package/lib/setup-apply.d.ts +39 -0
  73. package/lib/setup-apply.js +267 -264
  74. package/lib/setup-journal.d.ts +41 -0
  75. package/lib/setup-journal.js +119 -76
  76. package/lib/setup-plan-types.d.ts +102 -0
  77. package/lib/setup-plan-types.js +2 -0
  78. package/lib/setup-plan.d.ts +30 -0
  79. package/lib/setup-plan.js +300 -324
  80. package/lib/setup-undo.d.ts +44 -0
  81. package/lib/setup-undo.js +61 -74
  82. package/lib/start-cluster-config.d.ts +26 -0
  83. package/lib/start-cluster-config.js +56 -0
  84. package/lib/start-cluster-environment.d.ts +40 -0
  85. package/lib/start-cluster-environment.js +134 -0
  86. package/lib/start-cluster-run-options.d.ts +53 -0
  87. package/lib/start-cluster-run-options.js +147 -0
  88. package/lib/start-cluster.d.ts +64 -0
  89. package/lib/start-cluster.js +98 -454
  90. package/lib/stream-json-parser.d.ts +17 -0
  91. package/lib/stream-json-parser.js +51 -52
  92. package/npm-shrinkwrap.json +2 -2
  93. package/package.json +12 -6
  94. package/scripts/postinstall.js +27 -0
  95. package/scripts/rust-distribution.js +23 -14
  96. package/src/agent/agent-command-proofs-context.js +35 -45
  97. package/src/agent/agent-command-proofs-context.ts +87 -0
  98. package/src/agent/agent-config-settings.js +19 -0
  99. package/src/agent/agent-config-settings.ts +41 -0
  100. package/src/agent/agent-config.js +122 -231
  101. package/src/agent/agent-config.ts +285 -0
  102. package/src/agent/agent-context-builder.js +38 -273
  103. package/src/agent/agent-context-builder.ts +51 -0
  104. package/src/agent/agent-context-environment-sections.js +105 -0
  105. package/src/agent/agent-context-environment-sections.ts +134 -0
  106. package/src/agent/agent-context-packs.js +165 -0
  107. package/src/agent/agent-context-packs.ts +296 -0
  108. package/src/agent/agent-context-prompt-sections.js +100 -0
  109. package/src/agent/agent-context-prompt-sections.ts +148 -0
  110. package/src/agent/agent-context-sections.js +25 -334
  111. package/src/agent/agent-context-sections.ts +36 -0
  112. package/src/agent/agent-context-sources.js +96 -149
  113. package/src/agent/agent-context-sources.ts +253 -0
  114. package/src/agent/agent-context-types.js +2 -0
  115. package/src/agent/agent-context-types.ts +132 -0
  116. package/src/agent/agent-context-validation-sections.js +73 -0
  117. package/src/agent/agent-context-validation-sections.ts +129 -0
  118. package/src/agent/agent-input-injector.js +99 -118
  119. package/src/agent/agent-input-injector.ts +195 -0
  120. package/src/agent/agent-liveness-poll.js +74 -78
  121. package/src/agent/agent-liveness-poll.ts +163 -0
  122. package/src/agent/agent-quality-gate-schema.js +77 -86
  123. package/src/agent/agent-quality-gate-schema.ts +135 -0
  124. package/src/agent/agent-quality-gates-context.js +44 -50
  125. package/src/agent/agent-quality-gates-context.ts +91 -0
  126. package/src/agent/agent-stuck-detector.js +171 -239
  127. package/src/agent/agent-stuck-detector.ts +288 -0
  128. package/src/agent/agent-trigger-evaluator.js +29 -46
  129. package/src/agent/agent-trigger-evaluator.ts +98 -0
  130. package/src/agent/context-metrics.js +110 -141
  131. package/src/agent/context-metrics.ts +261 -0
  132. package/src/agent/context-pack-builder.js +72 -358
  133. package/src/agent/context-pack-builder.ts +105 -0
  134. package/src/agent/context-pack-core.js +70 -0
  135. package/src/agent/context-pack-core.ts +96 -0
  136. package/src/agent/context-pack-selection.js +119 -0
  137. package/src/agent/context-pack-selection.ts +187 -0
  138. package/src/agent/context-pack-truncation.js +139 -0
  139. package/src/agent/context-pack-truncation.ts +208 -0
  140. package/src/agent/context-pack-types.js +2 -0
  141. package/src/agent/context-pack-types.ts +98 -0
  142. package/src/agent/context-replay-policy.js +30 -39
  143. package/src/agent/context-replay-policy.ts +71 -0
  144. package/src/agent/critical-agent-policy.js +6 -10
  145. package/src/agent/critical-agent-policy.ts +20 -0
  146. package/src/agent/guidance-queue.js +74 -87
  147. package/src/agent/guidance-queue.ts +166 -0
  148. package/src/agent/output-extraction-error-detail.js +45 -0
  149. package/src/agent/output-extraction-error-detail.ts +49 -0
  150. package/src/agent/output-extraction-failures.js +125 -0
  151. package/src/agent/output-extraction-failures.ts +149 -0
  152. package/src/agent/output-extraction-json.js +234 -0
  153. package/src/agent/output-extraction-json.ts +235 -0
  154. package/src/agent/output-extraction-pi.js +124 -0
  155. package/src/agent/output-extraction-pi.ts +137 -0
  156. package/src/agent/output-extraction-types.js +2 -0
  157. package/src/agent/output-extraction-types.ts +49 -0
  158. package/src/agent/output-extraction.js +17 -617
  159. package/src/agent/output-extraction.ts +30 -0
  160. package/src/agent/output-reformatter-errors.js +83 -0
  161. package/src/agent/output-reformatter-errors.ts +106 -0
  162. package/src/agent/output-reformatter-types.js +2 -0
  163. package/src/agent/output-reformatter-types.ts +86 -0
  164. package/src/agent/output-reformatter.js +140 -185
  165. package/src/agent/output-reformatter.ts +238 -0
  166. package/src/agent/pi-terminal-lifecycle-types.js +2 -0
  167. package/src/agent/pi-terminal-lifecycle-types.ts +41 -0
  168. package/src/agent/pi-terminal-lifecycle.js +186 -206
  169. package/src/agent/pi-terminal-lifecycle.ts +297 -0
  170. package/src/agent/provider-control-plane.js +22 -21
  171. package/src/agent/provider-control-plane.ts +52 -0
  172. package/src/agent/provider-terminal-failure-types.js +2 -0
  173. package/src/agent/provider-terminal-failure-types.ts +60 -0
  174. package/src/agent/provider-terminal-failure.js +194 -191
  175. package/src/agent/provider-terminal-failure.ts +262 -0
  176. package/src/agent/rate-limit-backoff.js +31 -74
  177. package/src/agent/rate-limit-backoff.ts +71 -0
  178. package/src/agent/schema-utils.js +85 -125
  179. package/src/agent/schema-utils.ts +148 -0
  180. package/src/agent/structured-output-error.js +34 -33
  181. package/src/agent/structured-output-error.ts +105 -0
  182. package/src/agent/validation-platform.js +27 -27
  183. package/src/agent/validation-platform.ts +49 -0
  184. package/src/agent-cli-provider/adapters/codex.ts +3 -1
  185. package/src/attach/attach-client.js +232 -405
  186. package/src/attach/attach-client.ts +300 -0
  187. package/src/attach/attach-server-cleanup.js +43 -0
  188. package/src/attach/attach-server-cleanup.ts +39 -0
  189. package/src/attach/attach-server-clients.js +117 -0
  190. package/src/attach/attach-server-clients.ts +122 -0
  191. package/src/attach/attach-server-events.js +38 -0
  192. package/src/attach/attach-server-events.ts +36 -0
  193. package/src/attach/attach-server-pty.js +45 -0
  194. package/src/attach/attach-server-pty.ts +64 -0
  195. package/src/attach/attach-server-runtime.js +73 -0
  196. package/src/attach/attach-server-runtime.ts +62 -0
  197. package/src/attach/attach-server-socket.js +28 -0
  198. package/src/attach/attach-server-socket.ts +23 -0
  199. package/src/attach/attach-server-types.js +2 -0
  200. package/src/attach/attach-server-types.ts +82 -0
  201. package/src/attach/attach-server.js +106 -523
  202. package/src/attach/attach-server.ts +158 -0
  203. package/src/attach/index.js +18 -35
  204. package/src/attach/index.ts +18 -0
  205. package/src/attach/protocol.js +95 -184
  206. package/src/attach/protocol.ts +181 -0
  207. package/src/attach/ring-buffer.js +76 -102
  208. package/src/attach/ring-buffer.ts +109 -0
  209. package/src/attach/send-input.js +64 -75
  210. package/src/attach/send-input.ts +94 -0
  211. package/src/attach/socket-discovery.js +164 -218
  212. package/src/attach/socket-discovery.ts +230 -0
  213. package/src/attach/socket-paths.js +42 -61
  214. package/src/attach/socket-paths.ts +81 -0
  215. package/src/claude-credentials.js +51 -54
  216. package/src/claude-credentials.ts +89 -0
  217. package/src/cluster/generated/protocol-schema.ts +1 -1
  218. package/src/cluster/generated/protocol.ts +2 -1
  219. package/src/command-proofs.js +110 -141
  220. package/src/command-proofs.ts +216 -0
  221. package/src/config-router.js +81 -73
  222. package/src/config-router.ts +131 -0
  223. package/src/copy-worker.js +53 -29
  224. package/src/copy-worker.ts +75 -0
  225. package/src/darwin-keychain-boundary.js +80 -111
  226. package/src/darwin-keychain-boundary.ts +148 -0
  227. package/src/guidance-topics.js +4 -5
  228. package/src/guidance-topics.ts +10 -0
  229. package/src/input-helpers.js +33 -54
  230. package/src/input-helpers.ts +58 -0
  231. package/src/ledger-sequence.js +45 -48
  232. package/src/ledger-sequence.ts +63 -0
  233. package/src/legacy-lib/clusters-registry.ts +40 -0
  234. package/src/legacy-lib/completion.ts +148 -0
  235. package/src/legacy-lib/compose-utils.ts +102 -0
  236. package/src/legacy-lib/detached-startup.ts +449 -0
  237. package/src/legacy-lib/docker-config.ts +282 -0
  238. package/src/legacy-lib/docker-env-auth.ts +116 -0
  239. package/src/legacy-lib/git-remote-utils.ts +244 -0
  240. package/src/legacy-lib/id-detector.ts +57 -0
  241. package/src/legacy-lib/js-yaml.d.ts +3 -0
  242. package/src/legacy-lib/omelette.d.ts +15 -0
  243. package/src/legacy-lib/path-check.ts +89 -0
  244. package/src/legacy-lib/process-liveness.ts +36 -0
  245. package/src/legacy-lib/provider-credential-path.ts +57 -0
  246. package/src/legacy-lib/provider-defaults.ts +114 -0
  247. package/src/legacy-lib/provider-detection.ts +67 -0
  248. package/src/legacy-lib/provider-names.ts +126 -0
  249. package/src/legacy-lib/repo-settings.ts +88 -0
  250. package/src/legacy-lib/run-mode.ts +58 -0
  251. package/src/legacy-lib/run-plan.ts +49 -0
  252. package/src/legacy-lib/settings/claude-auth.ts +80 -0
  253. package/src/legacy-lib/settings-defaults.ts +212 -0
  254. package/src/legacy-lib/settings-error.ts +8 -0
  255. package/src/legacy-lib/settings-issue-providers.ts +18 -0
  256. package/src/legacy-lib/settings-models.ts +124 -0
  257. package/src/legacy-lib/settings-storage.ts +277 -0
  258. package/src/legacy-lib/settings-validation.ts +220 -0
  259. package/src/legacy-lib/settings.ts +87 -0
  260. package/src/legacy-lib/setup-apply-types.ts +70 -0
  261. package/src/legacy-lib/setup-apply.ts +456 -0
  262. package/src/legacy-lib/setup-journal.ts +185 -0
  263. package/src/legacy-lib/setup-plan-types.ts +96 -0
  264. package/src/legacy-lib/setup-plan.ts +500 -0
  265. package/src/legacy-lib/setup-undo.ts +142 -0
  266. package/src/legacy-lib/start-cluster-config.ts +124 -0
  267. package/src/legacy-lib/start-cluster-environment.ts +165 -0
  268. package/src/legacy-lib/start-cluster-run-options.ts +279 -0
  269. package/src/legacy-lib/start-cluster.ts +237 -0
  270. package/src/legacy-lib/stream-json-parser.ts +88 -0
  271. package/src/message-buffer.js +55 -71
  272. package/src/message-buffer.ts +107 -0
  273. package/src/message-bus-bridge.js +92 -133
  274. package/src/message-bus-bridge.ts +149 -0
  275. package/src/name-generator-shared.js +220 -0
  276. package/src/name-generator-shared.ts +231 -0
  277. package/src/name-generator.js +8 -217
  278. package/src/name-generator.ts +27 -0
  279. package/src/omp-blob-root.js +83 -64
  280. package/src/omp-blob-root.ts +116 -0
  281. package/src/omp-config-overlay.js +65 -38
  282. package/src/omp-config-overlay.ts +110 -0
  283. package/src/omp-execution-fingerprint.js +38 -43
  284. package/src/omp-execution-fingerprint.ts +92 -0
  285. package/src/omp-session-limits.js +10 -15
  286. package/src/omp-session-limits.ts +53 -0
  287. package/src/omp-session-partition.js +2 -2
  288. package/src/omp-session-verifier.js +1 -1
  289. package/src/orchestrator.js +19 -4
  290. package/src/providers/anthropic/index.js +3 -1
  291. package/src/providers/anthropic/index.ts +13 -0
  292. package/src/providers/capabilities.js +19 -27
  293. package/src/providers/capabilities.ts +44 -0
  294. package/src/providers/google/index.js +3 -1
  295. package/src/providers/google/index.ts +13 -0
  296. package/src/providers/openai/index.js +3 -1
  297. package/src/providers/openai/index.ts +13 -0
  298. package/src/providers/opencode/index.js +3 -1
  299. package/src/providers/opencode/index.ts +13 -0
  300. package/src/quality-gates.js +67 -127
  301. package/src/quality-gates.ts +149 -0
  302. package/src/repo-settings-access.js +40 -0
  303. package/src/repo-settings-access.ts +64 -0
  304. package/src/schemas/sub-cluster.js +127 -183
  305. package/src/schemas/sub-cluster.ts +238 -0
  306. package/src/state-snapshot-normalization.js +224 -0
  307. package/src/state-snapshot-normalization.ts +222 -0
  308. package/src/state-snapshot.js +192 -359
  309. package/src/state-snapshot.ts +291 -0
  310. package/src/state-snapshotter.js +118 -130
  311. package/src/state-snapshotter.ts +167 -0
  312. package/src/sub-cluster-wrapper.js +4 -13
  313. package/src/task-run-model-args.js +87 -124
  314. package/src/task-run-model-args.ts +204 -0
  315. package/src/task-runner.js +5 -25
  316. package/src/task-runner.ts +28 -0
  317. package/src/task-startup-error.js +73 -58
  318. package/src/task-startup-error.ts +126 -0
  319. package/src/template-validation/consensus-gate-contracts.js +2 -0
  320. package/src/template-validation/consensus-gate-contracts.ts +70 -0
  321. package/src/template-validation/consensus-gate-scenarios.js +76 -0
  322. package/src/template-validation/consensus-gate-scenarios.ts +130 -0
  323. package/src/template-validation/consensus-gate-stage.js +34 -0
  324. package/src/template-validation/consensus-gate-stage.ts +56 -0
  325. package/src/template-validation/random-topology-contracts.js +2 -0
  326. package/src/template-validation/random-topology-contracts.ts +54 -0
  327. package/src/template-validation/random-topology-dispatch.js +25 -0
  328. package/src/template-validation/random-topology-dispatch.ts +33 -0
  329. package/src/template-validation/random-topology-message-loop.js +53 -0
  330. package/src/template-validation/random-topology-message-loop.ts +73 -0
  331. package/src/template-validation/random-topology-operations.js +79 -0
  332. package/src/template-validation/random-topology-operations.ts +101 -0
  333. package/src/template-validation/random-topology-runtime.js +25 -0
  334. package/src/template-validation/random-topology-runtime.ts +43 -0
  335. package/src/template-validation/random-topology-scenario.js +52 -0
  336. package/src/template-validation/random-topology-scenario.ts +57 -0
  337. package/src/template-validation/random-topology-schema.js +159 -0
  338. package/src/template-validation/random-topology-schema.ts +190 -0
  339. package/src/template-validation/random-topology-state.js +28 -0
  340. package/src/template-validation/random-topology-state.ts +30 -0
  341. package/src/template-validation/random-topology-trigger-evaluation.js +45 -0
  342. package/src/template-validation/random-topology-trigger-evaluation.ts +65 -0
  343. package/src/template-validation/random-topology-trigger.js +75 -0
  344. package/src/template-validation/random-topology-trigger.ts +88 -0
  345. package/src/template-validation/report-formatter.js +40 -46
  346. package/src/template-validation/report-formatter.ts +101 -0
  347. package/src/template-validation/simulate-consensus-gates.js +111 -302
  348. package/src/template-validation/simulate-consensus-gates.ts +196 -0
  349. package/src/template-validation/simulate-random-topology.js +26 -519
  350. package/src/template-validation/simulate-random-topology.ts +57 -0
  351. package/src/template-validation/simulate-two-stage-validation.js +41 -265
  352. package/src/template-validation/simulate-two-stage-validation.ts +55 -0
  353. package/src/template-validation/simulation-agent-runtime.js +25 -0
  354. package/src/template-validation/simulation-agent-runtime.ts +40 -0
  355. package/src/template-validation/simulation-agent.js +29 -0
  356. package/src/template-validation/simulation-agent.ts +73 -0
  357. package/src/template-validation/simulation-runtime.js +34 -0
  358. package/src/template-validation/simulation-runtime.ts +72 -0
  359. package/src/template-validation/two-stage-contracts.js +2 -0
  360. package/src/template-validation/two-stage-contracts.ts +41 -0
  361. package/src/template-validation/two-stage-inputs.js +21 -0
  362. package/src/template-validation/two-stage-inputs.ts +29 -0
  363. package/src/template-validation/two-stage-results.js +30 -0
  364. package/src/template-validation/two-stage-results.ts +40 -0
  365. package/src/template-validation/two-stage-scenario.js +86 -0
  366. package/src/template-validation/two-stage-scenario.ts +120 -0
  367. package/src/worktree-claude-config.js +182 -220
  368. package/src/worktree-claude-config.ts +272 -0
  369. package/src/worktree-tooling-env.js +103 -125
  370. package/src/worktree-tooling-env.ts +142 -0
  371. package/task-lib/completion.js +2 -3
  372. package/task-lib/completion.ts +9 -0
  373. package/task-lib/config.js +1 -4
  374. package/task-lib/config.ts +11 -0
  375. package/task-lib/name-generator.js +4 -226
  376. package/task-lib/name-generator.ts +11 -0
  377. package/task-lib/omp-session-cleanup.js +1 -1
  378. package/task-lib/omp-storage-root.js +8 -12
  379. package/task-lib/omp-storage-root.ts +62 -0
  380. package/task-lib/process-termination.js +143 -166
  381. package/task-lib/process-termination.ts +268 -0
@@ -1,351 +1,280 @@
1
- const fs = require('fs');
2
- const os = require('os');
3
- const path = require('path');
1
+ "use strict";
2
+ const fs = require("fs");
3
+ const os = require("os");
4
+ const path = require("path");
5
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
4
6
  const lockfile = require('proper-lockfile');
5
- const { resolveRunPlan } = require('./run-plan');
6
- const { isProcessRunning } = require('./process-liveness');
7
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
8
+ const runPlan = require('./run-plan');
9
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
10
+ const processLiveness = require('./process-liveness');
11
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
7
12
  const IsolationManager = require('../src/isolation-manager');
8
-
13
+ const { resolveRunPlan } = runPlan;
14
+ const { isProcessRunning } = processLiveness;
9
15
  const DEFAULT_WAIT_TIMEOUT_SECONDS = 180;
10
16
  const DEFAULT_WAIT_POLL_MS = 1000;
11
17
  const CLUSTERS_LOCK_STALE_MS = 5000;
12
18
  const DEFAULT_OWNERSHIP_TIMEOUT_MS = 10000;
13
-
19
+ function isClusterRegistry(value) {
20
+ return value !== null && typeof value === 'object';
21
+ }
22
+ function hasErrorCode(error, code) {
23
+ return error !== null && typeof error === 'object' && 'code' in error && error.code === code;
24
+ }
14
25
  function getStorageDir(storageDir) {
15
- return storageDir || path.join(os.homedir(), '.zeroshot');
26
+ return storageDir || path.join(os.homedir(), '.zeroshot');
16
27
  }
17
-
18
28
  function getClustersFilePath(storageDir) {
19
- return path.join(getStorageDir(storageDir), 'clusters.json');
29
+ return path.join(getStorageDir(storageDir), 'clusters.json');
20
30
  }
21
-
22
31
  function resolveWaitTimeoutMs(waitTimeoutSeconds) {
23
- const parsed = Number(waitTimeoutSeconds);
24
- if (!Number.isFinite(parsed) || parsed <= 0) {
25
- return DEFAULT_WAIT_TIMEOUT_SECONDS * 1000;
26
- }
27
- return Math.floor(parsed * 1000);
32
+ const parsed = Number(waitTimeoutSeconds);
33
+ if (!Number.isFinite(parsed) || parsed <= 0) {
34
+ return DEFAULT_WAIT_TIMEOUT_SECONDS * 1000;
35
+ }
36
+ return Math.floor(parsed * 1000);
28
37
  }
29
-
30
38
  // Kept as an alias: this module used to carry its own copy of this check.
31
39
  const isProcessAlive = isProcessRunning;
32
-
33
40
  function isClusterRegistered(clusterId, storageDir) {
34
- const clustersFile = getClustersFilePath(storageDir);
35
- if (!fs.existsSync(clustersFile)) {
36
- return false;
37
- }
38
-
39
- let parsed;
40
- try {
41
- const raw = fs.readFileSync(clustersFile, 'utf8');
42
- parsed = JSON.parse(raw);
43
- } catch {
44
- return false;
45
- }
46
-
47
- return parsed !== null && typeof parsed === 'object' && Boolean(parsed[clusterId]);
41
+ const clustersFile = getClustersFilePath(storageDir);
42
+ if (!fs.existsSync(clustersFile)) {
43
+ return false;
44
+ }
45
+ try {
46
+ const raw = fs.readFileSync(clustersFile, 'utf8');
47
+ const parsed = JSON.parse(raw);
48
+ return isClusterRegistry(parsed) && Boolean(parsed[clusterId]);
49
+ }
50
+ catch {
51
+ return false;
52
+ }
48
53
  }
49
-
50
54
  function ensureStorageDir(storageDir) {
51
- const resolvedStorageDir = getStorageDir(storageDir);
52
- fs.mkdirSync(resolvedStorageDir, { recursive: true });
53
- return resolvedStorageDir;
55
+ const resolvedStorageDir = getStorageDir(storageDir);
56
+ fs.mkdirSync(resolvedStorageDir, { recursive: true });
57
+ return resolvedStorageDir;
54
58
  }
55
-
56
59
  function ensureClustersFile(storageDir) {
57
- const resolvedStorageDir = ensureStorageDir(storageDir);
58
- const clustersFile = getClustersFilePath(resolvedStorageDir);
59
- try {
60
- fs.writeFileSync(clustersFile, '{}', { flag: 'wx', mode: 0o600 });
61
- } catch (error) {
62
- if (!error || error.code !== 'EEXIST') {
63
- throw error;
60
+ const resolvedStorageDir = ensureStorageDir(storageDir);
61
+ const clustersFile = getClustersFilePath(resolvedStorageDir);
62
+ try {
63
+ fs.writeFileSync(clustersFile, '{}', { flag: 'wx', mode: 0o600 });
64
64
  }
65
- }
66
- return clustersFile;
65
+ catch (error) {
66
+ if (!hasErrorCode(error, 'EEXIST')) {
67
+ throw error;
68
+ }
69
+ }
70
+ return clustersFile;
67
71
  }
68
-
69
72
  function readClustersFile(clustersFile) {
70
- try {
71
- return JSON.parse(fs.readFileSync(clustersFile, 'utf8'));
72
- } catch {
73
- return {};
74
- }
73
+ try {
74
+ const parsed = JSON.parse(fs.readFileSync(clustersFile, 'utf8'));
75
+ return isClusterRegistry(parsed) ? parsed : {};
76
+ }
77
+ catch {
78
+ return {};
79
+ }
75
80
  }
76
-
77
81
  async function updateClustersFile(storageDir, updater) {
78
- const clustersFile = ensureClustersFile(storageDir);
79
- const lockfilePath = path.join(path.dirname(clustersFile), 'clusters.json.lock');
80
- let release;
81
-
82
- try {
83
- release = await lockfile.lock(clustersFile, {
84
- lockfilePath,
85
- stale: CLUSTERS_LOCK_STALE_MS,
86
- retries: {
87
- retries: 20,
88
- minTimeout: 100,
89
- maxTimeout: 250,
90
- randomize: true,
91
- },
92
- });
93
-
94
- const clusters = readClustersFile(clustersFile);
95
- const updated = updater(clusters) || clusters;
96
- fs.writeFileSync(clustersFile, JSON.stringify(updated, null, 2));
97
- return updated;
98
- } finally {
99
- if (release) {
100
- await release();
82
+ const clustersFile = ensureClustersFile(storageDir);
83
+ const lockfilePath = path.join(path.dirname(clustersFile), 'clusters.json.lock');
84
+ let release;
85
+ try {
86
+ release = await lockfile.lock(clustersFile, {
87
+ lockfilePath,
88
+ stale: CLUSTERS_LOCK_STALE_MS,
89
+ retries: {
90
+ retries: 20,
91
+ minTimeout: 100,
92
+ maxTimeout: 250,
93
+ randomize: true,
94
+ },
95
+ });
96
+ const clusters = readClustersFile(clustersFile);
97
+ const updated = updater(clusters) || clusters;
98
+ fs.writeFileSync(clustersFile, JSON.stringify(updated, null, 2));
99
+ return updated;
100
+ }
101
+ finally {
102
+ if (release) {
103
+ await release();
104
+ }
101
105
  }
102
- }
103
106
  }
104
-
105
- async function registerDetachedSetupCluster({
106
- clusterId,
107
- pid,
108
- storageDir,
109
- logPath,
110
- worktree,
111
- runOptions = {},
112
- cwd,
113
- }) {
114
- const plan = resolveRunPlan(runOptions);
115
- const setupResources =
116
- plan.isolation === 'docker' ? IsolationManager.getDetachedSetupResources(clusterId) : null;
117
- await updateClustersFile(storageDir, (clusters) => {
118
- clusters[clusterId] = {
119
- id: clusterId,
120
- state: 'setup',
121
- createdAt: Date.now(),
122
- pid: Number.isInteger(pid) ? pid : null,
123
- setupLogPath: logPath || null,
124
- setupStartedAt: Date.now(),
125
- setupStage: 'starting',
126
- autoPr: plan.delivery !== 'none',
127
- prOptions: runOptions.prBase
128
- ? {
129
- prBase: runOptions.prBase,
130
- mergeQueue: runOptions.mergeQueue || false,
131
- closeIssue: runOptions.closeIssue || null,
132
- autoMerge: plan.autoMerge,
133
- cwd: cwd || null,
134
- }
135
- : null,
136
- worktree: worktree || null,
137
- config: null,
138
- issue: null,
139
- isolation: null,
140
- agentStates: [],
141
- failureInfo: null,
142
- setupResources,
143
- provisional: true,
144
- };
145
- return clusters;
146
- });
107
+ async function registerDetachedSetupCluster({ clusterId, pid, storageDir, logPath, worktree, runOptions = {}, cwd, }) {
108
+ const plan = resolveRunPlan(runOptions);
109
+ const setupResources = plan.isolation === 'docker' ? IsolationManager.getDetachedSetupResources(clusterId) : null;
110
+ await updateClustersFile(storageDir, (clusters) => {
111
+ clusters[clusterId] = {
112
+ id: clusterId,
113
+ state: 'setup',
114
+ createdAt: Date.now(),
115
+ pid: typeof pid === 'number' && Number.isInteger(pid) ? pid : null,
116
+ setupLogPath: logPath || null,
117
+ setupStartedAt: Date.now(),
118
+ setupStage: 'starting',
119
+ autoPr: plan.delivery !== 'none',
120
+ prOptions: runOptions.prBase
121
+ ? {
122
+ prBase: runOptions.prBase,
123
+ mergeQueue: runOptions.mergeQueue || false,
124
+ closeIssue: runOptions.closeIssue || null,
125
+ autoMerge: plan.autoMerge,
126
+ cwd: cwd || null,
127
+ }
128
+ : null,
129
+ worktree: worktree || null,
130
+ config: null,
131
+ issue: null,
132
+ isolation: null,
133
+ agentStates: [],
134
+ failureInfo: null,
135
+ setupResources,
136
+ provisional: true,
137
+ };
138
+ return clusters;
139
+ });
147
140
  }
148
-
149
- async function removeDetachedSetupCluster({ clusterId, storageDir }) {
150
- await updateClustersFile(storageDir, (clusters) => {
151
- delete clusters[clusterId];
152
- return clusters;
153
- });
141
+ async function removeDetachedSetupCluster({ clusterId, storageDir, }) {
142
+ await updateClustersFile(storageDir, (clusters) => {
143
+ delete clusters[clusterId];
144
+ return clusters;
145
+ });
154
146
  }
155
-
156
- async function markDetachedSetupFailed({ clusterId, storageDir, error, logPath }) {
157
- await updateClustersFile(storageDir, (clusters) => {
158
- const existing = clusters[clusterId] || { id: clusterId, createdAt: Date.now() };
159
- clusters[clusterId] = {
160
- ...existing,
161
- state: 'failed',
162
- pid: null,
163
- setupLogPath: existing.setupLogPath || logPath || null,
164
- setupFinishedAt: Date.now(),
165
- failureInfo: {
166
- type: 'setup',
167
- error: error instanceof Error ? error.message : String(error),
168
- timestamp: Date.now(),
169
- },
170
- provisional: true,
171
- };
172
- return clusters;
173
- });
147
+ async function markDetachedSetupFailed({ clusterId, storageDir, error, logPath, }) {
148
+ await updateClustersFile(storageDir, (clusters) => {
149
+ const existing = clusters[clusterId] || { id: clusterId, createdAt: Date.now() };
150
+ clusters[clusterId] = {
151
+ ...existing,
152
+ state: 'failed',
153
+ pid: null,
154
+ setupLogPath: existing.setupLogPath || logPath || null,
155
+ setupFinishedAt: Date.now(),
156
+ failureInfo: {
157
+ type: 'setup',
158
+ error: error instanceof Error ? error.message : String(error),
159
+ timestamp: Date.now(),
160
+ },
161
+ provisional: true,
162
+ };
163
+ return clusters;
164
+ });
174
165
  }
175
-
176
166
  function sleep(ms) {
177
- return new Promise((resolve) => setTimeout(resolve, ms));
167
+ return new Promise((resolve) => setTimeout(resolve, ms));
178
168
  }
179
-
180
169
  function formatLogHint(logPath) {
181
- return logPath ? ` Check log: ${logPath}` : '';
170
+ return logPath ? ` Check log: ${logPath}` : '';
182
171
  }
183
-
184
- async function waitForClusterRegistration({
185
- clusterId,
186
- timeoutMs,
187
- pollMs = DEFAULT_WAIT_POLL_MS,
188
- storageDir,
189
- daemonPid,
190
- logPath,
191
- }) {
192
- const effectiveTimeoutMs =
193
- Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : DEFAULT_WAIT_TIMEOUT_SECONDS * 1000;
194
- const startedAt = Date.now();
195
- const deadline = startedAt + effectiveTimeoutMs;
196
- const logHint = formatLogHint(logPath);
197
-
198
- while (Date.now() < deadline) {
199
- if (isClusterRegistered(clusterId, storageDir)) {
200
- return { ready: true, elapsedMs: Date.now() - startedAt };
201
- }
202
-
203
- if (daemonPid && !isProcessAlive(daemonPid)) {
204
- throw new Error(
205
- `Detached daemon exited before cluster "${clusterId}" registered in storage.${logHint}`
206
- );
172
+ async function waitForClusterRegistration({ clusterId, timeoutMs, pollMs = DEFAULT_WAIT_POLL_MS, storageDir, daemonPid, logPath, }) {
173
+ const effectiveTimeoutMs = typeof timeoutMs === 'number' && Number.isFinite(timeoutMs) && timeoutMs > 0
174
+ ? timeoutMs
175
+ : DEFAULT_WAIT_TIMEOUT_SECONDS * 1000;
176
+ const startedAt = Date.now();
177
+ const deadline = startedAt + effectiveTimeoutMs;
178
+ const logHint = formatLogHint(logPath);
179
+ while (Date.now() < deadline) {
180
+ if (isClusterRegistered(clusterId, storageDir)) {
181
+ return { ready: true, elapsedMs: Date.now() - startedAt };
182
+ }
183
+ if (daemonPid && !isProcessAlive(daemonPid)) {
184
+ throw new Error(`Detached daemon exited before cluster "${clusterId}" registered in storage.${logHint}`);
185
+ }
186
+ await sleep(pollMs);
207
187
  }
208
-
209
- await sleep(pollMs);
210
- }
211
-
212
- const timeoutSeconds = Math.ceil(effectiveTimeoutMs / 1000);
213
- throw new Error(
214
- `Timed out after ${timeoutSeconds}s waiting for cluster "${clusterId}" to appear in status/list.${logHint}`
215
- );
188
+ const timeoutSeconds = Math.ceil(effectiveTimeoutMs / 1000);
189
+ throw new Error(`Timed out after ${timeoutSeconds}s waiting for cluster "${clusterId}" to appear in status/list.${logHint}`);
216
190
  }
217
-
218
191
  /**
219
- * Atomically claim the right to resume-daemon an *existing* cluster record.
220
- *
221
- * This deliberately does NOT touch cluster.pid/state - those are the fields
222
- * orchestrator.resume()'s own eligibility guard inspects to decide "is
223
- * someone else already running this?". If this function stamped its PID onto
224
- * `cluster.pid` up front, the daemon's own subsequent resume() call would see
225
- * state:'running' with a PID that (trivially) belongs to itself and is
226
- * therefore alive, and reject itself as "still running" - which is exactly
227
- * what happened in early revisions of this fix. Ownership for the handoff is
228
- * tracked in a separate `resumeDaemonPid` field instead; orchestrator.resume()
229
- * never looks at it, and _restartClusterAgents sets the real cluster.pid once
230
- * resume() actually decides to proceed.
231
- *
232
- * Unlike registerDetachedSetupCluster (which writes a brand-new placeholder
233
- * record for a cluster ID that doesn't exist yet), this only adds
234
- * resumeDaemonPid to the existing record - config/agents/worktree/isolation
235
- * survive untouched, or the daemon's orchestrator.resume() would reload a
236
- * blank record and reject it as an unfinished setup cluster.
237
- *
238
- * The liveness re-check happens inside the same updateClustersFile lock that
239
- * performs the write, so two concurrent resume --detach invocations can't both
240
- * observe no live claimant and both win: whichever's write lands second sees
241
- * either the first daemon's (still-live) resumeDaemonPid, or - once that gets
242
- * overwritten by the first daemon's own early _saveClusters() call - its real
243
- * state:'running' + live pid, and aborts instead of clobbering it.
192
+ * Atomically claim the right to resume-daemon an existing cluster record.
193
+ * Ownership for the handoff is tracked separately from cluster.pid/state so
194
+ * orchestrator.resume() can still perform its own eligibility check.
244
195
  */
245
- async function patchDetachedResumeCluster({ clusterId, daemonPid, storageDir }) {
246
- await updateClustersFile(storageDir, (clusters) => {
247
- const existing = clusters[clusterId];
248
- if (!existing) {
249
- throw new Error(`Cannot start resume daemon: cluster "${clusterId}" not found in registry`);
250
- }
251
- if (existing.resumeDaemonPid && isProcessRunning(existing.resumeDaemonPid)) {
252
- throw new Error(
253
- `Cluster "${clusterId}" already has a live resume daemon (PID ${existing.resumeDaemonPid}); refusing to start a second one`
254
- );
255
- }
256
- // resumeDaemonPid only covers the window up to orchestrator.resume()
257
- // actually proceeding - _restartClusterAgents sets the real cluster.pid,
258
- // and _resumeFailedCluster/_resumeCleanCluster save that almost
259
- // immediately (well before the resumed work itself finishes), which wipes
260
- // resumeDaemonPid since it isn't in _saveClusters' persisted field list.
261
- // Falling back to state+pid here closes that second window: a first
262
- // daemon that has already progressed to actually running is just as much
263
- // a live claimant as one still mid-handoff.
264
- if (existing.state === 'running' && existing.pid && isProcessRunning(existing.pid)) {
265
- throw new Error(
266
- `Cluster "${clusterId}" is already running (PID ${existing.pid}); refusing to start a second resume daemon`
267
- );
268
- }
269
- clusters[clusterId] = { ...existing, resumeDaemonPid: daemonPid };
270
- return clusters;
271
- });
196
+ async function patchDetachedResumeCluster({ clusterId, daemonPid, storageDir, }) {
197
+ await updateClustersFile(storageDir, (clusters) => {
198
+ const existing = clusters[clusterId];
199
+ if (!existing) {
200
+ throw new Error(`Cannot start resume daemon: cluster "${clusterId}" not found in registry`);
201
+ }
202
+ if (existing.resumeDaemonPid && isProcessRunning(existing.resumeDaemonPid)) {
203
+ const ownership = `Cluster "${clusterId}" already has a live resume daemon`;
204
+ throw new Error(`${ownership} (PID ${existing.resumeDaemonPid}); refusing to start a second one`);
205
+ }
206
+ if (existing.state === 'running' && existing.pid && isProcessRunning(existing.pid)) {
207
+ throw new Error(`Cluster "${clusterId}" is already running (PID ${existing.pid}); refusing to start a second resume daemon`);
208
+ }
209
+ clusters[clusterId] = { ...existing, resumeDaemonPid: daemonPid };
210
+ return clusters;
211
+ });
272
212
  }
273
-
274
213
  /**
275
- * Undo a resume handoff that didn't pan out (daemon died before completing
276
- * ownership, or orchestrator.resume() itself rejected it) so the cluster
277
- * doesn't end up stuck at state:'running' with a dead PID - the exact zombie
278
- * this whole mechanism exists to prevent.
214
+ * Undo a resume handoff that did not complete so a dead daemon cannot leave
215
+ * the cluster stuck in a running state.
279
216
  */
280
- async function revertDetachedResumeCluster({ clusterId, storageDir, error }) {
281
- await updateClustersFile(storageDir, (clusters) => {
282
- const existing = clusters[clusterId];
283
- if (!existing) return clusters;
284
- clusters[clusterId] = {
285
- ...existing,
286
- state: 'failed',
287
- pid: null,
288
- resumeDaemonPid: null,
289
- failureInfo: {
290
- type: 'resume-daemon',
291
- error: error instanceof Error ? error.message : String(error),
292
- timestamp: Date.now(),
293
- },
294
- };
295
- return clusters;
296
- });
217
+ async function revertDetachedResumeCluster({ clusterId, storageDir, error, }) {
218
+ await updateClustersFile(storageDir, (clusters) => {
219
+ const existing = clusters[clusterId];
220
+ if (!existing)
221
+ return clusters;
222
+ clusters[clusterId] = {
223
+ ...existing,
224
+ state: 'failed',
225
+ pid: null,
226
+ resumeDaemonPid: null,
227
+ failureInfo: {
228
+ type: 'resume-daemon',
229
+ error: error instanceof Error ? error.message : String(error),
230
+ timestamp: Date.now(),
231
+ },
232
+ };
233
+ return clusters;
234
+ });
297
235
  }
298
-
299
236
  function getRegisteredResumeDaemonPid(clusterId, storageDir) {
300
- const clustersFile = getClustersFilePath(storageDir);
301
- if (!fs.existsSync(clustersFile)) {
302
- return null;
303
- }
304
- try {
305
- const parsed = JSON.parse(fs.readFileSync(clustersFile, 'utf8'));
306
- return parsed?.[clusterId]?.resumeDaemonPid ?? null;
307
- } catch {
308
- return null;
309
- }
237
+ const clustersFile = getClustersFilePath(storageDir);
238
+ if (!fs.existsSync(clustersFile)) {
239
+ return null;
240
+ }
241
+ try {
242
+ const parsed = JSON.parse(fs.readFileSync(clustersFile, 'utf8'));
243
+ if (!isClusterRegistry(parsed)) {
244
+ return null;
245
+ }
246
+ return parsed[clusterId]?.resumeDaemonPid ?? null;
247
+ }
248
+ catch {
249
+ return null;
250
+ }
310
251
  }
311
-
312
252
  /**
313
- * Daemon-side half of the resume handoff: block until the registry shows
314
- * *this process's* PID as resumeDaemonPid before touching the cluster.
315
- * Closes the window between spawn() returning a PID and the parent's
316
- * patchDetachedResumeCluster() write landing - without it, a losing daemon
317
- * from a concurrent resume --detach could start running orchestrator.resume()
318
- * before its parent's CAS check ever gets a chance to reject it.
253
+ * Daemon-side half of the resume handoff: wait until the registry shows this
254
+ * process's PID as resumeDaemonPid before touching the cluster.
319
255
  */
320
- async function waitForResumeOwnership({
321
- clusterId,
322
- daemonPid,
323
- storageDir,
324
- timeoutMs = DEFAULT_OWNERSHIP_TIMEOUT_MS,
325
- pollMs = DEFAULT_WAIT_POLL_MS,
326
- }) {
327
- const deadline = Date.now() + timeoutMs;
328
- while (Date.now() < deadline) {
329
- if (getRegisteredResumeDaemonPid(clusterId, storageDir) === daemonPid) {
330
- return true;
256
+ async function waitForResumeOwnership({ clusterId, daemonPid, storageDir, timeoutMs = DEFAULT_OWNERSHIP_TIMEOUT_MS, pollMs = DEFAULT_WAIT_POLL_MS, }) {
257
+ const deadline = Date.now() + timeoutMs;
258
+ while (Date.now() < deadline) {
259
+ if (getRegisteredResumeDaemonPid(clusterId, storageDir) === daemonPid) {
260
+ return true;
261
+ }
262
+ await sleep(pollMs);
331
263
  }
332
- await sleep(pollMs);
333
- }
334
- return getRegisteredResumeDaemonPid(clusterId, storageDir) === daemonPid;
264
+ return getRegisteredResumeDaemonPid(clusterId, storageDir) === daemonPid;
335
265
  }
336
-
337
266
  module.exports = {
338
- DEFAULT_WAIT_TIMEOUT_SECONDS,
339
- getClustersFilePath,
340
- getRegisteredResumeDaemonPid,
341
- isClusterRegistered,
342
- isProcessAlive,
343
- markDetachedSetupFailed,
344
- patchDetachedResumeCluster,
345
- registerDetachedSetupCluster,
346
- removeDetachedSetupCluster,
347
- resolveWaitTimeoutMs,
348
- revertDetachedResumeCluster,
349
- waitForClusterRegistration,
350
- waitForResumeOwnership,
267
+ DEFAULT_WAIT_TIMEOUT_SECONDS,
268
+ getClustersFilePath,
269
+ getRegisteredResumeDaemonPid,
270
+ isClusterRegistered,
271
+ isProcessAlive,
272
+ markDetachedSetupFailed,
273
+ patchDetachedResumeCluster,
274
+ registerDetachedSetupCluster,
275
+ removeDetachedSetupCluster,
276
+ resolveWaitTimeoutMs,
277
+ revertDetachedResumeCluster,
278
+ waitForClusterRegistration,
279
+ waitForResumeOwnership,
351
280
  };
@@ -0,0 +1,43 @@
1
+ interface MountPreset {
2
+ host: string;
3
+ container: string;
4
+ readonly: boolean;
5
+ hostEnv?: string;
6
+ }
7
+ interface ProviderEnvAuthResult {
8
+ ok: boolean;
9
+ satisfiedOneOf: boolean;
10
+ malformed: string[];
11
+ message: string;
12
+ }
13
+ interface ResolvedMount {
14
+ host: string;
15
+ container: string;
16
+ readonly: boolean;
17
+ }
18
+ interface ResolveMountOptions {
19
+ containerHome?: string;
20
+ }
21
+ interface ExpandedEnv {
22
+ name: string;
23
+ value: string | null;
24
+ forced: boolean;
25
+ }
26
+ declare function resolveMounts(config: unknown, options?: ResolveMountOptions): ResolvedMount[];
27
+ declare function resolveEnvs(mountConfig: readonly unknown[], extraEnvs?: readonly string[]): string[];
28
+ declare function expandEnvPatterns(envVars: readonly string[], env?: Readonly<Record<string, string | undefined>>): ExpandedEnv[];
29
+ declare function validateMountConfig(value: unknown): string | null;
30
+ declare const _default: {
31
+ MOUNT_PRESETS: Readonly<Record<string, MountPreset>>;
32
+ ENV_PRESETS: Readonly<Record<string, readonly string[]>>;
33
+ PROVIDER_ENV_ONLY_PRESETS: ReadonlySet<string>;
34
+ resolveMounts: typeof resolveMounts;
35
+ resolveEnvs: typeof resolveEnvs;
36
+ expandEnvPatterns: typeof expandEnvPatterns;
37
+ isUsableEnvValue: (value: unknown) => value is string;
38
+ isUsableHttpUrl: (value: unknown) => boolean;
39
+ validateMountConfig: typeof validateMountConfig;
40
+ validateEnvPassthrough: (value: unknown) => string | null;
41
+ validateProviderEnvAuth: (providerId: string, forwardedEnv: Readonly<Record<string, string | undefined>> | null | undefined) => ProviderEnvAuthResult;
42
+ };
43
+ export = _default;