@rockclaver/sandcastle 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 (62) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1355 -0
  3. package/dist/MountConfig-CmXclHA5.d.ts +26 -0
  4. package/dist/SandboxProvider-EkSMuBp8.d.ts +243 -0
  5. package/dist/chunk-72UVAC7B.js +99 -0
  6. package/dist/chunk-72UVAC7B.js.map +1 -0
  7. package/dist/chunk-BIWNFKGV.js +22 -0
  8. package/dist/chunk-BIWNFKGV.js.map +1 -0
  9. package/dist/chunk-FKX3DRTL.js +362 -0
  10. package/dist/chunk-FKX3DRTL.js.map +1 -0
  11. package/dist/chunk-NGBM7T3E.js +76 -0
  12. package/dist/chunk-NGBM7T3E.js.map +1 -0
  13. package/dist/chunk-QCLZLPJ7.js +26431 -0
  14. package/dist/chunk-QCLZLPJ7.js.map +1 -0
  15. package/dist/chunk-VAKEM3U2.js +26997 -0
  16. package/dist/chunk-VAKEM3U2.js.map +1 -0
  17. package/dist/index.d.ts +943 -0
  18. package/dist/index.js +2393 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/main.d.ts +1 -0
  21. package/dist/main.js +19268 -0
  22. package/dist/main.js.map +1 -0
  23. package/dist/mountUtils-CCA-bbpK.d.ts +25 -0
  24. package/dist/sandboxes/daytona.d.ts +60 -0
  25. package/dist/sandboxes/daytona.js +122 -0
  26. package/dist/sandboxes/daytona.js.map +1 -0
  27. package/dist/sandboxes/docker.d.ts +110 -0
  28. package/dist/sandboxes/docker.js +9 -0
  29. package/dist/sandboxes/docker.js.map +1 -0
  30. package/dist/sandboxes/no-sandbox.d.ts +38 -0
  31. package/dist/sandboxes/no-sandbox.js +7 -0
  32. package/dist/sandboxes/no-sandbox.js.map +1 -0
  33. package/dist/sandboxes/podman.d.ts +124 -0
  34. package/dist/sandboxes/podman.js +299 -0
  35. package/dist/sandboxes/podman.js.map +1 -0
  36. package/dist/sandboxes/vercel.d.ts +104 -0
  37. package/dist/sandboxes/vercel.js +148 -0
  38. package/dist/sandboxes/vercel.js.map +1 -0
  39. package/dist/templates/blank/main.mts +14 -0
  40. package/dist/templates/blank/prompt.md +12 -0
  41. package/dist/templates/blank/template.json +4 -0
  42. package/dist/templates/parallel-planner/implement-prompt.md +62 -0
  43. package/dist/templates/parallel-planner/main.mts +204 -0
  44. package/dist/templates/parallel-planner/merge-prompt.md +26 -0
  45. package/dist/templates/parallel-planner/plan-prompt.md +37 -0
  46. package/dist/templates/parallel-planner/template.json +4 -0
  47. package/dist/templates/parallel-planner-with-review/CODING_STANDARDS.md +27 -0
  48. package/dist/templates/parallel-planner-with-review/implement-prompt.md +62 -0
  49. package/dist/templates/parallel-planner-with-review/main.mts +226 -0
  50. package/dist/templates/parallel-planner-with-review/merge-prompt.md +26 -0
  51. package/dist/templates/parallel-planner-with-review/plan-prompt.md +37 -0
  52. package/dist/templates/parallel-planner-with-review/review-prompt.md +55 -0
  53. package/dist/templates/parallel-planner-with-review/template.json +4 -0
  54. package/dist/templates/sequential-reviewer/CODING_STANDARDS.md +27 -0
  55. package/dist/templates/sequential-reviewer/implement-prompt.md +53 -0
  56. package/dist/templates/sequential-reviewer/main.mts +119 -0
  57. package/dist/templates/sequential-reviewer/review-prompt.md +55 -0
  58. package/dist/templates/sequential-reviewer/template.json +4 -0
  59. package/dist/templates/simple-loop/main.mts +49 -0
  60. package/dist/templates/simple-loop/prompt.md +53 -0
  61. package/dist/templates/simple-loop/template.json +4 -0
  62. package/package.json +104 -0
