@ai-hero/sandcastle 0.6.5 → 0.7.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 (229) hide show
  1. package/README.md +137 -62
  2. package/dist/{MountConfig.d.ts → MountConfig-CmXclHA5.d.ts} +3 -2
  3. package/dist/{SandboxProvider.d.ts → SandboxProvider-EkSMuBp8.d.ts} +25 -39
  4. package/dist/chunk-52CIJF45.js +25569 -0
  5. package/dist/chunk-52CIJF45.js.map +1 -0
  6. package/dist/chunk-5VM5QZ26.js +26988 -0
  7. package/dist/chunk-5VM5QZ26.js.map +1 -0
  8. package/dist/chunk-72UVAC7B.js +99 -0
  9. package/dist/chunk-72UVAC7B.js.map +1 -0
  10. package/dist/chunk-BIWNFKGV.js +22 -0
  11. package/dist/chunk-BIWNFKGV.js.map +1 -0
  12. package/dist/chunk-NGBM7T3E.js +76 -0
  13. package/dist/chunk-NGBM7T3E.js.map +1 -0
  14. package/dist/chunk-NSFQW6ML.js +362 -0
  15. package/dist/chunk-NSFQW6ML.js.map +1 -0
  16. package/dist/index.d.ts +920 -22
  17. package/dist/index.js +3212 -9
  18. package/dist/index.js.map +1 -1
  19. package/dist/main.d.ts +0 -2
  20. package/dist/main.js +19349 -13
  21. package/dist/main.js.map +1 -1
  22. package/dist/mountUtils-CCA-bbpK.d.ts +25 -0
  23. package/dist/sandboxes/daytona.d.ts +8 -5
  24. package/dist/sandboxes/daytona.js +118 -124
  25. package/dist/sandboxes/daytona.js.map +1 -1
  26. package/dist/sandboxes/docker.d.ts +10 -8
  27. package/dist/sandboxes/docker.js +8 -255
  28. package/dist/sandboxes/docker.js.map +1 -1
  29. package/dist/sandboxes/no-sandbox.d.ts +7 -4
  30. package/dist/sandboxes/no-sandbox.js +6 -114
  31. package/dist/sandboxes/no-sandbox.js.map +1 -1
  32. package/dist/sandboxes/podman.d.ts +10 -8
  33. package/dist/sandboxes/podman.js +287 -297
  34. package/dist/sandboxes/podman.js.map +1 -1
  35. package/dist/sandboxes/vercel.d.ts +7 -4
  36. package/dist/sandboxes/vercel.js +144 -165
  37. package/dist/sandboxes/vercel.js.map +1 -1
  38. package/dist/templates/sequential-reviewer/implement-prompt.md +2 -2
  39. package/dist/templates/simple-loop/prompt.md +2 -2
  40. package/package.json +15 -14
  41. package/dist/AgentProvider.d.ts +0 -134
  42. package/dist/AgentProvider.d.ts.map +0 -1
  43. package/dist/AgentProvider.js +0 -647
  44. package/dist/AgentProvider.js.map +0 -1
  45. package/dist/AgentStreamEmitter.d.ts +0 -36
  46. package/dist/AgentStreamEmitter.d.ts.map +0 -1
  47. package/dist/AgentStreamEmitter.js +0 -21
  48. package/dist/AgentStreamEmitter.js.map +0 -1
  49. package/dist/CopyToWorktree.d.ts +0 -15
  50. package/dist/CopyToWorktree.d.ts.map +0 -1
  51. package/dist/CopyToWorktree.js +0 -60
  52. package/dist/CopyToWorktree.js.map +0 -1
  53. package/dist/Display.d.ts +0 -58
  54. package/dist/Display.d.ts.map +0 -1
  55. package/dist/Display.js +0 -142
  56. package/dist/Display.js.map +0 -1
  57. package/dist/DockerLifecycle.d.ts +0 -54
  58. package/dist/DockerLifecycle.d.ts.map +0 -1
  59. package/dist/DockerLifecycle.js +0 -123
  60. package/dist/DockerLifecycle.js.map +0 -1
  61. package/dist/EnvResolver.d.ts +0 -11
  62. package/dist/EnvResolver.d.ts.map +0 -1
  63. package/dist/EnvResolver.js +0 -63
  64. package/dist/EnvResolver.js.map +0 -1
  65. package/dist/ErrorHandler.d.ts +0 -15
  66. package/dist/ErrorHandler.d.ts.map +0 -1
  67. package/dist/ErrorHandler.js +0 -85
  68. package/dist/ErrorHandler.js.map +0 -1
  69. package/dist/InitService.d.ts +0 -92
  70. package/dist/InitService.d.ts.map +0 -1
  71. package/dist/InitService.js +0 -836
  72. package/dist/InitService.js.map +0 -1
  73. package/dist/MountConfig.d.ts.map +0 -1
  74. package/dist/MountConfig.js +0 -7
  75. package/dist/MountConfig.js.map +0 -1
  76. package/dist/Orchestrator.d.ts +0 -56
  77. package/dist/Orchestrator.d.ts.map +0 -1
  78. package/dist/Orchestrator.js +0 -293
  79. package/dist/Orchestrator.js.map +0 -1
  80. package/dist/Output.d.ts +0 -107
  81. package/dist/Output.d.ts.map +0 -1
  82. package/dist/Output.js +0 -95
  83. package/dist/Output.js.map +0 -1
  84. package/dist/PodmanLifecycle.d.ts +0 -17
  85. package/dist/PodmanLifecycle.d.ts.map +0 -1
  86. package/dist/PodmanLifecycle.js +0 -45
  87. package/dist/PodmanLifecycle.js.map +0 -1
  88. package/dist/PromptArgumentSubstitution.d.ts +0 -32
  89. package/dist/PromptArgumentSubstitution.d.ts.map +0 -1
  90. package/dist/PromptArgumentSubstitution.js +0 -104
  91. package/dist/PromptArgumentSubstitution.js.map +0 -1
  92. package/dist/PromptPreprocessor.d.ts +0 -15
  93. package/dist/PromptPreprocessor.d.ts.map +0 -1
  94. package/dist/PromptPreprocessor.js +0 -55
  95. package/dist/PromptPreprocessor.js.map +0 -1
  96. package/dist/PromptResolver.d.ts +0 -21
  97. package/dist/PromptResolver.d.ts.map +0 -1
  98. package/dist/PromptResolver.js +0 -27
  99. package/dist/PromptResolver.js.map +0 -1
  100. package/dist/RecoveryMessage.d.ts +0 -15
  101. package/dist/RecoveryMessage.d.ts.map +0 -1
  102. package/dist/RecoveryMessage.js +0 -81
  103. package/dist/RecoveryMessage.js.map +0 -1
  104. package/dist/SandboxFactory.d.ts +0 -90
  105. package/dist/SandboxFactory.d.ts.map +0 -1
  106. package/dist/SandboxFactory.js +0 -324
  107. package/dist/SandboxFactory.js.map +0 -1
  108. package/dist/SandboxLifecycle.d.ts +0 -65
  109. package/dist/SandboxLifecycle.d.ts.map +0 -1
  110. package/dist/SandboxLifecycle.js +0 -296
  111. package/dist/SandboxLifecycle.js.map +0 -1
  112. package/dist/SandboxProvider.d.ts.map +0 -1
  113. package/dist/SandboxProvider.js +0 -28
  114. package/dist/SandboxProvider.js.map +0 -1
  115. package/dist/SessionStore.d.ts +0 -110
  116. package/dist/SessionStore.d.ts.map +0 -1
  117. package/dist/SessionStore.js +0 -330
  118. package/dist/SessionStore.js.map +0 -1
  119. package/dist/TextDeltaBuffer.d.ts +0 -24
  120. package/dist/TextDeltaBuffer.d.ts.map +0 -1
  121. package/dist/TextDeltaBuffer.js +0 -68
  122. package/dist/TextDeltaBuffer.js.map +0 -1
  123. package/dist/WorktreeManager.d.ts +0 -79
  124. package/dist/WorktreeManager.d.ts.map +0 -1
  125. package/dist/WorktreeManager.js +0 -283
  126. package/dist/WorktreeManager.js.map +0 -1
  127. package/dist/boundedTail.d.ts +0 -48
  128. package/dist/boundedTail.d.ts.map +0 -1
  129. package/dist/boundedTail.js +0 -64
  130. package/dist/boundedTail.js.map +0 -1
  131. package/dist/cli.d.ts +0 -30
  132. package/dist/cli.d.ts.map +0 -1
  133. package/dist/cli.js +0 -340
  134. package/dist/cli.js.map +0 -1
  135. package/dist/createSandbox.d.ts +0 -154
  136. package/dist/createSandbox.d.ts.map +0 -1
  137. package/dist/createSandbox.js +0 -476
  138. package/dist/createSandbox.js.map +0 -1
  139. package/dist/createWorktree.d.ts +0 -154
  140. package/dist/createWorktree.d.ts.map +0 -1
  141. package/dist/createWorktree.js +0 -391
  142. package/dist/createWorktree.js.map +0 -1
  143. package/dist/errors.d.ts +0 -227
  144. package/dist/errors.d.ts.map +0 -1
  145. package/dist/errors.js +0 -81
  146. package/dist/errors.js.map +0 -1
  147. package/dist/extractStructuredOutput.d.ts +0 -23
  148. package/dist/extractStructuredOutput.d.ts.map +0 -1
  149. package/dist/extractStructuredOutput.js +0 -102
  150. package/dist/extractStructuredOutput.js.map +0 -1
  151. package/dist/index.d.ts.map +0 -1
  152. package/dist/interactive.d.ts +0 -74
  153. package/dist/interactive.d.ts.map +0 -1
  154. package/dist/interactive.js +0 -279
  155. package/dist/interactive.js.map +0 -1
  156. package/dist/main.d.ts.map +0 -1
  157. package/dist/mergeProviderEnv.d.ts +0 -13
  158. package/dist/mergeProviderEnv.d.ts.map +0 -1
  159. package/dist/mergeProviderEnv.js +0 -23
  160. package/dist/mergeProviderEnv.js.map +0 -1
  161. package/dist/mountUtils.d.ts +0 -146
  162. package/dist/mountUtils.d.ts.map +0 -1
  163. package/dist/mountUtils.js +0 -301
  164. package/dist/mountUtils.js.map +0 -1
  165. package/dist/raceAbortSignal.d.ts +0 -18
  166. package/dist/raceAbortSignal.d.ts.map +0 -1
  167. package/dist/raceAbortSignal.js +0 -32
  168. package/dist/raceAbortSignal.js.map +0 -1
  169. package/dist/resolveCwd.d.ts +0 -24
  170. package/dist/resolveCwd.d.ts.map +0 -1
  171. package/dist/resolveCwd.js +0 -32
  172. package/dist/resolveCwd.js.map +0 -1
  173. package/dist/resumePrecheck.d.ts +0 -26
  174. package/dist/resumePrecheck.d.ts.map +0 -1
  175. package/dist/resumePrecheck.js +0 -40
  176. package/dist/resumePrecheck.js.map +0 -1
  177. package/dist/run.d.ts +0 -216
  178. package/dist/run.d.ts.map +0 -1
  179. package/dist/run.js +0 -313
  180. package/dist/run.js.map +0 -1
  181. package/dist/sandboxExec.d.ts +0 -12
  182. package/dist/sandboxExec.d.ts.map +0 -1
  183. package/dist/sandboxExec.js +0 -26
  184. package/dist/sandboxExec.js.map +0 -1
  185. package/dist/sandboxes/daytona.d.ts.map +0 -1
  186. package/dist/sandboxes/docker.d.ts.map +0 -1
  187. package/dist/sandboxes/no-sandbox.d.ts.map +0 -1
  188. package/dist/sandboxes/podman.d.ts.map +0 -1
  189. package/dist/sandboxes/test-bind-mount.d.ts +0 -17
  190. package/dist/sandboxes/test-bind-mount.d.ts.map +0 -1
  191. package/dist/sandboxes/test-bind-mount.js +0 -92
  192. package/dist/sandboxes/test-bind-mount.js.map +0 -1
  193. package/dist/sandboxes/test-isolated.d.ts +0 -17
  194. package/dist/sandboxes/test-isolated.d.ts.map +0 -1
  195. package/dist/sandboxes/test-isolated.js +0 -98
  196. package/dist/sandboxes/test-isolated.js.map +0 -1
  197. package/dist/sandboxes/vercel.d.ts.map +0 -1
  198. package/dist/shutdownRegistry.d.ts +0 -30
  199. package/dist/shutdownRegistry.d.ts.map +0 -1
  200. package/dist/shutdownRegistry.js +0 -73
  201. package/dist/shutdownRegistry.js.map +0 -1
  202. package/dist/startSandbox.d.ts +0 -50
  203. package/dist/startSandbox.d.ts.map +0 -1
  204. package/dist/startSandbox.js +0 -117
  205. package/dist/startSandbox.js.map +0 -1
  206. package/dist/syncIn.d.ts +0 -24
  207. package/dist/syncIn.d.ts.map +0 -1
  208. package/dist/syncIn.js +0 -107
  209. package/dist/syncIn.js.map +0 -1
  210. package/dist/syncOut.d.ts +0 -27
  211. package/dist/syncOut.d.ts.map +0 -1
  212. package/dist/syncOut.js +0 -271
  213. package/dist/syncOut.js.map +0 -1
  214. package/dist/templates.d.ts +0 -2
  215. package/dist/templates.d.ts.map +0 -1
  216. package/dist/templates.js +0 -26
  217. package/dist/templates.js.map +0 -1
  218. package/dist/terminalCleanup.d.ts +0 -30
  219. package/dist/terminalCleanup.d.ts.map +0 -1
  220. package/dist/terminalCleanup.js +0 -37
  221. package/dist/terminalCleanup.js.map +0 -1
  222. package/dist/testSandbox.d.ts +0 -8
  223. package/dist/testSandbox.d.ts.map +0 -1
  224. package/dist/testSandbox.js +0 -109
  225. package/dist/testSandbox.js.map +0 -1
  226. package/dist/testSetup.d.ts +0 -2
  227. package/dist/testSetup.d.ts.map +0 -1
  228. package/dist/testSetup.js +0 -29
  229. package/dist/testSetup.js.map +0 -1
