@ai-hero/sandcastle 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -30
- package/dist/AgentProvider.d.ts +28 -4
- package/dist/AgentProvider.d.ts.map +1 -1
- package/dist/AgentProvider.js +193 -49
- package/dist/AgentProvider.js.map +1 -1
- package/dist/InitService.d.ts +16 -3
- package/dist/InitService.d.ts.map +1 -1
- package/dist/InitService.js +166 -19
- package/dist/InitService.js.map +1 -1
- package/dist/Orchestrator.d.ts +7 -34
- package/dist/Orchestrator.d.ts.map +1 -1
- package/dist/Orchestrator.js +32 -104
- package/dist/Orchestrator.js.map +1 -1
- package/dist/SandboxFactory.d.ts +8 -4
- package/dist/SandboxFactory.d.ts.map +1 -1
- package/dist/SandboxFactory.js +65 -26
- package/dist/SandboxFactory.js.map +1 -1
- package/dist/WorktreeManager.d.ts +5 -5
- package/dist/WorktreeManager.d.ts.map +1 -1
- package/dist/WorktreeManager.js +8 -8
- package/dist/WorktreeManager.js.map +1 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +75 -27
- package/dist/cli.js.map +1 -1
- package/dist/createSandbox.d.ts +82 -0
- package/dist/createSandbox.d.ts.map +1 -0
- package/dist/createSandbox.js +192 -0
- package/dist/createSandbox.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/run.d.ts +20 -6
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +36 -31
- package/dist/run.js.map +1 -1
- package/dist/templates/blank/.env.example +4 -0
- package/dist/templates/blank/main.ts +2 -1
- package/dist/templates/parallel-planner/.env.example +4 -0
- package/dist/templates/parallel-planner/main.ts +4 -4
- package/dist/templates/sequential-reviewer/.env.example +4 -0
- package/dist/templates/sequential-reviewer/main.ts +3 -3
- package/dist/templates/simple-loop/.env.example +4 -0
- package/dist/templates/simple-loop/main.ts +6 -5
- package/package.json +1 -1
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Layer } from "effect";
|
|
2
|
+
import type { AgentProvider } from "./AgentProvider.js";
|
|
3
|
+
import { type PromptArgs } from "./PromptArgumentSubstitution.js";
|
|
4
|
+
import type { LoggingOption } from "./run.js";
|
|
5
|
+
import { Sandbox as SandboxTag } from "./SandboxFactory.js";
|
|
6
|
+
export interface CreateSandboxOptions {
|
|
7
|
+
/** Explicit branch for the worktree (required). */
|
|
8
|
+
readonly branch: string;
|
|
9
|
+
/** Docker image name to use for the sandbox (default: sandcastle:<repo-dir-name>). */
|
|
10
|
+
readonly imageName?: string;
|
|
11
|
+
/** One-time setup hooks to run when the sandbox is first created. */
|
|
12
|
+
readonly hooks?: {
|
|
13
|
+
readonly onSandboxReady?: ReadonlyArray<{
|
|
14
|
+
command: string;
|
|
15
|
+
}>;
|
|
16
|
+
};
|
|
17
|
+
/** Paths relative to the host repo root to copy into the worktree at creation time. */
|
|
18
|
+
readonly copyToSandbox?: string[];
|
|
19
|
+
/** @internal Test-only overrides to bypass Docker. */
|
|
20
|
+
readonly _test?: {
|
|
21
|
+
readonly hostRepoDir?: string;
|
|
22
|
+
readonly buildSandboxLayer?: (sandboxDir: string) => Layer.Layer<SandboxTag>;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export interface SandboxRunOptions {
|
|
26
|
+
/** Agent provider to use (e.g. claudeCode("claude-opus-4-6")). */
|
|
27
|
+
readonly agent: AgentProvider;
|
|
28
|
+
/** Inline prompt string (mutually exclusive with promptFile). */
|
|
29
|
+
readonly prompt?: string;
|
|
30
|
+
/** Path to a prompt file (mutually exclusive with prompt). */
|
|
31
|
+
readonly promptFile?: string;
|
|
32
|
+
/** Key-value map for {{KEY}} placeholder substitution in prompts. */
|
|
33
|
+
readonly promptArgs?: PromptArgs;
|
|
34
|
+
/** Maximum iterations to run (default: 1). */
|
|
35
|
+
readonly maxIterations?: number;
|
|
36
|
+
/** Substring(s) the agent emits to stop the iteration loop early. */
|
|
37
|
+
readonly completionSignal?: string | string[];
|
|
38
|
+
/** Idle timeout in seconds. Default: 600. */
|
|
39
|
+
readonly idleTimeoutSeconds?: number;
|
|
40
|
+
/** Display name for this run. */
|
|
41
|
+
readonly name?: string;
|
|
42
|
+
/** Logging mode. */
|
|
43
|
+
readonly logging?: LoggingOption;
|
|
44
|
+
}
|
|
45
|
+
export interface SandboxRunResult {
|
|
46
|
+
/** Number of iterations the agent completed during this run. */
|
|
47
|
+
readonly iterationsRun: number;
|
|
48
|
+
/** The matched completion signal string, or undefined if none fired. */
|
|
49
|
+
readonly completionSignal?: string;
|
|
50
|
+
/** Combined stdout output from all agent iterations. */
|
|
51
|
+
readonly stdout: string;
|
|
52
|
+
/** List of commits made by the agent during the run. */
|
|
53
|
+
readonly commits: {
|
|
54
|
+
sha: string;
|
|
55
|
+
}[];
|
|
56
|
+
/** Path to the log file, if logging was drained to a file. */
|
|
57
|
+
readonly logFilePath?: string;
|
|
58
|
+
}
|
|
59
|
+
export interface CloseResult {
|
|
60
|
+
/** Host path to the preserved worktree, set when the worktree had uncommitted changes. */
|
|
61
|
+
readonly preservedWorktreePath?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface Sandbox {
|
|
64
|
+
/** The branch the worktree is on. */
|
|
65
|
+
readonly branch: string;
|
|
66
|
+
/** Host path to the worktree. */
|
|
67
|
+
readonly worktreePath: string;
|
|
68
|
+
/** Invoke an agent inside the existing sandbox. */
|
|
69
|
+
run(options: SandboxRunOptions): Promise<SandboxRunResult>;
|
|
70
|
+
/** Tear down the container and worktree. */
|
|
71
|
+
close(): Promise<CloseResult>;
|
|
72
|
+
/** Auto teardown via `await using`. */
|
|
73
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Eagerly creates a git worktree on the provided explicit branch and starts
|
|
77
|
+
* a Docker container (or local sandbox in test mode) with the worktree
|
|
78
|
+
* bind-mounted. Returns a Sandbox handle that can be reused across multiple
|
|
79
|
+
* `run()` calls.
|
|
80
|
+
*/
|
|
81
|
+
export declare const createSandbox: (options: CreateSandboxOptions) => Promise<Sandbox>;
|
|
82
|
+
//# sourceMappingURL=createSandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSandbox.d.ts","sourceRoot":"","sources":["../src/createSandbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { NodeContext, NodeFileSystem } from "@effect/platform-node";
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { Effect, Layer, Ref } from "effect";
|
|
6
|
+
import { Display, FileDisplay, SilentDisplay, } from "./Display.js";
|
|
7
|
+
import { startContainer, removeContainer, chownInContainer, } from "./DockerLifecycle.js";
|
|
8
|
+
import { resolveEnv } from "./EnvResolver.js";
|
|
9
|
+
import { orchestrate } from "./Orchestrator.js";
|
|
10
|
+
import { substitutePromptArgs, validateNoBuiltInArgOverride, BUILT_IN_PROMPT_ARG_KEYS, } from "./PromptArgumentSubstitution.js";
|
|
11
|
+
import { resolvePrompt } from "./PromptResolver.js";
|
|
12
|
+
import { buildLogFilename, defaultImageName, printFileDisplayStartup, } from "./run.js";
|
|
13
|
+
import { Sandbox as SandboxTag, SandboxFactory, SANDBOX_WORKSPACE_DIR, makeDockerSandboxLayer, } from "./SandboxFactory.js";
|
|
14
|
+
import * as WorktreeManager from "./WorktreeManager.js";
|
|
15
|
+
import { copyToSandbox } from "./CopyToSandbox.js";
|
|
16
|
+
/**
|
|
17
|
+
* Eagerly creates a git worktree on the provided explicit branch and starts
|
|
18
|
+
* a Docker container (or local sandbox in test mode) with the worktree
|
|
19
|
+
* bind-mounted. Returns a Sandbox handle that can be reused across multiple
|
|
20
|
+
* `run()` calls.
|
|
21
|
+
*/
|
|
22
|
+
export const createSandbox = async (options) => {
|
|
23
|
+
const hostRepoDir = options._test?.hostRepoDir ?? process.cwd();
|
|
24
|
+
const { branch } = options;
|
|
25
|
+
const isTestMode = !!options._test?.buildSandboxLayer;
|
|
26
|
+
// 1. Prune stale worktrees + create worktree on the explicit branch
|
|
27
|
+
const worktreeInfo = await Effect.runPromise(WorktreeManager.pruneStale(hostRepoDir)
|
|
28
|
+
.pipe(Effect.catchAll(() => Effect.void))
|
|
29
|
+
.pipe(Effect.andThen(WorktreeManager.create(hostRepoDir, { branch })))
|
|
30
|
+
.pipe(Effect.provide(NodeContext.layer)));
|
|
31
|
+
const worktreePath = worktreeInfo.path;
|
|
32
|
+
// 2. Copy files if requested
|
|
33
|
+
if (options.copyToSandbox && options.copyToSandbox.length > 0) {
|
|
34
|
+
await Effect.runPromise(copyToSandbox(options.copyToSandbox, hostRepoDir, worktreePath));
|
|
35
|
+
}
|
|
36
|
+
// 3. Start container (Docker mode) or create local sandbox layer (test mode)
|
|
37
|
+
let containerName;
|
|
38
|
+
let sandboxLayer;
|
|
39
|
+
let sandboxRepoDir;
|
|
40
|
+
if (isTestMode) {
|
|
41
|
+
sandboxLayer = options._test.buildSandboxLayer(worktreePath);
|
|
42
|
+
sandboxRepoDir = worktreePath;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
containerName = `sandcastle-${randomUUID()}`;
|
|
46
|
+
const resolvedImageName = options.imageName ?? defaultImageName(hostRepoDir);
|
|
47
|
+
const env = await Effect.runPromise(resolveEnv(hostRepoDir).pipe(Effect.provide(NodeContext.layer)));
|
|
48
|
+
const gitDir = join(hostRepoDir, ".git");
|
|
49
|
+
const volumeMounts = [
|
|
50
|
+
`${worktreePath}:${SANDBOX_WORKSPACE_DIR}`,
|
|
51
|
+
`${gitDir}:${gitDir}`,
|
|
52
|
+
];
|
|
53
|
+
const hostUid = process.getuid?.() ?? 1000;
|
|
54
|
+
const hostGid = process.getgid?.() ?? 1000;
|
|
55
|
+
await Effect.runPromise(startContainer(containerName, resolvedImageName, { ...env, HOME: "/home/agent" }, {
|
|
56
|
+
volumeMounts,
|
|
57
|
+
workdir: SANDBOX_WORKSPACE_DIR,
|
|
58
|
+
user: `${hostUid}:${hostGid}`,
|
|
59
|
+
}).pipe(Effect.andThen(chownInContainer(containerName, `${hostUid}:${hostGid}`, "/home/agent"))));
|
|
60
|
+
sandboxLayer = makeDockerSandboxLayer(containerName);
|
|
61
|
+
sandboxRepoDir = SANDBOX_WORKSPACE_DIR;
|
|
62
|
+
}
|
|
63
|
+
// 4. Run onSandboxReady hooks
|
|
64
|
+
if (options.hooks?.onSandboxReady?.length) {
|
|
65
|
+
await Effect.runPromise(Effect.gen(function* () {
|
|
66
|
+
const sandbox = yield* SandboxTag;
|
|
67
|
+
yield* sandbox.exec(`git config --global --add safe.directory "${sandboxRepoDir}"`);
|
|
68
|
+
for (const hook of options.hooks.onSandboxReady) {
|
|
69
|
+
yield* sandbox.exec(hook.command, { cwd: sandboxRepoDir });
|
|
70
|
+
}
|
|
71
|
+
}).pipe(Effect.provide(sandboxLayer)));
|
|
72
|
+
}
|
|
73
|
+
// 5. Set up signal handlers
|
|
74
|
+
let closed = false;
|
|
75
|
+
const forceCleanup = () => {
|
|
76
|
+
if (containerName) {
|
|
77
|
+
try {
|
|
78
|
+
execFileSync("docker", ["rm", "-f", containerName], {
|
|
79
|
+
stdio: "ignore",
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
catch { }
|
|
83
|
+
}
|
|
84
|
+
console.error(`\nWorktree preserved at ${worktreePath}`);
|
|
85
|
+
console.error(` To review: cd ${worktreePath}`);
|
|
86
|
+
console.error(` To clean up: git worktree remove --force ${worktreePath}`);
|
|
87
|
+
};
|
|
88
|
+
const onSignal = () => {
|
|
89
|
+
forceCleanup();
|
|
90
|
+
process.exit(1);
|
|
91
|
+
};
|
|
92
|
+
process.on("SIGINT", onSignal);
|
|
93
|
+
process.on("SIGTERM", onSignal);
|
|
94
|
+
// 6. Build close function
|
|
95
|
+
const doClose = async () => {
|
|
96
|
+
if (closed)
|
|
97
|
+
return { preservedWorktreePath: undefined };
|
|
98
|
+
closed = true;
|
|
99
|
+
// Remove container
|
|
100
|
+
if (containerName) {
|
|
101
|
+
await Effect.runPromise(removeContainer(containerName).pipe(Effect.orDie));
|
|
102
|
+
}
|
|
103
|
+
// Check for uncommitted changes
|
|
104
|
+
const isDirty = await Effect.runPromise(WorktreeManager.hasUncommittedChanges(worktreePath).pipe(Effect.catchAll(() => Effect.succeed(false))));
|
|
105
|
+
if (isDirty) {
|
|
106
|
+
return { preservedWorktreePath: worktreePath };
|
|
107
|
+
}
|
|
108
|
+
// Remove worktree
|
|
109
|
+
await Effect.runPromise(WorktreeManager.remove(worktreePath).pipe(Effect.catchAll(() => Effect.void)));
|
|
110
|
+
return { preservedWorktreePath: undefined };
|
|
111
|
+
};
|
|
112
|
+
// 7. Return the Sandbox handle
|
|
113
|
+
const sandboxHandle = {
|
|
114
|
+
branch,
|
|
115
|
+
worktreePath,
|
|
116
|
+
run: async (runOptions) => {
|
|
117
|
+
const { agent: provider, prompt, promptFile, maxIterations = 1, } = runOptions;
|
|
118
|
+
// Resolve prompt
|
|
119
|
+
const rawPrompt = await Effect.runPromise(resolvePrompt({ prompt, promptFile }).pipe(Effect.provide(NodeContext.layer)));
|
|
120
|
+
// Resolve prompt arguments
|
|
121
|
+
const userArgs = runOptions.promptArgs ?? {};
|
|
122
|
+
const currentHostBranch = await Effect.runPromise(WorktreeManager.getCurrentBranch(hostRepoDir));
|
|
123
|
+
const displayRef = Ref.unsafeMake([]);
|
|
124
|
+
const silentDisplayLayer = SilentDisplay.layer(displayRef);
|
|
125
|
+
const resolvedPrompt = await Effect.runPromise(Effect.gen(function* () {
|
|
126
|
+
yield* validateNoBuiltInArgOverride(userArgs);
|
|
127
|
+
const effectiveArgs = {
|
|
128
|
+
SOURCE_BRANCH: branch,
|
|
129
|
+
TARGET_BRANCH: currentHostBranch,
|
|
130
|
+
...userArgs,
|
|
131
|
+
};
|
|
132
|
+
const builtInArgKeysSet = new Set(BUILT_IN_PROMPT_ARG_KEYS);
|
|
133
|
+
return yield* substitutePromptArgs(rawPrompt, effectiveArgs, builtInArgKeysSet);
|
|
134
|
+
}).pipe(Effect.provide(silentDisplayLayer)));
|
|
135
|
+
// Resolve logging
|
|
136
|
+
const resolvedLogging = runOptions.logging ?? {
|
|
137
|
+
type: "file",
|
|
138
|
+
path: join(hostRepoDir, ".sandcastle", "logs", buildLogFilename(branch, undefined, runOptions.name)),
|
|
139
|
+
};
|
|
140
|
+
const runDisplayLayer = resolvedLogging.type === "file"
|
|
141
|
+
? (() => {
|
|
142
|
+
printFileDisplayStartup({
|
|
143
|
+
logPath: resolvedLogging.path,
|
|
144
|
+
agentName: runOptions.name,
|
|
145
|
+
branch,
|
|
146
|
+
});
|
|
147
|
+
return Layer.provide(FileDisplay.layer(resolvedLogging.path), NodeFileSystem.layer);
|
|
148
|
+
})()
|
|
149
|
+
: silentDisplayLayer;
|
|
150
|
+
// Build a SandboxFactory that reuses the existing container/sandbox
|
|
151
|
+
const reuseFactoryLayer = Layer.succeed(SandboxFactory, {
|
|
152
|
+
withSandbox: (makeEffect) => makeEffect({ hostWorktreePath: worktreePath }).pipe(Effect.provide(sandboxLayer), Effect.map((value) => ({
|
|
153
|
+
value,
|
|
154
|
+
preservedWorktreePath: undefined,
|
|
155
|
+
}))),
|
|
156
|
+
});
|
|
157
|
+
const runLayer = Layer.merge(reuseFactoryLayer, runDisplayLayer);
|
|
158
|
+
const result = await Effect.runPromise(Effect.gen(function* () {
|
|
159
|
+
const display = yield* Display;
|
|
160
|
+
yield* display.intro(runOptions.name ?? "sandcastle");
|
|
161
|
+
return yield* orchestrate({
|
|
162
|
+
hostRepoDir,
|
|
163
|
+
sandboxRepoDir,
|
|
164
|
+
iterations: maxIterations,
|
|
165
|
+
prompt: resolvedPrompt,
|
|
166
|
+
branch,
|
|
167
|
+
provider,
|
|
168
|
+
completionSignal: runOptions.completionSignal,
|
|
169
|
+
idleTimeoutSeconds: runOptions.idleTimeoutSeconds,
|
|
170
|
+
name: runOptions.name,
|
|
171
|
+
});
|
|
172
|
+
}).pipe(Effect.provide(runLayer)));
|
|
173
|
+
return {
|
|
174
|
+
iterationsRun: result.iterationsRun,
|
|
175
|
+
completionSignal: result.completionSignal,
|
|
176
|
+
stdout: result.stdout,
|
|
177
|
+
commits: result.commits,
|
|
178
|
+
logFilePath: resolvedLogging.type === "file" ? resolvedLogging.path : undefined,
|
|
179
|
+
};
|
|
180
|
+
},
|
|
181
|
+
close: async () => {
|
|
182
|
+
process.removeListener("SIGINT", onSignal);
|
|
183
|
+
process.removeListener("SIGTERM", onSignal);
|
|
184
|
+
return doClose();
|
|
185
|
+
},
|
|
186
|
+
[Symbol.asyncDispose]: async () => {
|
|
187
|
+
await sandboxHandle.close();
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
return sandboxHandle;
|
|
191
|
+
};
|
|
192
|
+
//# sourceMappingURL=createSandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSandbox.js","sourceRoot":"","sources":["../src/createSandbox.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export { run } from "./run.js";
|
|
2
|
-
export type { RunOptions, RunResult, LoggingOption } from "./run.js";
|
|
2
|
+
export type { RunOptions, RunResult, LoggingOption, WorktreeMode, } from "./run.js";
|
|
3
|
+
export { createSandbox } from "./createSandbox.js";
|
|
4
|
+
export type { CreateSandboxOptions, Sandbox, SandboxRunOptions, SandboxRunResult, CloseResult, } from "./createSandbox.js";
|
|
3
5
|
export type { PromptArgs } from "./PromptArgumentSubstitution.js";
|
|
6
|
+
export { claudeCode, codex, pi } from "./AgentProvider.js";
|
|
7
|
+
export type { AgentProvider } from "./AgentProvider.js";
|
|
4
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,YAAY,EACV,UAAU,EACV,SAAS,EACT,aAAa,EACb,YAAY,GACb,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EACV,oBAAoB,EACpB,OAAO,EACP,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAC3D,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAO/B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AASnD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/run.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AgentProvider } from "./AgentProvider.js";
|
|
1
2
|
import { type Severity } from "./Display.js";
|
|
2
3
|
import { type PromptArgs } from "./PromptArgumentSubstitution.js";
|
|
3
4
|
/** Default maximum number of iterations for a run. */
|
|
@@ -35,7 +36,6 @@ export interface RunSummaryRowsOptions {
|
|
|
35
36
|
readonly imageName: string;
|
|
36
37
|
readonly maxIterations: number;
|
|
37
38
|
readonly branch: string;
|
|
38
|
-
readonly model?: string;
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
41
|
* Build the summary rows for a run, used in both terminal mode and
|
|
@@ -66,7 +66,23 @@ export type LoggingOption =
|
|
|
66
66
|
| {
|
|
67
67
|
readonly type: "stdout";
|
|
68
68
|
};
|
|
69
|
+
/**
|
|
70
|
+
* Worktree mode discriminated union.
|
|
71
|
+
* - `none`: bind-mounts host working directory directly; no worktree, no merge step.
|
|
72
|
+
* - `temp-branch`: creates a temporary worktree/branch, merges back, deletes the temp branch (default).
|
|
73
|
+
* - `branch`: creates a worktree on an explicit branch; commits stay on that branch.
|
|
74
|
+
*/
|
|
75
|
+
export type WorktreeMode = {
|
|
76
|
+
readonly mode: "none";
|
|
77
|
+
} | {
|
|
78
|
+
readonly mode: "temp-branch";
|
|
79
|
+
} | {
|
|
80
|
+
readonly mode: "branch";
|
|
81
|
+
readonly branch: string;
|
|
82
|
+
};
|
|
69
83
|
export interface RunOptions {
|
|
84
|
+
/** Agent provider to use (e.g. claudeCode("claude-opus-4-6")) */
|
|
85
|
+
readonly agent: AgentProvider;
|
|
70
86
|
/** Inline prompt string (mutually exclusive with promptFile) */
|
|
71
87
|
readonly prompt?: string;
|
|
72
88
|
/** Path to a prompt file (mutually exclusive with prompt) */
|
|
@@ -79,10 +95,8 @@ export interface RunOptions {
|
|
|
79
95
|
command: string;
|
|
80
96
|
}>;
|
|
81
97
|
};
|
|
82
|
-
/**
|
|
83
|
-
readonly
|
|
84
|
-
/** Model to use for the agent (default: claude-opus-4-6) */
|
|
85
|
-
readonly model?: string;
|
|
98
|
+
/** Worktree mode for sandbox work. Defaults to `{ mode: 'temp-branch' }` when omitted. */
|
|
99
|
+
readonly worktree?: WorktreeMode;
|
|
86
100
|
/** Docker image name to use for the sandbox (default: sandcastle:<repo-dir-name>) */
|
|
87
101
|
readonly imageName?: string;
|
|
88
102
|
/** Key-value map for {{KEY}} placeholder substitution in prompts */
|
|
@@ -91,7 +105,7 @@ export interface RunOptions {
|
|
|
91
105
|
readonly logging?: LoggingOption;
|
|
92
106
|
/** Substring(s) the agent emits to stop the iteration loop early. Matched via `includes` against agent output. (default: `"<promise>COMPLETE</promise>"`) */
|
|
93
107
|
readonly completionSignal?: string | string[];
|
|
94
|
-
/** Idle timeout in seconds. If the agent produces no output for this long, it fails. Default:
|
|
108
|
+
/** Idle timeout in seconds. If the agent produces no output for this long, it fails. Default: 600 (10 minutes) */
|
|
95
109
|
readonly idleTimeoutSeconds?: number;
|
|
96
110
|
/** Optional name for the run, shown as a prefix in log output */
|
|
97
111
|
readonly name?: string;
|
package/dist/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
|
package/dist/run.js
CHANGED
|
@@ -2,7 +2,6 @@ import { NodeContext, NodeFileSystem } from "@effect/platform-node";
|
|
|
2
2
|
import path, { join } from "node:path";
|
|
3
3
|
import { styleText } from "node:util";
|
|
4
4
|
import { Effect, Layer } from "effect";
|
|
5
|
-
import { getAgentProvider } from "./AgentProvider.js";
|
|
6
5
|
import { ClackDisplay, Display, FileDisplay, } from "./Display.js";
|
|
7
6
|
import { orchestrate } from "./Orchestrator.js";
|
|
8
7
|
import { resolvePrompt } from "./PromptResolver.js";
|
|
@@ -59,17 +58,12 @@ export const buildLogFilename = (resolvedBranch, targetBranch, name) => {
|
|
|
59
58
|
* log-to-file mode. When a custom name is provided it appears as the
|
|
60
59
|
* Agent value instead of the internal provider name.
|
|
61
60
|
*/
|
|
62
|
-
export const buildRunSummaryRows = (options) => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
};
|
|
69
|
-
if (options.model)
|
|
70
|
-
rows["Model"] = options.model;
|
|
71
|
-
return rows;
|
|
72
|
-
};
|
|
61
|
+
export const buildRunSummaryRows = (options) => ({
|
|
62
|
+
Agent: options.name ?? options.agentName,
|
|
63
|
+
Image: options.imageName,
|
|
64
|
+
"Max iterations": String(options.maxIterations),
|
|
65
|
+
Branch: options.branch,
|
|
66
|
+
});
|
|
73
67
|
/**
|
|
74
68
|
* Build the completion status message for a run, used in both terminal mode
|
|
75
69
|
* and log-to-file mode to record the final outcome.
|
|
@@ -87,29 +81,39 @@ export const buildCompletionMessage = (completionSignal, iterationsRun) => {
|
|
|
87
81
|
};
|
|
88
82
|
};
|
|
89
83
|
export const run = async (options) => {
|
|
90
|
-
const { prompt, promptFile, maxIterations = DEFAULT_MAX_ITERATIONS, hooks,
|
|
84
|
+
const { prompt, promptFile, maxIterations = DEFAULT_MAX_ITERATIONS, hooks, agent: provider, } = options;
|
|
85
|
+
// Resolve worktree mode: default to temp-branch when omitted
|
|
86
|
+
const worktreeMode = options.worktree ?? {
|
|
87
|
+
mode: "temp-branch",
|
|
88
|
+
};
|
|
89
|
+
// Validate: copyToSandbox is incompatible with mode: 'none'
|
|
90
|
+
if (worktreeMode.mode === "none" &&
|
|
91
|
+
options.copyToSandbox &&
|
|
92
|
+
options.copyToSandbox.length > 0) {
|
|
93
|
+
throw new Error("copyToSandbox is not supported with worktree mode 'none'. " +
|
|
94
|
+
"In mode 'none' the host working directory is bind-mounted directly.");
|
|
95
|
+
}
|
|
96
|
+
// Extract explicit branch when in branch mode, undefined for temp-branch/none mode
|
|
97
|
+
const branch = worktreeMode.mode === "branch" ? worktreeMode.branch : undefined;
|
|
91
98
|
const hostRepoDir = process.cwd();
|
|
92
99
|
// Resolve prompt
|
|
93
100
|
const rawPrompt = await Effect.runPromise(resolvePrompt({ prompt, promptFile }).pipe(Effect.provide(NodeContext.layer)));
|
|
94
|
-
|
|
95
|
-
const resolvedModel = model;
|
|
96
|
-
// Agent is hardcoded to claude-code (agent selection is not part of the public API)
|
|
97
|
-
const agentName = "claude-code";
|
|
98
|
-
const provider = getAgentProvider(agentName);
|
|
101
|
+
const agentName = provider.name;
|
|
99
102
|
// Resolve image name: explicit option > default
|
|
100
103
|
const resolvedImageName = options.imageName ?? defaultImageName(hostRepoDir);
|
|
101
104
|
// Resolve env vars
|
|
102
105
|
const env = await Effect.runPromise(resolveEnv(hostRepoDir).pipe(Effect.provide(NodeContext.layer)));
|
|
103
|
-
// When no branch is provided, generate a temporary branch name.
|
|
104
|
-
// This names the log file after the temp branch and also directs
|
|
105
|
-
// the sandbox to work on that branch (instead of the current host branch).
|
|
106
|
-
const resolvedBranch = branch ?? generateTempBranchName(agentName);
|
|
107
106
|
// Always capture the host's current branch for the TARGET_BRANCH built-in
|
|
108
107
|
// prompt argument. When using a temp branch, it also prefixes the log filename.
|
|
109
108
|
const currentHostBranch = await Effect.runPromise(getCurrentBranch(hostRepoDir));
|
|
109
|
+
// When in temp-branch mode, generate a temporary branch name.
|
|
110
|
+
// In none mode, use the host's current branch directly (no worktree).
|
|
111
|
+
const resolvedBranch = worktreeMode.mode === "none"
|
|
112
|
+
? currentHostBranch
|
|
113
|
+
: (branch ?? generateTempBranchName(options.name));
|
|
110
114
|
// When using a temp branch, prefix the log filename with the target branch
|
|
111
115
|
// (the host's current branch) so developers can tell which branch was targeted.
|
|
112
|
-
const targetBranch =
|
|
116
|
+
const targetBranch = worktreeMode.mode === "temp-branch" ? currentHostBranch : undefined;
|
|
113
117
|
// Resolve logging option
|
|
114
118
|
const resolvedLogging = options.logging ?? {
|
|
115
119
|
type: "file",
|
|
@@ -129,11 +133,9 @@ export const run = async (options) => {
|
|
|
129
133
|
imageName: resolvedImageName,
|
|
130
134
|
env,
|
|
131
135
|
hostRepoDir,
|
|
132
|
-
|
|
133
|
-
// and SandboxLifecycle cherry-picks commits onto the host's current branch
|
|
134
|
-
branch,
|
|
136
|
+
worktree: worktreeMode,
|
|
135
137
|
copyToSandbox: options.copyToSandbox,
|
|
136
|
-
|
|
138
|
+
name: options.name,
|
|
137
139
|
}), NodeFileSystem.layer, displayLayer));
|
|
138
140
|
const runLayer = Layer.merge(factoryLayer, displayLayer);
|
|
139
141
|
const result = await Effect.runPromise(Effect.gen(function* () {
|
|
@@ -145,14 +147,14 @@ export const run = async (options) => {
|
|
|
145
147
|
imageName: resolvedImageName,
|
|
146
148
|
maxIterations,
|
|
147
149
|
branch: resolvedBranch,
|
|
148
|
-
model: resolvedModel,
|
|
149
150
|
});
|
|
150
151
|
yield* d.summary("Sandcastle Run", rows);
|
|
151
152
|
// Validate that the user has not provided built-in prompt argument keys
|
|
152
153
|
const userArgs = options.promptArgs ?? {};
|
|
153
154
|
yield* validateNoBuiltInArgOverride(userArgs);
|
|
154
155
|
// Build effective args: built-in args merged with user-provided args.
|
|
155
|
-
//
|
|
156
|
+
// In none mode, resolvedBranch is already currentHostBranch, so
|
|
157
|
+
// SOURCE_BRANCH and TARGET_BRANCH both resolve to the host's current branch.
|
|
156
158
|
const effectiveArgs = {
|
|
157
159
|
SOURCE_BRANCH: resolvedBranch,
|
|
158
160
|
TARGET_BRANCH: currentHostBranch,
|
|
@@ -160,14 +162,17 @@ export const run = async (options) => {
|
|
|
160
162
|
};
|
|
161
163
|
const builtInArgKeysSet = new Set(BUILT_IN_PROMPT_ARG_KEYS);
|
|
162
164
|
const resolvedPrompt = yield* substitutePromptArgs(rawPrompt, effectiveArgs, builtInArgKeysSet);
|
|
165
|
+
// In none mode, pass the host branch so SandboxLifecycle skips the merge step.
|
|
166
|
+
// In temp-branch mode, branch is undefined (triggers merge). In branch mode, it's the explicit branch.
|
|
167
|
+
const orchestrateBranch = worktreeMode.mode === "none" ? currentHostBranch : branch;
|
|
163
168
|
const orchestrateResult = yield* orchestrate({
|
|
164
169
|
hostRepoDir,
|
|
165
170
|
sandboxRepoDir: SANDBOX_WORKSPACE_DIR,
|
|
166
171
|
iterations: maxIterations,
|
|
167
172
|
hooks,
|
|
168
173
|
prompt: resolvedPrompt,
|
|
169
|
-
branch,
|
|
170
|
-
|
|
174
|
+
branch: orchestrateBranch,
|
|
175
|
+
provider,
|
|
171
176
|
completionSignal: options.completionSignal,
|
|
172
177
|
idleTimeoutSeconds: options.idleTimeoutSeconds,
|
|
173
178
|
name: options.name,
|
package/dist/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { run } from "@ai-hero/sandcastle";
|
|
1
|
+
import { run, claudeCode } from "@ai-hero/sandcastle";
|
|
2
2
|
|
|
3
3
|
// Blank template: customize this to build your own orchestration.
|
|
4
4
|
// Run this with: npx tsx .sandcastle/main.ts
|
|
5
5
|
// Or add to package.json scripts: "sandcastle": "npx tsx .sandcastle/main.ts"
|
|
6
6
|
|
|
7
7
|
await run({
|
|
8
|
+
agent: claudeCode("claude-opus-4-6"),
|
|
8
9
|
promptFile: "./.sandcastle/prompt.md",
|
|
9
10
|
});
|
|
@@ -61,7 +61,7 @@ for (let iteration = 1; iteration <= MAX_ITERATIONS; iteration++) {
|
|
|
61
61
|
// not write code.
|
|
62
62
|
maxIterations: 1,
|
|
63
63
|
// Opus for planning: dependency analysis benefits from deeper reasoning.
|
|
64
|
-
|
|
64
|
+
agent: sandcastle.claudeCode("claude-opus-4-6"),
|
|
65
65
|
promptFile: "./.sandcastle/plan-prompt.md",
|
|
66
66
|
});
|
|
67
67
|
|
|
@@ -109,7 +109,7 @@ for (let iteration = 1; iteration <= MAX_ITERATIONS; iteration++) {
|
|
|
109
109
|
// Give each agent plenty of room to implement and iterate on tests.
|
|
110
110
|
maxIterations: 100,
|
|
111
111
|
// Sonnet for execution: fast and capable enough for typical issue work.
|
|
112
|
-
|
|
112
|
+
agent: sandcastle.claudeCode("claude-sonnet-4-6"),
|
|
113
113
|
promptFile: "./.sandcastle/implement-prompt.md",
|
|
114
114
|
// Prompt arguments substitute {{ISSUE_NUMBER}}, {{ISSUE_TITLE}},
|
|
115
115
|
// and {{BRANCH}} placeholders in implement-prompt.md before the
|
|
@@ -120,7 +120,7 @@ for (let iteration = 1; iteration <= MAX_ITERATIONS; iteration++) {
|
|
|
120
120
|
BRANCH: issue.branch,
|
|
121
121
|
},
|
|
122
122
|
// Each agent starts on its own branch.
|
|
123
|
-
branch: issue.branch,
|
|
123
|
+
worktree: { mode: "branch", branch: issue.branch },
|
|
124
124
|
}),
|
|
125
125
|
),
|
|
126
126
|
);
|
|
@@ -182,7 +182,7 @@ for (let iteration = 1; iteration <= MAX_ITERATIONS; iteration++) {
|
|
|
182
182
|
name: "merger",
|
|
183
183
|
maxIterations: 10,
|
|
184
184
|
// Sonnet is sufficient for merge conflict resolution.
|
|
185
|
-
|
|
185
|
+
agent: sandcastle.claudeCode("claude-sonnet-4-6"),
|
|
186
186
|
promptFile: "./.sandcastle/merge-prompt.md",
|
|
187
187
|
promptArgs: {
|
|
188
188
|
// A markdown list of branch names, one per line.
|