@@ -0,0 +1,943 @@
1
+ import { B as BindMountSandboxHandle, S as SandboxProvider, a as BranchStrategy, A as AnySandboxProvider, M as MergeToHeadBranchStrategy, b as NamedBranchStrategy } from './SandboxProvider-EkSMuBp8.js';
2
+ export { c as BindMountBranchStrategy, d as BindMountCreateOptions, e as BindMountSandboxProvider, f as BindMountSandboxProviderConfig, E as ExecResult, H as HeadBranchStrategy, g as InteractiveExecOptions, h as IsolatedBranchStrategy, i as IsolatedCreateOptions, j as IsolatedSandboxHandle, I as IsolatedSandboxProvider, k as IsolatedSandboxProviderConfig, l as NoSandboxBranchStrategy, m as NoSandboxHandle, N as NoSandboxProvider, n as createBindMountSandboxProvider, o as createIsolatedSandboxProvider } from './SandboxProvider-EkSMuBp8.js';
3
+ import { StandardSchemaV1 } from '@standard-schema/spec';
4
+ export { M as MountConfig } from './MountConfig-CmXclHA5.js';
5
+
6
+ /**
7
+ * Session JSONL transfer primitives.
8
+ *
9
+ * The transfer functions are pure: they take a JSONL string and the source/
10
+ * target cwds, and return the rewritten JSONL string. Call sites do their own
11
+ * file I/O (reading the source, writing the destination). Per ADR 0012, the
12
+ * cwd rewrite is specific to each agent's JSONL format, so each agent owns
13
+ * its own transfer function.
14
+ */
15
+
16
+ /**
17
+ * Result of locating a session on the host by its unique id, independent of any
18
+ * cwd-derived path encoding.
19
+ */
20
+ interface HostSessionLookup {
21
+ /** Absolute path to the located session file, or `undefined` when no session
22
+ * with this id exists anywhere under the searched root. */
23
+ readonly path: string | undefined;
24
+ /** The host directory that was scanned — surfaced in not-found errors so the
25
+ * user knows where Sandcastle looked. */
26
+ readonly searchedRoot: string;
27
+ }
28
+ /**
29
+ * Encode a cwd into the Claude Code `~/.claude/projects/<encoded>/` layout.
30
+ * Replaces path separators with hyphens, matching Claude Code's convention.
31
+ */
32
+ declare const encodeProjectPath: (cwd: string) => string;
33
+ /** Absolute host path to a Claude session JSONL file. */
34
+ declare const claudeHostSessionPath: (cwd: string, id: string, projectsDir?: string) => string;
35
+ /** Sandbox-side path to a Claude session JSONL file (always POSIX separators). */
36
+ declare const claudeSandboxSessionPath: (cwd: string, id: string, projectsDir: string) => string;
37
+ /**
38
+ * Locate a Claude Code session JSONL on the host by its unique id, scanning each
39
+ * `~/.claude/projects/<encoded-cwd>/` directory rather than reconstructing the
40
+ * cwd encoding. The session id is globally unique, so the first match wins.
41
+ */
42
+ declare const findClaudeSessionOnHost: (id: string, projectsDir?: string) => Promise<HostSessionLookup>;
43
+ /**
44
+ * Rewrite a Claude Code session JSONL string, replacing `cwd` fields that
45
+ * match `fromCwd` with `toCwd`. Pure function — no file I/O.
46
+ */
47
+ declare const transferClaudeSession: (jsonl: string, fromCwd: string, toCwd: string) => string;
48
+ /**
49
+ * Locate a Codex session rollout file on the host by its id, reusing the
50
+ * date-nested scan.
51
+ */
52
+ declare const findCodexSessionOnHost: (id: string, sessionsDir?: string) => Promise<HostSessionLookup>;
53
+ /**
54
+ * Rewrite a Codex session JSONL string, replacing `cwd` fields (both top-level
55
+ * and `session_meta.payload.cwd`) that match `fromCwd` with `toCwd`. Pure
56
+ * function — no file I/O.
57
+ */
58
+ declare const transferCodexSession: (jsonl: string, fromCwd: string, toCwd: string) => string;
59
+
60
+ type ParsedStreamEvent = {
61
+ type: "text";
62
+ text: string;
63
+ } | {
64
+ type: "result";
65
+ result: string;
66
+ } | {
67
+ type: "tool_call";
68
+ name: string;
69
+ args: string;
70
+ } | {
71
+ type: "session_id";
72
+ sessionId: string;
73
+ } | {
74
+ type: "usage";
75
+ usage: IterationUsage;
76
+ };
77
+ /** Options passed to buildPrintCommand and buildInteractiveArgs. */
78
+ interface AgentCommandOptions {
79
+ readonly prompt: string;
80
+ readonly dangerouslySkipPermissions: boolean;
81
+ /** When set, the agent should resume the given session ID instead of starting fresh. */
82
+ readonly resumeSession?: string;
83
+ /**
84
+ * When true alongside `resumeSession`, the agent should fork the session
85
+ * instead of mutating it — Claude's `--fork-session`, Codex's
86
+ * `codex exec fork`. The parent session JSONL is left intact and the agent
87
+ * writes a new session under a fresh id.
88
+ */
89
+ readonly forkSession?: boolean;
90
+ }
91
+ /** Return type of buildPrintCommand — command string plus optional stdin content.
92
+ * When `stdin` is set, the sandbox pipes it to the child process's stdin
93
+ * instead of inlining the prompt in argv, avoiding the Linux 128 KB per-arg limit. */
94
+ interface PrintCommand {
95
+ readonly command: string;
96
+ readonly stdin?: string;
97
+ }
98
+ /** Per-iteration token usage snapshot extracted from the agent session. */
99
+ interface IterationUsage {
100
+ readonly inputTokens: number;
101
+ readonly cacheCreationInputTokens: number;
102
+ readonly cacheReadInputTokens: number;
103
+ readonly outputTokens: number;
104
+ }
105
+ interface AgentSessionStorage {
106
+ /** Transfer a session JSONL from the sandbox into the host store. */
107
+ captureToHost(args: {
108
+ hostCwd: string;
109
+ sandboxCwd: string;
110
+ sessionId: string;
111
+ handle: BindMountSandboxHandle;
112
+ }): Promise<void>;
113
+ /** Transfer a session JSONL from the host store into the sandbox. */
114
+ resumeIntoSandbox(args: {
115
+ hostCwd: string;
116
+ sandboxCwd: string;
117
+ sessionId: string;
118
+ handle: BindMountSandboxHandle;
119
+ }): Promise<void>;
120
+ /** Read a captured session JSONL from the host store. Returns undefined when absent. */
121
+ readHostSession(cwd: string, sessionId: string): Promise<string | undefined>;
122
+ /** Whether a session with the given id exists in the host store keyed on cwd. */
123
+ existsOnHost(cwd: string, sessionId: string): Promise<boolean>;
124
+ /** Absolute host path where a session would be stored (for not-found error messages). */
125
+ hostSessionFilePath(cwd: string, sessionId: string): string | undefined;
126
+ /**
127
+ * Locate a session on the host by its unique id, independent of cwd encoding.
128
+ * Used by the no-sandbox resume precheck, where the agent runs on the host and
129
+ * writes the session in place under a cwd-derived directory Sandcastle cannot
130
+ * reliably reconstruct. Returns the located path (or `undefined`) plus the
131
+ * directory that was searched (for not-found errors).
132
+ */
133
+ findByIdOnHost(sessionId: string): Promise<HostSessionLookup>;
134
+ }
135
+ interface AgentProvider {
136
+ readonly name: string;
137
+ /** Environment variables injected by this agent provider. Merged at launch time with env resolver and sandbox provider env. */
138
+ readonly env: Record<string, string>;
139
+ /** When true, session capture is enabled for this provider. Default: true for Claude Code, false for others. */
140
+ readonly captureSessions: boolean;
141
+ /** Provider-owned storage and transfer behavior for resumable agent sessions. */
142
+ readonly sessionStorage?: AgentSessionStorage;
143
+ buildPrintCommand(options: AgentCommandOptions): PrintCommand;
144
+ buildInteractiveArgs?(options: AgentCommandOptions): string[];
145
+ parseStreamLine(line: string): ParsedStreamEvent[];
146
+ /** Parse token usage from the captured session JSONL content. Only implemented by Claude Code. */
147
+ parseSessionUsage?(content: string): IterationUsage | undefined;
148
+ }
149
+ declare const AGENT_DEFAULT_MODELS: {
150
+ readonly "claude-code": "claude-opus-4-7";
151
+ readonly pi: "claude-sonnet-4-6";
152
+ readonly codex: "gpt-5.4-mini";
153
+ readonly cursor: "composer-2";
154
+ readonly opencode: "opencode/big-pickle";
155
+ readonly copilot: "claude-sonnet-4.5";
156
+ };
157
+ type AgentName = keyof typeof AGENT_DEFAULT_MODELS;
158
+ /** Options for the pi agent provider. */
159
+ interface PiOptions {
160
+ /** Reasoning effort level. Maps to the CLI's --thinking flag. */
161
+ readonly thinking?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
162
+ /** Environment variables injected by this agent provider. */
163
+ readonly env?: Record<string, string>;
164
+ /** When false, session capture is disabled. Default: true. */
165
+ readonly captureSessions?: boolean;
166
+ /** Override pi session directories for tests or non-standard installs. */
167
+ readonly sessionStorage?: {
168
+ readonly hostSessionsDir?: string;
169
+ readonly sandboxSessionsDir?: string;
170
+ };
171
+ }
172
+ declare const pi: (model: string, options?: PiOptions) => AgentProvider & {
173
+ readonly sessionStorage: AgentSessionStorage;
174
+ };
175
+ /** Options for the codex agent provider. */
176
+ interface CodexOptions {
177
+ readonly effort?: "low" | "medium" | "high" | "xhigh";
178
+ /** Environment variables injected by this agent provider. */
179
+ readonly env?: Record<string, string>;
180
+ /** When false, session capture is disabled. Default: true. */
181
+ readonly captureSessions?: boolean;
182
+ /** Override Codex session directories for tests or non-standard installs. */
183
+ readonly sessionStorage?: {
184
+ readonly hostSessionsDir?: string;
185
+ readonly sandboxSessionsDir?: string;
186
+ };
187
+ }
188
+ declare const codex: (model: string, options?: CodexOptions) => AgentProvider & {
189
+ readonly sessionStorage: AgentSessionStorage;
190
+ };
191
+ /** Options for the cursor agent provider. */
192
+ interface CursorOptions {
193
+ /** Environment variables injected by this agent provider. */
194
+ readonly env?: Record<string, string>;
195
+ }
196
+ declare const cursor: (model: string, options?: CursorOptions) => AgentProvider;
197
+ /** Options for the opencode agent provider. */
198
+ interface OpenCodeOptions {
199
+ /** Provider-specific reasoning effort variant (e.g. "high", "max", "low", "minimal"). */
200
+ readonly variant?: string;
201
+ /**
202
+ * Named OpenCode agent/mode to run, mapped to OpenCode's own `--agent` flag
203
+ * (e.g. "build", "plan"). This is distinct from Sandcastle's `--agent`
204
+ * provider selector — it chooses an agent *inside* OpenCode.
205
+ */
206
+ readonly agent?: string;
207
+ /** Environment variables injected by this agent provider. */
208
+ readonly env?: Record<string, string>;
209
+ }
210
+ declare const opencode: (model: string, options?: OpenCodeOptions) => AgentProvider;
211
+ /** Options for the GitHub Copilot CLI agent provider. */
212
+ interface CopilotOptions {
213
+ /** Reasoning effort level. Maps to the CLI's --effort flag. */
214
+ readonly effort?: "low" | "medium" | "high";
215
+ /** Environment variables injected by this agent provider. */
216
+ readonly env?: Record<string, string>;
217
+ }
218
+ declare const copilot: (model: string, options?: CopilotOptions) => AgentProvider;
219
+ interface ClaudeCodeOptions {
220
+ readonly effort?: "low" | "medium" | "high" | "xhigh" | "max";
221
+ /** Environment variables injected by this agent provider. */
222
+ readonly env?: Record<string, string>;
223
+ /** When false, session capture is disabled. Default: true. */
224
+ readonly captureSessions?: boolean;
225
+ /** Override Claude session directories for tests or non-standard installs. */
226
+ readonly sessionStorage?: {
227
+ readonly hostProjectsDir?: string;
228
+ readonly sandboxProjectsDir?: string;
229
+ };
230
+ }
231
+ declare const claudeCode: (model: string, options?: ClaudeCodeOptions) => AgentProvider & {
232
+ readonly sessionStorage: AgentSessionStorage;
233
+ };
234
+ interface AgentResolverOptions {
235
+ /** Provider name used when AGENT is unset. */
236
+ readonly default?: AgentName;
237
+ /** Environment source for AGENT and AGENT_MODEL. Defaults to process.env. */
238
+ readonly env?: Record<string, string | undefined>;
239
+ readonly claudeCode?: ClaudeCodeOptions;
240
+ readonly "claude-code"?: ClaudeCodeOptions;
241
+ readonly pi?: PiOptions;
242
+ readonly codex?: CodexOptions;
243
+ readonly cursor?: CursorOptions;
244
+ readonly opencode?: OpenCodeOptions;
245
+ readonly copilot?: CopilotOptions;
246
+ }
247
+ declare const agent: (options?: AgentResolverOptions) => AgentProvider;
248
+
249
+ /**
250
+ * A single event in the agent's output stream, surfaced to callers of `run()`
251
+ * so they can forward it to their own observability system.
252
+ *
253
+ * Emitted only in log-to-file mode when an `onAgentStreamEvent` callback is
254
+ * provided via `logging`. See `run()`.
255
+ */
256
+ type AgentStreamEvent = {
257
+ readonly type: "text";
258
+ readonly message: string;
259
+ readonly iteration: number;
260
+ readonly timestamp: Date;
261
+ } | {
262
+ readonly type: "toolCall";
263
+ readonly name: string;
264
+ readonly formattedArgs: string;
265
+ readonly iteration: number;
266
+ readonly timestamp: Date;
267
+ };
268
+
269
+ type SandboxHooks = {
270
+ readonly host?: {
271
+ readonly onWorktreeReady?: ReadonlyArray<{
272
+ readonly command: string;
273
+ readonly timeoutMs?: number;
274
+ }>;
275
+ readonly onSandboxReady?: ReadonlyArray<{
276
+ readonly command: string;
277
+ readonly timeoutMs?: number;
278
+ }>;
279
+ };
280
+ readonly sandbox?: {
281
+ readonly onSandboxReady?: ReadonlyArray<{
282
+ readonly command: string;
283
+ readonly sudo?: boolean;
284
+ readonly timeoutMs?: number;
285
+ }>;
286
+ };
287
+ };
288
+
289
+ /** Per-iteration result carrying an optional session ID. */
290
+ interface IterationResult {
291
+ /** Claude Code session ID extracted from the init line, or undefined for non-Claude agents. */
292
+ readonly sessionId?: string;
293
+ /** Absolute host path to the captured session JSONL, or undefined when capture is disabled or provider is non-Claude. */
294
+ readonly sessionFilePath?: string;
295
+ /** Token usage snapshot from the last assistant message in the session, or undefined when capture is disabled or provider does not support usage parsing. */
296
+ readonly usage?: IterationUsage;
297
+ }
298
+
299
+ /**
300
+ * A map of named values used for prompt argument substitution.
301
+ * Each key corresponds to a `{{KEY}}` placeholder in the prompt; the value
302
+ * replaces it before the prompt is passed to the agent.
303
+ */
304
+ type PromptArgs = Record<string, string | number | boolean>;
305
+
306
+ /** Branded output definition for `Output.object({ tag, schema })`. */
307
+ interface OutputObjectDefinition<T> {
308
+ readonly _tag: "object";
309
+ readonly tag: string;
310
+ readonly schema: StandardSchemaV1<unknown, T>;
311
+ }
312
+ /** Branded output definition for `Output.string({ tag })`. */
313
+ interface OutputStringDefinition {
314
+ readonly _tag: "string";
315
+ readonly tag: string;
316
+ }
317
+ /** Union of all output definition shapes accepted by `run()`. */
318
+ type OutputDefinition = OutputObjectDefinition<any> | OutputStringDefinition;
319
+ /**
320
+ * Helpers for declaring structured output on `run()`.
321
+ *
322
+ * ```ts
323
+ * import { Output, run } from "@ai-hero/sandcastle";
324
+ * import { z } from "zod";
325
+ *
326
+ * const result = await run({
327
+ * output: Output.object({ tag: "result", schema: z.object({ answer: z.number() }) }),
328
+ * // ...
329
+ * });
330
+ * console.log(result.output.answer); // typed as number
331
+ * ```
332
+ */
333
+ declare const Output: {
334
+ /**
335
+ * Declare an object-typed structured output extracted from an XML tag in
336
+ * the agent's stdout. The tag contents are JSON-parsed (with fence-aware
337
+ * unwrapping) and validated against the provided Standard Schema validator.
338
+ */
339
+ readonly object: <Schema extends StandardSchemaV1>(opts: {
340
+ tag: string;
341
+ schema: Schema;
342
+ }) => OutputObjectDefinition<StandardSchemaV1.InferOutput<Schema>>;
343
+ /**
344
+ * Declare a string-typed structured output extracted from an XML tag in
345
+ * the agent's stdout. The tag contents are whitespace-trimmed and returned
346
+ * as a plain string — no JSON parsing, no schema validation.
347
+ */
348
+ readonly string: (opts: {
349
+ tag: string;
350
+ }) => OutputStringDefinition;
351
+ };
352
+ interface StructuredOutputErrorOptions {
353
+ readonly tag: string;
354
+ readonly rawMatched: string | undefined;
355
+ readonly cause?: unknown;
356
+ readonly commits: {
357
+ sha: string;
358
+ }[];
359
+ readonly branch: string;
360
+ readonly preservedWorktreePath?: string;
361
+ readonly sessionId?: string;
362
+ readonly sessionFilePath?: string;
363
+ }
364
+ /**
365
+ * Thrown by `run()` when structured output extraction or validation fails.
366
+ *
367
+ * Possible failure modes:
368
+ * - The configured XML tag was not found in stdout (`rawMatched` is `undefined`).
369
+ * - The tag contents failed `JSON.parse` (`cause` carries the parse error).
370
+ * - The parsed JSON failed schema validation (`cause` carries the Standard Schema issues).
371
+ *
372
+ * The error carries `commits`, `branch`, and optionally `preservedWorktreePath`
373
+ * so callers can decide recovery without losing the run's side effects.
374
+ *
375
+ * It also carries `sessionId` (and `sessionFilePath` when the session was
376
+ * captured to the host) of the iteration that produced the bad output, so a
377
+ * caller can resume that same session and ask the agent to re-emit corrected
378
+ * output:
379
+ *
380
+ * ```ts
381
+ * try {
382
+ * return await run({ ...opts, output });
383
+ * } catch (e) {
384
+ * if (e instanceof StructuredOutputError && e.sessionId) {
385
+ * return await run({
386
+ * ...opts,
387
+ * output,
388
+ * resumeSession: e.sessionId,
389
+ * prompt: feedback(e),
390
+ * });
391
+ * }
392
+ * throw e;
393
+ * }
394
+ * ```
395
+ */
396
+ declare class StructuredOutputError extends Error {
397
+ readonly tag: string;
398
+ readonly rawMatched: string | undefined;
399
+ readonly cause: unknown;
400
+ readonly commits: {
401
+ sha: string;
402
+ }[];
403
+ readonly branch: string;
404
+ readonly preservedWorktreePath?: string;
405
+ /** Session ID of the iteration that produced the bad output, when available. */
406
+ readonly sessionId?: string;
407
+ /** Host path to the captured session JSONL, when the session was captured. */
408
+ readonly sessionFilePath?: string;
409
+ constructor(message: string, options: StructuredOutputErrorOptions);
410
+ }
411
+
412
+ /**
413
+ * Controls where Sandcastle writes iteration progress and agent output.
414
+ * Use `"file"` (log-to-file mode) to write to a log file on disk, or
415
+ * `"stdout"` (terminal mode) to render an interactive UI in the terminal.
416
+ */
417
+ type LoggingOption =
418
+ /** Write progress and agent output to a log file at the given path (log-to-file mode). */
419
+ {
420
+ readonly type: "file";
421
+ readonly path: string;
422
+ /**
423
+ * Optional callback invoked for each agent stream event (text chunk or
424
+ * tool call) in addition to being written to the log file. Intended for
425
+ * forwarding the agent's output stream to external observability
426
+ * systems. Errors thrown by the callback are swallowed.
427
+ */
428
+ readonly onAgentStreamEvent?: (event: AgentStreamEvent) => void;
429
+ }
430
+ /** Render progress and agent output as an interactive UI in the terminal (terminal mode). */
431
+ | {
432
+ readonly type: "stdout";
433
+ };
434
+ /** Override default timeouts for built-in lifecycle steps. Unset keys keep their defaults. */
435
+ interface Timeouts {
436
+ /** Timeout (ms) for the host-side copy of `copyToWorktree` paths into the worktree. Default: 60_000. */
437
+ readonly copyToWorktreeMs?: number;
438
+ /** Timeout (ms) for each in-sandbox git setup command (safe.directory, user.name/email, branch discovery). Default: 10_000. */
439
+ readonly gitSetupMs?: number;
440
+ /** Timeout (ms) for collecting the commits produced during the run. Default: 30_000. */
441
+ readonly commitCollectionMs?: number;
442
+ /** Timeout (ms) for merging the temp branch back to the host branch (merge-to-head strategy). Default: 30_000. */
443
+ readonly mergeToHostMs?: number;
444
+ }
445
+ interface RunOptions<A extends AgentProvider = AgentProvider> {
446
+ /** Agent provider to use (e.g. claudeCode("claude-opus-4-7")) */
447
+ readonly agent: A;
448
+ /** Sandbox provider (e.g. docker({ imageName: "sandcastle:myrepo" })). */
449
+ readonly sandbox: SandboxProvider;
450
+ /**
451
+ * Host repo directory. Replaces `process.cwd()` as the anchor for
452
+ * `.sandcastle/worktrees/`, `.sandcastle/.env`, `.sandcastle/logs/`,
453
+ * `.sandcastle/patches/`, and git operations.
454
+ *
455
+ * - Relative paths are resolved against `process.cwd()`.
456
+ * - Absolute paths are used as-is.
457
+ * - Defaults to `process.cwd()` when omitted.
458
+ */
459
+ readonly cwd?: string;
460
+ /** Inline prompt string (mutually exclusive with promptFile) */
461
+ readonly prompt?: string;
462
+ /**
463
+ * Path to a prompt file (mutually exclusive with prompt).
464
+ *
465
+ * **Note:** `promptFile` is always resolved against `process.cwd()`, not
466
+ * against the `cwd` option. If you set a custom `cwd`, pass an absolute
467
+ * `promptFile` to avoid ambiguity.
468
+ */
469
+ readonly promptFile?: string;
470
+ /** Maximum iterations to run (default: 1) */
471
+ readonly maxIterations?: number;
472
+ /** Lifecycle hooks grouped by execution location (host or sandbox). */
473
+ readonly hooks?: SandboxHooks;
474
+ /** Key-value map for {{KEY}} placeholder substitution in prompts */
475
+ readonly promptArgs?: PromptArgs;
476
+ /** Logging mode (default: { type: 'file' } with auto-generated path under .sandcastle/logs/) */
477
+ readonly logging?: LoggingOption;
478
+ /** Substring(s) the agent emits to stop the iteration loop early. Matched via `includes` against agent output. (default: `"<promise>COMPLETE</promise>"`) */
479
+ readonly completionSignal?: string | string[];
480
+ /** Idle timeout in seconds. If the agent produces no output for this long, it fails. Default: 600 (10 minutes) */
481
+ readonly idleTimeoutSeconds?: number;
482
+ /**
483
+ * Grace window in seconds after a completion signal is observed in the
484
+ * agent's output. The agent process is expected to exit shortly after
485
+ * emitting the signal; if it does not (typically because a spawned child —
486
+ * a `gh`/git subprocess or long-lived MCP server — keeps stdout open),
487
+ * Sandcastle force-completes the iteration with a warning. Resets on every
488
+ * subsequent output line so trailing data (token-usage events, terminal
489
+ * `result` events, structured-output tags) is still captured. Independent
490
+ * of `idleTimeoutSeconds`. Default: 60.
491
+ */
492
+ readonly completionTimeoutSeconds?: number;
493
+ /** Optional name for the run, shown as a prefix in log output */
494
+ readonly name?: string;
495
+ /** Paths relative to the host repo root to copy into the worktree before sandbox start. */
496
+ readonly copyToWorktree?: string[];
497
+ /** Branch strategy — controls how the agent's changes relate to branches.
498
+ * Defaults to { type: "head" } for bind-mount providers and { type: "merge-to-head" } for isolated providers. */
499
+ readonly branchStrategy?: BranchStrategy;
500
+ /** Resume a prior Claude Code session by ID. The session JSONL must exist on the host. Incompatible with maxIterations > 1. */
501
+ readonly resumeSession?: string;
502
+ /**
503
+ * An `AbortSignal` that cancels the run when aborted.
504
+ *
505
+ * - If `signal.aborted` is already `true` at entry, `run()` rejects
506
+ * immediately without doing any setup work.
507
+ * - Aborting mid-iteration kills the in-flight agent subprocess.
508
+ * - Phase boundaries (between iterations) also check the signal.
509
+ * - The rejected promise surfaces `signal.reason` via
510
+ * `signal.throwIfAborted()` — no Sandcastle-specific wrapping.
511
+ * - The worktree is preserved on disk after abort (error-path behavior).
512
+ */
513
+ readonly signal?: AbortSignal;
514
+ /** Override default timeouts for built-in lifecycle steps. Unset keys keep their defaults. */
515
+ readonly timeouts?: Timeouts;
516
+ /**
517
+ * Structured output definition. When provided, the agent's stdout is
518
+ * scanned for the configured XML tag after the iteration completes, and the
519
+ * result is parsed/validated and returned on `RunResult.output`.
520
+ *
521
+ * Use `Output.object({ tag, schema })` for JSON+schema or
522
+ * `Output.string({ tag })` for raw string extraction.
523
+ *
524
+ * Constraints:
525
+ * - `maxIterations` must be `1` (the default).
526
+ * - The resolved prompt must contain the configured opening tag literal.
527
+ *
528
+ * See ADR 0010 for design rationale.
529
+ */
530
+ readonly output?: OutputDefinition;
531
+ }
532
+
533
+ type ResumeRunResultOptions = Omit<RunOptions, "agent" | "sandbox" | "prompt" | "promptFile" | "resumeSession" | "forkSession" | "maxIterations">;
534
+ interface RunResult {
535
+ /** Per-iteration results (use `iterations.length` for the count). */
536
+ readonly iterations: IterationResult[];
537
+ /** The matched completion signal string, or undefined if no signal fired before the iteration limit. */
538
+ readonly completionSignal?: string;
539
+ /** Combined stdout output from all agent iterations. */
540
+ readonly stdout: string;
541
+ /** List of commits made by the agent during the run, each identified by its SHA. */
542
+ readonly commits: {
543
+ sha: string;
544
+ }[];
545
+ /** The branch name the agent worked on inside the sandbox. */
546
+ readonly branch: string;
547
+ /** Path to the log file, if logging was drained to a file. */
548
+ readonly logFilePath?: string;
549
+ /** Host path to the preserved worktree, set when the run succeeded but the worktree had uncommitted changes. */
550
+ readonly preservedWorktreePath?: string;
551
+ /** Continue the last captured agent session for exactly one iteration.
552
+ * Present only when the provider supports resume (`sessionStorage` populated). */
553
+ readonly resume?: (prompt: string, options?: ResumeRunResultOptions) => Promise<RunResult>;
554
+ /**
555
+ * Fork the last captured agent session for exactly one iteration: the
556
+ * parent session JSONL is left intact and the child run gets its own
557
+ * session id, enabling fan-out patterns where multiple children diverge
558
+ * from a single parent. Present only when the provider supports resume
559
+ * (`sessionStorage` populated).
560
+ *
561
+ * Sessions only: fork isolates the agent session, not the branch or
562
+ * sandbox. Safe concurrent fan-out (`Promise.all([r.fork(a), r.fork(b)])`)
563
+ * requires the caller to give each fork a distinct `branch` — `head` and
564
+ * `merge-to-head` are not safe for concurrent forks. See ADR 0018.
565
+ */
566
+ readonly fork?: (prompt: string, options?: ResumeRunResultOptions) => Promise<RunResult>;
567
+ }
568
+ /** Overload: with `Output.object`, returns `RunResult` with typed `output: T`. */
569
+ declare function run<T, A extends AgentProvider>(options: RunOptions<A> & {
570
+ output: OutputObjectDefinition<T>;
571
+ }): Promise<RunResult & {
572
+ output: T;
573
+ }>;
574
+ /** Overload: with `Output.string`, returns `RunResult` with `output: string`. */
575
+ declare function run<A extends AgentProvider>(options: RunOptions<A> & {
576
+ output: OutputStringDefinition;
577
+ }): Promise<RunResult & {
578
+ output: string;
579
+ }>;
580
+ /** Overload: without `output`, returns the standard `RunResult`. */
581
+ declare function run<A extends AgentProvider>(options: RunOptions<A>): Promise<RunResult>;
582
+
583
+ interface InteractiveOptions {
584
+ /** Agent provider to use (e.g. claudeCode("claude-opus-4-7")) */
585
+ readonly agent: AgentProvider;
586
+ /** Sandbox provider (e.g. docker(), noSandbox()). */
587
+ readonly sandbox?: AnySandboxProvider;
588
+ /** Inline prompt string (mutually exclusive with promptFile). */
589
+ readonly prompt?: string;
590
+ /** Path to a prompt file (mutually exclusive with prompt). */
591
+ readonly promptFile?: string;
592
+ /** Optional name for the interactive session. */
593
+ readonly name?: string;
594
+ /** Branch strategy — controls how the agent's changes relate to branches.
595
+ * Defaults to { type: "head" } for bind-mount providers and { type: "merge-to-head" } for isolated providers. */
596
+ readonly branchStrategy?: BranchStrategy;
597
+ /** Hooks to run during sandbox lifecycle */
598
+ readonly hooks?: SandboxHooks;
599
+ /** Paths relative to the host repo root to copy into the worktree before sandbox start. */
600
+ readonly copyToWorktree?: string[];
601
+ /** Key-value map for {{KEY}} placeholder substitution in prompts */
602
+ readonly promptArgs?: PromptArgs;
603
+ /** Environment variables to inject into the sandbox. */
604
+ readonly env?: Record<string, string>;
605
+ /**
606
+ * Host repo directory to use instead of `process.cwd()`.
607
+ *
608
+ * Relative paths resolve against `process.cwd()`; absolute paths pass
609
+ * through as-is. A {@link CwdError} is thrown if the path does not exist
610
+ * or is not a directory.
611
+ */
612
+ readonly cwd?: string;
613
+ /**
614
+ * An `AbortSignal` that cancels the interactive session when aborted.
615
+ *
616
+ * - If `signal.aborted` is already `true` at entry, `interactive()` rejects
617
+ * immediately without doing any setup work.
618
+ * - Aborting during an active session kills the agent subprocess.
619
+ * - The rejected promise surfaces `signal.reason` via
620
+ * `signal.throwIfAborted()` — no Sandcastle-specific wrapping.
621
+ * - The worktree is preserved on disk after abort (error-path behavior).
622
+ */
623
+ readonly signal?: AbortSignal;
624
+ /** Override default timeouts for built-in lifecycle steps. Unset keys keep their defaults. */
625
+ readonly timeouts?: Timeouts;
626
+ }
627
+ interface InteractiveResult {
628
+ /** List of commits made during the interactive session. */
629
+ readonly commits: {
630
+ sha: string;
631
+ }[];
632
+ /** The branch name the agent worked on. */
633
+ readonly branch: string;
634
+ /** Host path to the preserved worktree, if worktree had uncommitted changes. */
635
+ readonly preservedWorktreePath?: string;
636
+ /** Exit code of the interactive process. */
637
+ readonly exitCode: number;
638
+ }
639
+ /**
640
+ * Launch an interactive agent session inside a sandbox.
641
+ *
642
+ * The user sees the agent's TUI directly. When the session ends,
643
+ * Sandcastle collects commits and handles branch merging, just like run().
644
+ *
645
+ * Full prompt preprocessing pipeline: PromptResolver -> PromptArgumentSubstitution
646
+ * -> PromptPreprocessor (shell expressions inside sandbox).
647
+ *
648
+ * All three branch strategies are supported: head, merge-to-head, branch.
649
+ */
650
+ declare const interactive: (options: InteractiveOptions) => Promise<InteractiveResult>;
651
+
652
+ interface CreateSandboxOptions {
653
+ /** Explicit branch for the worktree (required). */
654
+ readonly branch: string;
655
+ /**
656
+ * Ref to fork from when `branch` does not yet exist. Ignored when the branch
657
+ * already exists. Defaults to `HEAD`.
658
+ */
659
+ readonly baseBranch?: string;
660
+ /** Sandbox provider (e.g. docker({ imageName: "sandcastle:myrepo" })). */
661
+ readonly sandbox: SandboxProvider;
662
+ /**
663
+ * Host repo directory. Replaces `process.cwd()` as the anchor for
664
+ * `.sandcastle/worktrees/`, `.sandcastle/.env`, and git operations.
665
+ *
666
+ * - Relative paths are resolved against `process.cwd()`.
667
+ * - Absolute paths are used as-is.
668
+ * - Defaults to `process.cwd()` when omitted.
669
+ */
670
+ readonly cwd?: string;
671
+ /** Lifecycle hooks grouped by execution location (host or sandbox). */
672
+ readonly hooks?: SandboxHooks;
673
+ /** Paths relative to the host repo root to copy into the worktree at creation time. */
674
+ readonly copyToWorktree?: string[];
675
+ /** Override default timeouts for built-in lifecycle steps. Unset keys keep their defaults. */
676
+ readonly timeouts?: Timeouts;
677
+ }
678
+ interface SandboxRunOptions {
679
+ /** Agent provider to use (e.g. claudeCode("claude-opus-4-7")). */
680
+ readonly agent: AgentProvider;
681
+ /** Inline prompt string (mutually exclusive with promptFile). */
682
+ readonly prompt?: string;
683
+ /** Path to a prompt file (mutually exclusive with prompt). */
684
+ readonly promptFile?: string;
685
+ /** Key-value map for {{KEY}} placeholder substitution in prompts. */
686
+ readonly promptArgs?: PromptArgs;
687
+ /** Maximum iterations to run (default: 1). */
688
+ readonly maxIterations?: number;
689
+ /** Substring(s) the agent emits to stop the iteration loop early. */
690
+ readonly completionSignal?: string | string[];
691
+ /** Idle timeout in seconds. Default: 600. */
692
+ readonly idleTimeoutSeconds?: number;
693
+ /** Grace window in seconds after a completion signal is observed but the agent process has not exited. See ADR 0019. Default: 60. */
694
+ readonly completionTimeoutSeconds?: number;
695
+ /** Display name for this run. */
696
+ readonly name?: string;
697
+ /** Logging mode. */
698
+ readonly logging?: LoggingOption;
699
+ /**
700
+ * An `AbortSignal` that cancels the run when aborted.
701
+ *
702
+ * - Pre-aborted signal rejects immediately without setup.
703
+ * - Mid-iteration abort kills the in-flight agent subprocess.
704
+ * - The rejected promise surfaces `signal.reason` verbatim.
705
+ * - The `Sandbox` handle remains usable after abort — call `.run()` again
706
+ * with a fresh signal, or `.close()` to tear down.
707
+ */
708
+ readonly signal?: AbortSignal;
709
+ }
710
+ interface SandboxRunResult {
711
+ /** Per-iteration results (use `iterations.length` for the count). */
712
+ readonly iterations: IterationResult[];
713
+ /** The matched completion signal string, or undefined if none fired. */
714
+ readonly completionSignal?: string;
715
+ /** Combined stdout output from all agent iterations. */
716
+ readonly stdout: string;
717
+ /** List of commits made by the agent during the run. */
718
+ readonly commits: {
719
+ sha: string;
720
+ }[];
721
+ /** Path to the log file, if logging was drained to a file. */
722
+ readonly logFilePath?: string;
723
+ }
724
+ interface SandboxInteractiveOptions {
725
+ /** Agent provider to use (e.g. claudeCode("claude-opus-4-7")). */
726
+ readonly agent: AgentProvider;
727
+ /** Inline prompt string (mutually exclusive with promptFile). */
728
+ readonly prompt?: string;
729
+ /** Path to a prompt file (mutually exclusive with prompt). */
730
+ readonly promptFile?: string;
731
+ /** Key-value map for {{KEY}} placeholder substitution in prompts. */
732
+ readonly promptArgs?: PromptArgs;
733
+ /** Display name for this interactive session. */
734
+ readonly name?: string;
735
+ /**
736
+ * An `AbortSignal` that cancels the interactive session when aborted.
737
+ *
738
+ * - Pre-aborted signal rejects immediately without setup.
739
+ * - The rejected promise surfaces `signal.reason` verbatim.
740
+ * - The `Sandbox` handle remains usable after abort.
741
+ */
742
+ readonly signal?: AbortSignal;
743
+ }
744
+ interface SandboxInteractiveResult {
745
+ /** List of commits made during the interactive session. */
746
+ readonly commits: {
747
+ sha: string;
748
+ }[];
749
+ /** Exit code of the interactive process. */
750
+ readonly exitCode: number;
751
+ }
752
+ interface CloseResult {
753
+ /** Host path to the preserved worktree, set when the worktree had uncommitted changes. */
754
+ readonly preservedWorktreePath?: string;
755
+ }
756
+ interface Sandbox {
757
+ /** The branch the worktree is on. */
758
+ readonly branch: string;
759
+ /** Host path to the worktree. */
760
+ readonly worktreePath: string;
761
+ /** Invoke an agent inside the existing sandbox. */
762
+ run(options: SandboxRunOptions): Promise<SandboxRunResult>;
763
+ /** Launch an interactive agent session inside the existing sandbox. */
764
+ interactive(options: SandboxInteractiveOptions): Promise<SandboxInteractiveResult>;
765
+ /** Tear down the sandbox and worktree. */
766
+ close(): Promise<CloseResult>;
767
+ /** Auto teardown via `await using`. */
768
+ [Symbol.asyncDispose](): Promise<void>;
769
+ }
770
+ /**
771
+ * Eagerly creates a git worktree on the provided explicit branch and starts
772
+ * a sandbox with the worktree bind-mounted. Returns a Sandbox handle that
773
+ * can be reused across multiple `run()` calls.
774
+ */
775
+ declare const createSandbox: (options: CreateSandboxOptions) => Promise<Sandbox>;
776
+
777
+ /** Branch strategies valid for createWorktree — head is excluded. */
778
+ type WorktreeBranchStrategy = MergeToHeadBranchStrategy | NamedBranchStrategy;
779
+ interface CreateWorktreeOptions {
780
+ /** Branch strategy — only 'branch' and 'merge-to-head' are allowed. */
781
+ readonly branchStrategy: WorktreeBranchStrategy;
782
+ /**
783
+ * Host repo directory. Replaces `process.cwd()` as the anchor for
784
+ * `.sandcastle/worktrees/`, `.sandcastle/.env`, and git operations.
785
+ *
786
+ * - Relative paths are resolved against `process.cwd()`.
787
+ * - Absolute paths are used as-is.
788
+ * - Defaults to `process.cwd()` when omitted.
789
+ */
790
+ readonly cwd?: string;
791
+ /** Paths relative to the host repo root to copy into the worktree at creation time. */
792
+ readonly copyToWorktree?: string[];
793
+ /** Lifecycle hooks grouped by execution location (host or sandbox).
794
+ * Only `host.onWorktreeReady` is executed here — other hooks are passed through
795
+ * to `run()`, `interactive()`, or `createSandbox()`. */
796
+ readonly hooks?: SandboxHooks;
797
+ /** Override default timeouts for built-in lifecycle steps. Unset keys keep their defaults. */
798
+ readonly timeouts?: Timeouts;
799
+ }
800
+ interface WorktreeInteractiveOptions {
801
+ /** Agent provider to use (e.g. claudeCode("claude-opus-4-7")) */
802
+ readonly agent: AgentProvider;
803
+ /** Sandbox provider (e.g. docker(), noSandbox()). Defaults to noSandbox(). */
804
+ readonly sandbox?: AnySandboxProvider;
805
+ /** Inline prompt string (mutually exclusive with promptFile). */
806
+ readonly prompt?: string;
807
+ /** Path to a prompt file (mutually exclusive with prompt). */
808
+ readonly promptFile?: string;
809
+ /** Optional name for the interactive session. */
810
+ readonly name?: string;
811
+ /** Hooks to run during sandbox lifecycle */
812
+ readonly hooks?: SandboxHooks;
813
+ /** Key-value map for {{KEY}} placeholder substitution in prompts */
814
+ readonly promptArgs?: PromptArgs;
815
+ /** Environment variables to inject into the sandbox. */
816
+ readonly env?: Record<string, string>;
817
+ /**
818
+ * An `AbortSignal` that cancels the interactive session when aborted.
819
+ *
820
+ * - If `signal.aborted` is already `true` at entry, rejects immediately.
821
+ * - Aborting during an active session kills the agent subprocess.
822
+ * - The worktree is preserved on disk after abort.
823
+ * - The `Worktree` handle remains usable for subsequent operations.
824
+ * - The rejected promise surfaces `signal.reason` via
825
+ * `signal.throwIfAborted()` — no Sandcastle-specific wrapping.
826
+ */
827
+ readonly signal?: AbortSignal;
828
+ }
829
+ interface WorktreeRunOptions {
830
+ /** Agent provider to use (e.g. claudeCode("claude-opus-4-7")) */
831
+ readonly agent: AgentProvider;
832
+ /** Sandbox provider (e.g. docker()). Required — AFK agents should always be sandboxed. */
833
+ readonly sandbox: SandboxProvider;
834
+ /** Inline prompt string (mutually exclusive with promptFile). */
835
+ readonly prompt?: string;
836
+ /** Path to a prompt file (mutually exclusive with prompt). */
837
+ readonly promptFile?: string;
838
+ /** Key-value map for {{KEY}} placeholder substitution in prompts */
839
+ readonly promptArgs?: PromptArgs;
840
+ /** Maximum iterations to run (default: 1). */
841
+ readonly maxIterations?: number;
842
+ /** Substring(s) the agent emits to stop the iteration loop early. */
843
+ readonly completionSignal?: string | string[];
844
+ /** Idle timeout in seconds. Default: 600. */
845
+ readonly idleTimeoutSeconds?: number;
846
+ /** Grace window in seconds after a completion signal is observed but the agent process has not exited. See ADR 0019. Default: 60. */
847
+ readonly completionTimeoutSeconds?: number;
848
+ /** Optional name for the run. */
849
+ readonly name?: string;
850
+ /** Logging mode. */
851
+ readonly logging?: LoggingOption;
852
+ /** Hooks to run during sandbox lifecycle */
853
+ readonly hooks?: SandboxHooks;
854
+ /** Environment variables to inject into the sandbox. */
855
+ readonly env?: Record<string, string>;
856
+ /** Resume a prior Claude Code session by ID. The session JSONL must exist on the host. Incompatible with maxIterations > 1. */
857
+ readonly resumeSession?: string;
858
+ /**
859
+ * An `AbortSignal` that cancels the run when aborted.
860
+ *
861
+ * - If `signal.aborted` is already `true` at entry, rejects immediately
862
+ * without doing any setup work.
863
+ * - Aborting mid-iteration kills the in-flight agent subprocess.
864
+ * - The worktree is preserved on disk after abort.
865
+ * - The `Worktree` handle remains usable for subsequent operations.
866
+ */
867
+ readonly signal?: AbortSignal;
868
+ }
869
+ interface WorktreeRunResult {
870
+ /** Per-iteration results (use `iterations.length` for the count). */
871
+ readonly iterations: IterationResult[];
872
+ /** The matched completion signal string, or undefined if none fired. */
873
+ readonly completionSignal?: string;
874
+ /** Combined stdout output from all agent iterations. */
875
+ readonly stdout: string;
876
+ /** List of commits made by the agent during the run. */
877
+ readonly commits: {
878
+ sha: string;
879
+ }[];
880
+ /** The branch name the agent worked on. */
881
+ readonly branch: string;
882
+ /** Path to the log file, if logging was drained to a file. */
883
+ readonly logFilePath?: string;
884
+ }
885
+ interface WorktreeCreateSandboxOptions {
886
+ /** Sandbox provider (e.g. docker({ imageName: "sandcastle:myrepo" })). */
887
+ readonly sandbox: SandboxProvider;
888
+ /** Lifecycle hooks grouped by execution location (host or sandbox). */
889
+ readonly hooks?: SandboxHooks;
890
+ /** Paths relative to the host repo root to copy into the worktree at creation time. */
891
+ readonly copyToWorktree?: string[];
892
+ /** Override default timeouts for built-in lifecycle steps. Unset keys keep their defaults. */
893
+ readonly timeouts?: Timeouts;
894
+ }
895
+ interface Worktree {
896
+ /** The branch the worktree is on. */
897
+ readonly branch: string;
898
+ /** Host path to the worktree (worktree). */
899
+ readonly worktreePath: string;
900
+ /** Run an AFK agent in this worktree with a required sandbox. */
901
+ run(options: WorktreeRunOptions): Promise<WorktreeRunResult>;
902
+ /** Run an interactive agent session in this worktree. */
903
+ interactive(options: WorktreeInteractiveOptions): Promise<InteractiveResult>;
904
+ /** Create a long-lived sandbox backed by this worktree's worktree. */
905
+ createSandbox(options: WorktreeCreateSandboxOptions): Promise<Sandbox>;
906
+ /** Clean up the worktree. Preserves worktree if dirty. */
907
+ close(): Promise<CloseResult>;
908
+ /** Auto cleanup via `await using`. */
909
+ [Symbol.asyncDispose](): Promise<void>;
910
+ }
911
+ /**
912
+ * Creates a git worktree as an independent, first-class worktree.
913
+ * Returns a Worktree handle with close() and [Symbol.asyncDispose]().
914
+ *
915
+ * Only accepts 'branch' and 'merge-to-head' strategies — 'head' is a
916
+ * compile-time type error since head means no worktree.
917
+ */
918
+ declare const createWorktree: (options: CreateWorktreeOptions) => Promise<Worktree>;
919
+
920
+ interface CwdErrorConstructor {
921
+ new (args: {
922
+ readonly message: string;
923
+ readonly cwd: string;
924
+ }): CwdError;
925
+ readonly prototype: CwdError;
926
+ }
927
+ /**
928
+ * The provided `cwd` path does not exist or is not a directory.
929
+ *
930
+ * Public-facing type for `CwdError`. The runtime class is the same
931
+ * `Data.TaggedError` from `resolveCwd.ts`, but we re-declare its public
932
+ * shape here as a plain `Error` subclass so that Effect's type machinery
933
+ * does not leak into Sandcastle's published `.d.ts` files.
934
+ */
935
+ interface CwdError extends Error {
936
+ readonly _tag: "CwdError";
937
+ readonly message: string;
938
+ readonly cwd: string;
939
+ }
940
+ /** The provided `cwd` path does not exist or is not a directory. */
941
+ declare const CwdError: CwdErrorConstructor;
942
+
943
+ export { AGENT_DEFAULT_MODELS, type AgentCommandOptions, type AgentName, type AgentProvider, type AgentResolverOptions, type AgentStreamEvent, AnySandboxProvider, BindMountSandboxHandle, BranchStrategy, type ClaudeCodeOptions, type CloseResult, type CodexOptions, type CopilotOptions, type CreateSandboxOptions, type CreateWorktreeOptions, type CursorOptions, CwdError, type HostSessionLookup, type InteractiveOptions, type InteractiveResult, type IterationResult, type IterationUsage, type LoggingOption, MergeToHeadBranchStrategy, NamedBranchStrategy, type OpenCodeOptions, Output, type OutputDefinition, type OutputObjectDefinition, type OutputStringDefinition, type PiOptions, type PrintCommand, type PromptArgs, type RunOptions, type RunResult, type Sandbox, type SandboxHooks, type SandboxInteractiveOptions, type SandboxInteractiveResult, SandboxProvider, type SandboxRunOptions, type SandboxRunResult, StructuredOutputError, type Timeouts, type Worktree, type WorktreeBranchStrategy, type WorktreeCreateSandboxOptions, type WorktreeInteractiveOptions, type WorktreeRunOptions, type WorktreeRunResult, agent, claudeCode, claudeHostSessionPath, claudeSandboxSessionPath, codex, copilot, createSandbox, createWorktree, cursor, encodeProjectPath, findClaudeSessionOnHost, findCodexSessionOnHost, interactive, opencode, pi, run, transferClaudeSession, transferCodexSession };