package/README.md CHANGED
@@ -234,6 +234,12 @@ const result = await run({
234
234
  // Idle timeout in seconds — resets whenever the agent produces output. Default: 600 (10 minutes)
235
235
  idleTimeoutSeconds: 600,
236
236
 
237
+ // Grace window in seconds after the agent emits a completion signal but
238
+ // before its process has exited (a "hanging process" — typically a spawned
239
+ // `gh`/git child or MCP server keeping stdout open). Resets on every
240
+ // subsequent output line so trailing data is still captured. Default: 60
241
+ completionTimeoutSeconds: 60,
242
+
237
243
  // Structured output — extract a typed payload from the agent's stdout.
238
244
  // Requires maxIterations === 1 and the tag must appear in the prompt.
239
245
  // output: Output.object({ tag: "result", schema: z.object({ answer: z.number() }) }),
@@ -341,18 +347,19 @@ if (closeResult.preservedWorktreePath) {
341
347
 
342
348
  #### `SandboxRunOptions`
343
349
 
344
- | Option | Type | Default | Description |
345
- | -------------------- | ------------------ | ----------------------------- | ------------------------------------------------------------------- |
346
- | `agent` | AgentProvider | — | **Required.** Agent provider (e.g. `claudeCode("claude-opus-4-7")`) |
347
- | `prompt` | string | — | Inline prompt (mutually exclusive with `promptFile`) |
348
- | `promptFile` | string | — | Path to prompt file (mutually exclusive with `prompt`) |
349
- | `promptArgs` | PromptArgs | — | Key-value map for `{{KEY}}` placeholder substitution |
350
- | `maxIterations` | number | `1` | Maximum iterations to run |
351
- | `completionSignal` | string \| string[] | `<promise>COMPLETE</promise>` | String(s) the agent emits to stop the iteration loop early |
352
- | `idleTimeoutSeconds` | number | `600` | Idle timeout in seconds — resets on each agent output event |
353
- | `name` | string | | Display name for the run |
354
- | `logging` | object | file (auto-generated) | `{ type: 'file', path }` or `{ type: 'stdout' }` |
355
- | `signal` | AbortSignal | | Cancels the run when aborted; handle stays usable afterward |
350
+ | Option | Type | Default | Description |
351
+ | -------------------------- | ------------------ | ----------------------------- | ------------------------------------------------------------------------------------ |
352
+ | `agent` | AgentProvider | — | **Required.** Agent provider (e.g. `claudeCode("claude-opus-4-7")`) |
353
+ | `prompt` | string | — | Inline prompt (mutually exclusive with `promptFile`) |
354
+ | `promptFile` | string | — | Path to prompt file (mutually exclusive with `prompt`) |
355
+ | `promptArgs` | PromptArgs | — | Key-value map for `{{KEY}}` placeholder substitution |
356
+ | `maxIterations` | number | `1` | Maximum iterations to run |
357
+ | `completionSignal` | string \| string[] | `<promise>COMPLETE</promise>` | String(s) the agent emits to stop the iteration loop early |
358
+ | `idleTimeoutSeconds` | number | `600` | Idle timeout in seconds — resets on each agent output event |
359
+ | `completionTimeoutSeconds` | number | `60` | Grace window after the completion signal is seen but the agent process hasn't exited |
360
+ | `name` | string | | Display name for the run |
361
+ | `logging` | object | file (auto-generated) | `{ type: 'file', path }` or `{ type: 'stdout' }` |
362
+ | `signal` | AbortSignal | — | Cancels the run when aborted; handle stays usable afterward |
356
363
 
357
364
  #### `SandboxRunResult`
358
365
 
@@ -459,22 +466,23 @@ await sandbox.close();
459
466
 
460
467
  #### `WorktreeRunOptions`
461
468
 
462
- | Option | Type | Default | Description |
463
- | -------------------- | ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
464
- | `agent` | AgentProvider | — | **Required.** Agent provider |
465
- | `sandbox` | SandboxProvider | — | **Required.** Sandbox provider (AFK agents must be sandboxed) |
466
- | `prompt` | string | — | Inline prompt (mutually exclusive with `promptFile`) |
467
- | `promptFile` | string | — | Path to prompt file |
468
- | `maxIterations` | number | 1 | Maximum iterations to run |
469
- | `completionSignal` | string \| string[] | — | Substring(s) to stop the iteration loop early |
470
- | `idleTimeoutSeconds` | number | 600 | Idle timeout in seconds |
471
- | `name` | string | | Optional run name |
472
- | `logging` | LoggingOption | file | Logging mode |
473
- | `hooks` | SandboxHooks | | Lifecycle hooks (`host.*`, `sandbox.*`) |
474
- | `promptArgs` | PromptArgs | — | Key-value map for `{{KEY}}` placeholder substitution |
475
- | `env` | Record<string, string> | — | Environment variables to inject into the sandbox |
476
- | `resumeSession` | string | — | Resume a prior session by ID for agents that support resume. Incompatible with `maxIterations > 1`. Session file must exist on host. |
477
- | `signal` | AbortSignal | — | Cancel the run when aborted. Kills the in-flight agent subprocess; the worktree is preserved on disk. Rejects with `signal.reason`. |
469
+ | Option | Type | Default | Description |
470
+ | -------------------------- | ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
471
+ | `agent` | AgentProvider | — | **Required.** Agent provider |
472
+ | `sandbox` | SandboxProvider | — | **Required.** Sandbox provider (AFK agents must be sandboxed) |
473
+ | `prompt` | string | — | Inline prompt (mutually exclusive with `promptFile`) |
474
+ | `promptFile` | string | — | Path to prompt file |
475
+ | `maxIterations` | number | 1 | Maximum iterations to run |
476
+ | `completionSignal` | string \| string[] | — | Substring(s) to stop the iteration loop early |
477
+ | `idleTimeoutSeconds` | number | 600 | Idle timeout in seconds |
478
+ | `completionTimeoutSeconds` | number | 60 | Grace window after completion signal is seen but agent process hasn't exited |
479
+ | `name` | string | | Optional run name |
480
+ | `logging` | LoggingOption | file | Logging mode |
481
+ | `hooks` | SandboxHooks | — | Lifecycle hooks (`host.*`, `sandbox.*`) |
482
+ | `promptArgs` | PromptArgs | — | Key-value map for `{{KEY}}` placeholder substitution |
483
+ | `env` | Record<string, string> | — | Environment variables to inject into the sandbox |
484
+ | `resumeSession` | string | — | Resume a prior session by ID for agents that support resume. Incompatible with `maxIterations > 1`. Session file must exist on host. |
485
+ | `signal` | AbortSignal | — | Cancel the run when aborted. Kills the in-flight agent subprocess; the worktree is preserved on disk. Rejects with `signal.reason`. |
478
486
 
479
487
  #### `WorktreeRunResult`
480
488
 
@@ -502,7 +510,7 @@ Sandcastle uses a **branch strategy** configured on the sandbox provider to cont
502
510
 
503
511
  - **Head** (`{ type: "head" }`) — The agent writes directly to the host working directory. No worktree, no branch indirection. This is the default for bind-mount providers like `docker()`.
504
512
  - **Merge-to-head** (`{ type: "merge-to-head" }`) — Sandcastle creates a temporary branch in a git worktree. The agent works on the temp branch, and changes are merged back to HEAD when done. The temp branch is cleaned up after merge.
505
- - **Branch** (`{ type: "branch", branch: "foo" }`) — Commits land on an explicitly named branch in a git worktree.
513
+ - **Branch** (`{ type: "branch", branch: "foo" }`) — Commits land on an explicitly named branch in a git worktree. Re-running with the same branch reuses the existing worktree and fast-forwards it from `origin` when safe — see [ADR 0003](docs/adr/0003-reuse-worktree-by-default.md).
506
514
 
507
515
  For bind-mount providers (like Docker), the worktree directory is bind-mounted into the container — the agent writes directly to the host filesystem through the mount, so no sync is needed.
508
516
 
@@ -614,6 +622,25 @@ await run({
614
622
 
615
623
  Tell the agent to output your chosen string(s) in the prompt, and the orchestrator will stop when it detects any of them. The matched signal is returned as `result.completionSignal`.
616
624
 
625
+ #### Hanging processes after the completion signal
626
+
627
+ The agent process is expected to exit shortly after emitting the completion signal. When a child it spawned — a `gh`/git subprocess, a long-lived MCP server, etc. — inherits the agent's stdout pipe and keeps it open, the parent process can linger long past its logical end. Sandcastle would otherwise wait for the full `idleTimeoutSeconds` and fail with `AgentIdleTimeoutError`, throwing away the commits the agent already made.
628
+
629
+ Instead, once the completion signal is observed in the output buffer, Sandcastle swaps in a short **completion timeout** (default 60 s). When it expires, the run resolves successfully with a warning that the process was hanging; `result.commits` and `result.completionSignal` are populated as if the process had exited cleanly. The timer resets on every subsequent output line, so trailing data emitted after the signal — token-usage events, terminal `result` events, a structured-output `<tag>` — is still captured.
630
+
631
+ A clean process exit always wins the race, so healthy runs gain zero added latency. The completion timeout only matters when the process hangs.
632
+
633
+ Tune the window with `completionTimeoutSeconds`:
634
+
635
+ ```ts
636
+ await run({
637
+ // ...
638
+ completionTimeoutSeconds: 30, // shorter grace window
639
+ });
640
+ ```
641
+
642
+ This is independent of `idleTimeoutSeconds`. They cover different phases: `idleTimeoutSeconds` runs **before** any signal is seen (genuinely stuck agent → fail); `completionTimeoutSeconds` runs **after** the signal is seen (hanging process → succeed with warning). See [ADR 0019](docs/adr/0019-completion-timeout-for-hanging-process.md).
643
+
617
644
  ### Structured output
618
645
 
619
646
  Use `Output.object()` to extract a typed, schema-validated JSON payload from the agent's stdout. The agent emits its answer inside an XML tag you specify, and Sandcastle parses, validates, and returns it on `result.output`. The schema can be any [Standard Schema](https://standardschema.dev) validator — the examples below use [Zod](https://zod.dev), but Valibot, ArkType, and others work identically. See [ADR 0010](docs/adr/0010-structured-output.md) for design rationale.
@@ -684,13 +711,19 @@ Scaffolds the `.sandcastle/` config directory and builds the container image. Th
684
711
 
685
712
  Init detects your host package manager (npm, pnpm, yarn, or bun) from a `packageManager` field or lockfile, defaulting to npm. Templates whose `main` file imports a host dependency — the planner templates import [Zod](https://zod.dev) for their `<plan>` output schema — prompt you to install it with that package manager when it isn't already in your `package.json`, so the first `npx tsx .sandcastle/main.ts` doesn't fail with `ERR_MODULE_NOT_FOUND`.
686
713
 
687
- | Option | Required | Default | Description |
688
- | -------------- | -------- | ---------------------------- | ---------------------------------------------------------------------------- |
689
- | `--image-name` | No | `sandcastle:<repo-dir-name>` | Docker image name |
690
- | `--agent` | No | Interactive prompt | Agent to use (`claude-code`, `pi`, `codex`, `cursor`, `opencode`, `copilot`) |
691
- | `--model` | No | Agent's default model | Model to use (e.g. `claude-sonnet-4-6`). Defaults to agent's default |
692
- | `--sandbox` | No | Interactive prompt | Sandbox provider to use (`docker`, `podman`) |
693
- | `--template` | No | Interactive prompt | Template to scaffold (e.g. `blank`, `simple-loop`) |
714
+ Every interactive prompt has a paired `--flag` so the entire init can run non-interactively (e.g. in CI or a scripted setup). When stdin is not a TTY and a required flag is missing, init fails fast with a clear error rather than wedging on a prompt.
715
+
716
+ | Option | Required | Default | Description |
717
+ | ------------------------- | -------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------- |
718
+ | `--image-name` | No | `sandcastle:<repo-dir-name>` | Docker image name |
719
+ | `--agent` | No | Interactive prompt | Agent to use (`claude-code`, `pi`, `codex`, `cursor`, `opencode`, `copilot`) |
720
+ | `--model` | No | Agent's default model | Model to use (e.g. `claude-sonnet-4-6`). Defaults to agent's default |
721
+ | `--sandbox` | No | Interactive prompt | Sandbox provider to use (`docker`, `podman`) |
722
+ | `--template` | No | Interactive prompt | Template to scaffold (e.g. `blank`, `simple-loop`) |
723
+ | `--issue-tracker` | No | Interactive prompt | Issue tracker to use (`github-issues`, `beads`, `custom`) |
724
+ | `--create-label` | No | Interactive prompt | `true` / `false` — whether to create the `Sandcastle` GitHub label (only with `--issue-tracker github-issues`) |
725
+ | `--build-image` | No | Interactive prompt | `true` / `false` — whether to build the sandbox image now (silently ignored with `--issue-tracker custom`) |
726
+ | `--install-template-deps` | No | Interactive prompt | `true` / `false` — whether to install template host deps (e.g. `zod` for the planner templates) |
694
727
 
695
728
  Creates the following files:
696
729
 
@@ -740,26 +773,27 @@ Removes the Podman image.
740
773
 
741
774
  ### `RunOptions`
742
775
 
743
- | Option | Type | Default | Description |
744
- | -------------------- | ------------------ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
745
- | `agent` | AgentProvider | — | **Required.** Agent provider (e.g. `claudeCode("claude-opus-4-7")`, `pi("claude-sonnet-4-6")`, `codex("gpt-5.4-mini")`, `cursor("composer-2")`, `opencode("opencode/big-pickle")`, `copilot("claude-sonnet-4.5")`) |
746
- | `sandbox` | SandboxProvider | — | **Required.** Sandbox provider (e.g. `docker()`, `podman()`, `docker({ imageName: "sandcastle:local" })`) |
747
- | `cwd` | string | `process.cwd()` | Host repo directory — anchor for `.sandcastle/` artifacts and git operations. Relative paths resolve against `process.cwd()`. |
748
- | `prompt` | string | — | Inline prompt (mutually exclusive with `promptFile`) |
749
- | `promptFile` | string | — | Path to prompt file (mutually exclusive with `prompt`). Resolves against `process.cwd()`, **not** `cwd`. |
750
- | `maxIterations` | number | `1` | Maximum iterations to run |
751
- | `hooks` | SandboxHooks | — | Lifecycle hooks (`host.*`, `sandbox.*`) |
752
- | `name` | string | — | Display name for the run, shown as a prefix in log output |
753
- | `promptArgs` | PromptArgs | — | Key-value map for `{{KEY}}` placeholder substitution |
754
- | `branchStrategy` | BranchStrategy | per-provider default | Branch strategy: `{ type: 'head' }`, `{ type: 'merge-to-head' }`, or `{ type: 'branch', branch: '…' }` |
755
- | `copyToWorktree` | string[] | — | Host-relative file paths to copy into the sandbox before start (not supported with `branchStrategy: { type: 'head' }`) |
756
- | `logging` | object | file (auto-generated) | `{ type: 'file', path }` or `{ type: 'stdout' }` |
757
- | `completionSignal` | string \| string[] | `<promise>COMPLETE</promise>` | String or array of strings the agent emits to stop the iteration loop early |
758
- | `idleTimeoutSeconds` | number | `600` | Idle timeout in seconds — resets on each agent output event |
759
- | `resumeSession` | string | | Resume a prior session by ID for agents that support resume. Incompatible with `maxIterations > 1`. Session file must exist on host. |
760
- | `signal` | AbortSignal | — | Cancel the run when aborted. Kills the in-flight agent subprocess and cancels lifecycle hooks; the worktree is preserved on disk. Rejects with `signal.reason`. |
761
- | `timeouts` | Timeouts | — | Override default timeouts for built-in lifecycle steps: `copyToWorktreeMs` (60 000), `gitSetupMs` (10 000), `commitCollectionMs` (30 000), `mergeToHostMs` (30 000). |
762
- | `output` | OutputDefinition | — | Structured output definition (`Output.object()` or `Output.string(…)`). Requires `maxIterations === 1`. See [Structured output](#structured-output). |
776
+ | Option | Type | Default | Description |
777
+ | -------------------------- | ------------------ | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
778
+ | `agent` | AgentProvider | — | **Required.** Agent provider (e.g. `claudeCode("claude-opus-4-7")`, `pi("claude-sonnet-4-6")`, `codex("gpt-5.4-mini")`, `cursor("composer-2")`, `opencode("opencode/big-pickle")`, `copilot("claude-sonnet-4.5")`) |
779
+ | `sandbox` | SandboxProvider | — | **Required.** Sandbox provider (e.g. `docker()`, `podman()`, `docker({ imageName: "sandcastle:local" })`) |
780
+ | `cwd` | string | `process.cwd()` | Host repo directory — anchor for `.sandcastle/` artifacts and git operations. Relative paths resolve against `process.cwd()`. |
781
+ | `prompt` | string | — | Inline prompt (mutually exclusive with `promptFile`) |
782
+ | `promptFile` | string | — | Path to prompt file (mutually exclusive with `prompt`). Resolves against `process.cwd()`, **not** `cwd`. |
783
+ | `maxIterations` | number | `1` | Maximum iterations to run |
784
+ | `hooks` | SandboxHooks | — | Lifecycle hooks (`host.*`, `sandbox.*`) |
785
+ | `name` | string | — | Display name for the run, shown as a prefix in log output |
786
+ | `promptArgs` | PromptArgs | — | Key-value map for `{{KEY}}` placeholder substitution |
787
+ | `branchStrategy` | BranchStrategy | per-provider default | Branch strategy: `{ type: 'head' }`, `{ type: 'merge-to-head' }`, or `{ type: 'branch', branch: '…' }` |
788
+ | `copyToWorktree` | string[] | — | Host-relative file paths to copy into the sandbox before start (not supported with `branchStrategy: { type: 'head' }`) |
789
+ | `logging` | object | file (auto-generated) | `{ type: 'file', path }` or `{ type: 'stdout' }` |
790
+ | `completionSignal` | string \| string[] | `<promise>COMPLETE</promise>` | String or array of strings the agent emits to stop the iteration loop early |
791
+ | `idleTimeoutSeconds` | number | `600` | Idle timeout in seconds — resets on each agent output event |
792
+ | `completionTimeoutSeconds` | number | `60` | Grace window in seconds after the completion signal is observed but the agent process has not exited (hanging process). See [Hanging processes after the completion signal](#hanging-processes-after-the-completion-signal). |
793
+ | `resumeSession` | string | — | Resume a prior session by ID for agents that support resume. Incompatible with `maxIterations > 1`. Session file must exist on host. |
794
+ | `signal` | AbortSignal | — | Cancel the run when aborted. Kills the in-flight agent subprocess and cancels lifecycle hooks; the worktree is preserved on disk. Rejects with `signal.reason`. |
795
+ | `timeouts` | Timeouts | — | Override default timeouts for built-in lifecycle steps: `copyToWorktreeMs` (60 000), `gitSetupMs` (10 000), `commitCollectionMs` (30 000), `mergeToHostMs` (30 000). |
796
+ | `output` | OutputDefinition | — | Structured output definition (`Output.object(…)` or `Output.string(…)`). Requires `maxIterations === 1`. See [Structured output](#structured-output). |
763
797
 
764
798
  ### `RunResult`
765
799
 
@@ -792,13 +826,13 @@ Removes the Podman image.
792
826
 
793
827
  ### Session capture
794
828
 
795
- After each resumable provider iteration, Sandcastle automatically captures the agent's session file from the sandbox to the host. Claude Code sessions are stored under `~/.claude/projects/<encoded-path>/<session-id>.jsonl`; Codex sessions are stored under `~/.codex/sessions/YYYY/MM/DD/rollout-*-<session-id>.jsonl`. Any provider-specific `cwd` fields are rewritten to match the host repo root, so the provider's native resume command works.
829
+ After each resumable provider iteration, Sandcastle automatically captures the agent's session file from the sandbox to the host. Claude Code sessions are stored under `~/.claude/projects/<encoded-path>/<session-id>.jsonl`; Codex sessions are stored under `~/.codex/sessions/YYYY/MM/DD/rollout-*-<session-id>.jsonl`; Pi sessions are stored under `~/.pi/agent/sessions/--<encoded-cwd>--/<timestamp>_<session-id>.jsonl`. Any provider-specific `cwd` fields are rewritten to match the host repo root, so the provider's native resume command works.
796
830
 
797
- Session capture is enabled by default for `claudeCode()` and `codex()` and can be opted out via `captureSessions: false`. Providers without `sessionStorage` do not attempt capture. Capture failure fails the run.
831
+ Session capture is enabled by default for `claudeCode()`, `codex()`, and `pi()` and can be opted out via `captureSessions: false`. Providers without `sessionStorage` do not attempt capture. Capture failure fails the run.
798
832
 
799
833
  ### Session resume
800
834
 
801
- Pass `resumeSession` to `run()` to continue a prior Claude Code or Codex conversation inside a new sandbox:
835
+ Pass `resumeSession` to `run()` to continue a prior Claude Code, Codex, or Pi conversation inside a new sandbox:
802
836
 
803
837
  ```typescript
804
838
  const result = await run({
@@ -821,9 +855,9 @@ const first = await run({
821
855
  const second = await first.resume?.("Now implement the plan");
822
856
  ```
823
857
 
824
- `resume` is present only on results from resumable providers (Claude Code, Codex) — hence the optional-chaining call.
858
+ `resume` is present only on results from resumable providers (Claude Code, Codex, Pi) — hence the optional-chaining call.
825
859
 
826
- Before the sandbox starts, Sandcastle validates that the session file exists on the host and transfers it into the sandbox with `cwd` fields rewritten to match the sandbox-side path. Claude Code receives `--resume <id>`; Codex receives `codex exec resume <id>` with the prompt piped over stdin.
860
+ Before the sandbox starts, Sandcastle validates that the session file exists on the host and transfers it into the sandbox with `cwd` fields rewritten to match the sandbox-side path. Claude Code receives `--resume <id>`; Codex receives `codex exec resume <id>` with the prompt piped over stdin; Pi receives `--session <id>`.
827
861
 
828
862
  Constraints:
829
863
 
@@ -832,6 +866,33 @@ Constraints:
832
866
  - Only iteration 1 receives the resume flag; subsequent iterations (if any) start fresh.
833
867
  - Providers without resume support reject `resumeSession`.
834
868
 
869
+ ### Session fork
870
+
871
+ `RunResult.fork(prompt, options?)` is the sibling of `.resume()`: it continues from the last captured session but leaves the parent session JSONL untouched and writes the child under a new session id. The mechanism is the agent's native fork flag — `claude --resume <id> --fork-session` for Claude Code, `codex exec fork <id>` for Codex.
872
+
873
+ Fork enables fan-out workflows where a single parent run is the starting point for several independent children:
874
+
875
+ ```typescript
876
+ const parent = await run({
877
+ agent: claudeCode("claude-opus-4-7"),
878
+ sandbox: docker(),
879
+ prompt: "Read the codebase and summarise the data model",
880
+ });
881
+
882
+ const [reviewA, reviewB] = await Promise.all([
883
+ parent.fork?.("Review the migration plan", {
884
+ branchStrategy: { type: "branch", branch: "review-a" },
885
+ }),
886
+ parent.fork?.("Audit the auth layer", {
887
+ branchStrategy: { type: "branch", branch: "review-b" },
888
+ }),
889
+ ]);
890
+ ```
891
+
892
+ **Fork is session-only.** `--fork-session` and `codex exec fork` isolate the agent session JSONL — they do **not** isolate the branch, worktree, or sandbox. Safe concurrent fan-out (`Promise.all([r.fork(a), r.fork(b)])`) requires the caller to give each child a distinct `branch` via `branchStrategy: { type: "branch", branch: "..." }`. The default `head` and `merge-to-head` strategies are **not** safe for concurrent forks: `head` shares the host working directory across all children, and `merge-to-head` races `git merge` against the same HEAD. See [ADR 0018](docs/adr/0018-fork-is-session-only.md).
893
+
894
+ `fork` is present only on results from providers with `sessionStorage` (Claude Code, Codex) — hence the optional-chaining call. The same single-iteration and session-file constraints as `.resume()` apply.
895
+
835
896
  ### `ClaudeCodeOptions`
836
897
 
837
898
  The `claudeCode()` factory accepts an optional second argument for provider-specific options:
@@ -860,6 +921,20 @@ agent: codex("gpt-5.4", { effort: "high" });
860
921
  | `env` | `Record<string, string>` | `{}` | Environment variables injected by this agent provider |
861
922
  | `captureSessions` | `boolean` | `true` | Capture Codex rollout JSONL to host for resume |
862
923
 
924
+ ### `PiOptions`
925
+
926
+ The `pi()` factory accepts an optional second argument for provider-specific options:
927
+
928
+ ```typescript
929
+ agent: pi("claude-sonnet-4-6", { thinking: "high" });
930
+ ```
931
+
932
+ | Option | Type | Default | Description |
933
+ | ----------------- | ------------------------------------------------------------------------ | ------- | -------------------------------------------------------- |
934
+ | `thinking` | `"off"` \| `"minimal"` \| `"low"` \| `"medium"` \| `"high"` \| `"xhigh"` | — | Pi reasoning effort level via the `--thinking` flag |
935
+ | `env` | `Record<string, string>` | `{}` | Environment variables injected by this agent provider |
936
+ | `captureSessions` | `boolean` | `true` | Capture pi session JSONL to host for `pi --session <id>` |
937
+
863
938
  ### Provider `env`
864
939
 
865
940
  Both **agent providers** and **sandbox providers** accept an optional `env: Record<string, string>` in their options. These environment variables are merged with the `.sandcastle/.env` resolver output at launch time:
@@ -1252,7 +1327,7 @@ hooks: {
1252
1327
 
1253
1328
  ```bash
1254
1329
  npm install
1255
- npm run build # Build with tsgo
1330
+ npm run build # Bundle with tsup
1256
1331
  npm test # Run tests with vitest
1257
1332
  npm run typecheck # Type-check
1258
1333
  ```
@@ -4,7 +4,7 @@
4
4
  * Each entry describes a host directory to mount into the sandbox container.
5
5
  */
6
6
  /** A single bind-mount descriptor for docker()/podman() providers. */
7
- export interface MountConfig {
7
+ interface MountConfig {
8
8
  /**
9
9
  * Path on the host. Supports:
10
10
  * - Absolute paths (`/data/cache`)
@@ -22,4 +22,5 @@ export interface MountConfig {
22
22
  /** Mount as read-only. Defaults to `false`. */
23
23
  readonly readonly?: boolean;
24
24
  }
25
- //# sourceMappingURL=MountConfig.d.ts.map
25
+
26
+ export type { MountConfig as M };
@@ -5,20 +5,20 @@
5
5
  * handles worktree creation, git mount resolution, and commit extraction.
6
6
  */
7
7
  /** Result of executing a command inside a sandbox. */
8
- export interface ExecResult {
8
+ interface ExecResult {
9
9
  readonly stdout: string;
10
10
  readonly stderr: string;
11
11
  readonly exitCode: number;
12
12
  }
13
13
  /** Options for interactiveExec — the streams the provider should wire to the spawned process. */
14
- export interface InteractiveExecOptions {
14
+ interface InteractiveExecOptions {
15
15
  readonly stdin: NodeJS.ReadableStream;
16
16
  readonly stdout: NodeJS.WritableStream;
17
17
  readonly stderr: NodeJS.WritableStream;
18
18
  readonly cwd?: string;
19
19
  }
20
20
  /** Handle to a running bind-mount sandbox. */
21
- export interface BindMountSandboxHandle {
21
+ interface BindMountSandboxHandle {
22
22
  /** Absolute path to the worktree inside the sandbox. */
23
23
  readonly worktreePath: string;
24
24
  /**
@@ -56,7 +56,7 @@ export interface BindMountSandboxHandle {
56
56
  close(): Promise<void>;
57
57
  }
58
58
  /** Options passed to a bind-mount provider's `create` function. */
59
- export interface BindMountCreateOptions {
59
+ interface BindMountCreateOptions {
60
60
  /** Host-side path to the worktree directory. */
61
61
  readonly worktreePath: string;
62
62
  /** Host-side path to the original repo root. */
@@ -71,7 +71,7 @@ export interface BindMountCreateOptions {
71
71
  readonly env: Record<string, string>;
72
72
  }
73
73
  /** Configuration for createBindMountSandboxProvider. */
74
- export interface BindMountSandboxProviderConfig {
74
+ interface BindMountSandboxProviderConfig {
75
75
  /** Human-readable name for this provider (e.g. "docker", "podman"). */
76
76
  readonly name: string;
77
77
  /** Environment variables injected by this provider. Merged at launch time. */
@@ -86,7 +86,7 @@ export interface BindMountSandboxProviderConfig {
86
86
  readonly create: (options: BindMountCreateOptions) => Promise<BindMountSandboxHandle>;
87
87
  }
88
88
  /** Handle to a running isolated sandbox (extends bind-mount with file transfer). */
89
- export interface IsolatedSandboxHandle {
89
+ interface IsolatedSandboxHandle {
90
90
  /** Absolute path to the worktree inside the sandbox. */
91
91
  readonly worktreePath: string;
92
92
  /**
@@ -124,12 +124,12 @@ export interface IsolatedSandboxHandle {
124
124
  close(): Promise<void>;
125
125
  }
126
126
  /** Options passed to an isolated provider's `create` function. */
127
- export interface IsolatedCreateOptions {
127
+ interface IsolatedCreateOptions {
128
128
  /** Environment variables to inject into the sandbox. */
129
129
  readonly env: Record<string, string>;
130
130
  }
131
131
  /** Configuration for createIsolatedSandboxProvider. */
132
- export interface IsolatedSandboxProviderConfig {
132
+ interface IsolatedSandboxProviderConfig {
133
133
  /** Human-readable name for this provider (e.g. "daytona", "e2b"). */
134
134
  readonly name: string;
135
135
  /** Environment variables injected by this provider. Merged at launch time. */
@@ -138,9 +138,7 @@ export interface IsolatedSandboxProviderConfig {
138
138
  readonly create: (options: IsolatedCreateOptions) => Promise<IsolatedSandboxHandle>;
139
139
  }
140
140
  /** A bind-mount sandbox provider. */
141
- export interface BindMountSandboxProvider {
142
- /** @internal Discriminator for internal dispatch. */
143
- readonly tag: "bind-mount";
141
+ interface BindMountSandboxProvider {
144
142
  /** Human-readable provider name. */
145
143
  readonly name: string;
146
144
  /** Environment variables injected by this provider. */
@@ -150,22 +148,16 @@ export interface BindMountSandboxProvider {
150
148
  * `undefined` when the provider does not declare a sandbox home directory.
151
149
  */
152
150
  readonly sandboxHomedir: string | undefined;
153
- /** @internal Create a sandbox handle. */
154
- readonly create: (options: BindMountCreateOptions) => Promise<BindMountSandboxHandle>;
155
151
  }
156
152
  /** An isolated sandbox provider. */
157
- export interface IsolatedSandboxProvider {
158
- /** @internal Discriminator for internal dispatch. */
159
- readonly tag: "isolated";
153
+ interface IsolatedSandboxProvider {
160
154
  /** Human-readable provider name. */
161
155
  readonly name: string;
162
156
  /** Environment variables injected by this provider. */
163
157
  readonly env: Record<string, string>;
164
- /** @internal Create an isolated sandbox handle. */
165
- readonly create: (options: IsolatedCreateOptions) => Promise<IsolatedSandboxHandle>;
166
158
  }
167
159
  /** Handle to a no-sandbox session — runs commands directly on the host. */
168
- export interface NoSandboxHandle {
160
+ interface NoSandboxHandle {
169
161
  /** Absolute path to the worktree on the host. */
170
162
  readonly worktreePath: string;
171
163
  /**
@@ -194,29 +186,22 @@ export interface NoSandboxHandle {
194
186
  close(): Promise<void>;
195
187
  }
196
188
  /** A no-sandbox provider — runs the agent directly on the host with no container isolation. */
197
- export interface NoSandboxProvider {
198
- /** @internal Discriminator for internal dispatch. */
199
- readonly tag: "none";
189
+ interface NoSandboxProvider {
200
190
  /** Human-readable provider name. */
201
191
  readonly name: string;
202
192
  /** Environment variables injected by this provider. */
203
193
  readonly env: Record<string, string>;
204
- /** @internal Create a no-sandbox handle. */
205
- readonly create: (options: {
206
- readonly worktreePath: string;
207
- readonly env: Record<string, string>;
208
- }) => Promise<NoSandboxHandle>;
209
194
  }
210
195
  /** Head strategy: agent writes directly to host working directory. Bind-mount only. */
211
- export interface HeadBranchStrategy {
196
+ interface HeadBranchStrategy {
212
197
  readonly type: "head";
213
198
  }
214
199
  /** Merge-to-head strategy: temp branch, merge back to HEAD, delete temp branch. */
215
- export interface MergeToHeadBranchStrategy {
200
+ interface MergeToHeadBranchStrategy {
216
201
  readonly type: "merge-to-head";
217
202
  }
218
203
  /** Branch strategy: commits land on an explicit named branch. */
219
- export interface NamedBranchStrategy {
204
+ interface NamedBranchStrategy {
220
205
  readonly type: "branch";
221
206
  readonly branch: string;
222
207
  /**
@@ -228,30 +213,31 @@ export interface NamedBranchStrategy {
228
213
  readonly baseBranch?: string;
229
214
  }
230
215
  /** Branch strategy for bind-mount providers (all three variants). */
231
- export type BindMountBranchStrategy = HeadBranchStrategy | MergeToHeadBranchStrategy | NamedBranchStrategy;
216
+ type BindMountBranchStrategy = HeadBranchStrategy | MergeToHeadBranchStrategy | NamedBranchStrategy;
232
217
  /** Branch strategy for isolated providers (no head — can't write to host). */
233
- export type IsolatedBranchStrategy = MergeToHeadBranchStrategy | NamedBranchStrategy;
218
+ type IsolatedBranchStrategy = MergeToHeadBranchStrategy | NamedBranchStrategy;
234
219
  /** Branch strategy for no-sandbox providers (all three — same as bind-mount). */
235
- export type NoSandboxBranchStrategy = HeadBranchStrategy | MergeToHeadBranchStrategy | NamedBranchStrategy;
220
+ type NoSandboxBranchStrategy = HeadBranchStrategy | MergeToHeadBranchStrategy | NamedBranchStrategy;
236
221
  /** Union of all branch strategy variants. */
237
- export type BranchStrategy = BindMountBranchStrategy | IsolatedBranchStrategy | NoSandboxBranchStrategy;
222
+ type BranchStrategy = BindMountBranchStrategy | IsolatedBranchStrategy | NoSandboxBranchStrategy;
238
223
  /**
239
224
  * A sandbox provider — the pluggable unit that `run()`, `interactive()`, and
240
225
  * `createSandbox()` accept. Tagged for internal dispatch: "bind-mount",
241
226
  * "isolated", or "none". When `NoSandboxProvider` is used, the agent runs
242
227
  * directly on the host with no container isolation — opt in at your own risk.
243
228
  */
244
- export type SandboxProvider = BindMountSandboxProvider | IsolatedSandboxProvider | NoSandboxProvider;
229
+ type SandboxProvider = BindMountSandboxProvider | IsolatedSandboxProvider | NoSandboxProvider;
245
230
  /** @deprecated Use `SandboxProvider` — it now includes `NoSandboxProvider`. */
246
- export type AnySandboxProvider = SandboxProvider;
231
+ type AnySandboxProvider = SandboxProvider;
247
232
  /**
248
233
  * Create a bind-mount sandbox provider from a config object.
249
234
  * The returned provider can be passed to `run()` or `createSandbox()`.
250
235
  */
251
- export declare const createBindMountSandboxProvider: (config: BindMountSandboxProviderConfig) => BindMountSandboxProvider;
236
+ declare const createBindMountSandboxProvider: (config: BindMountSandboxProviderConfig) => BindMountSandboxProvider;
252
237
  /**
253
238
  * Create an isolated sandbox provider from a config object.
254
239
  * The returned provider can be passed to `run()` or `createSandbox()`.
255
240
  */
256
- export declare const createIsolatedSandboxProvider: (config: IsolatedSandboxProviderConfig) => IsolatedSandboxProvider;
257
- //# sourceMappingURL=SandboxProvider.d.ts.map
241
+ declare const createIsolatedSandboxProvider: (config: IsolatedSandboxProviderConfig) => IsolatedSandboxProvider;
242
+
243
+ export { type AnySandboxProvider as A, type BindMountSandboxHandle as B, type ExecResult as E, type HeadBranchStrategy as H, type IsolatedSandboxProvider as I, type MergeToHeadBranchStrategy as M, type NoSandboxProvider as N, type SandboxProvider as S, type BranchStrategy as a, type NamedBranchStrategy as b, type BindMountBranchStrategy as c, type BindMountCreateOptions as d, type BindMountSandboxProvider as e, type BindMountSandboxProviderConfig as f, type InteractiveExecOptions as g, type IsolatedBranchStrategy as h, type IsolatedCreateOptions as i, type IsolatedSandboxHandle as j, type IsolatedSandboxProviderConfig as k, type NoSandboxBranchStrategy as l, type NoSandboxHandle as m, createBindMountSandboxProvider as n, createIsolatedSandboxProvider as o };