@ai-hero/sandcastle 0.2.4 → 0.4.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 +322 -42
- package/dist/AgentProvider.d.ts +0 -10
- package/dist/AgentProvider.d.ts.map +1 -1
- package/dist/AgentProvider.js +28 -45
- package/dist/AgentProvider.js.map +1 -1
- package/dist/DockerLifecycle.d.ts +5 -1
- package/dist/DockerLifecycle.d.ts.map +1 -1
- package/dist/DockerLifecycle.js +8 -1
- package/dist/DockerLifecycle.js.map +1 -1
- package/dist/InitService.d.ts.map +1 -1
- package/dist/InitService.js +2 -0
- package/dist/InitService.js.map +1 -1
- package/dist/Orchestrator.d.ts +0 -1
- package/dist/Orchestrator.d.ts.map +1 -1
- package/dist/Orchestrator.js +2 -13
- package/dist/Orchestrator.js.map +1 -1
- package/dist/SandboxFactory.d.ts +22 -11
- package/dist/SandboxFactory.d.ts.map +1 -1
- package/dist/SandboxFactory.js +166 -209
- package/dist/SandboxFactory.js.map +1 -1
- package/dist/SandboxProvider.d.ts +141 -0
- package/dist/SandboxProvider.d.ts.map +1 -0
- package/dist/SandboxProvider.js +27 -0
- package/dist/SandboxProvider.js.map +1 -0
- package/dist/cli.d.ts +7 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +12 -11
- package/dist/cli.js.map +1 -1
- package/dist/createSandbox.d.ts +3 -2
- package/dist/createSandbox.d.ts.map +1 -1
- package/dist/createSandbox.js +19 -32
- package/dist/createSandbox.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/run.d.ts +4 -25
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +21 -35
- package/dist/run.js.map +1 -1
- package/dist/sandboxExec.d.ts +12 -0
- package/dist/sandboxExec.d.ts.map +1 -0
- package/dist/sandboxExec.js +26 -0
- package/dist/sandboxExec.js.map +1 -0
- package/dist/sandboxes/docker.d.ts +28 -0
- package/dist/sandboxes/docker.d.ts.map +1 -0
- package/dist/sandboxes/docker.js +134 -0
- package/dist/sandboxes/docker.js.map +1 -0
- package/dist/sandboxes/test-isolated.d.ts +21 -0
- package/dist/sandboxes/test-isolated.d.ts.map +1 -0
- package/dist/sandboxes/test-isolated.js +87 -0
- package/dist/sandboxes/test-isolated.js.map +1 -0
- package/dist/syncIn.d.ts +24 -0
- package/dist/syncIn.d.ts.map +1 -0
- package/dist/syncIn.js +107 -0
- package/dist/syncIn.js.map +1 -0
- package/dist/syncOut.d.ts +27 -0
- package/dist/syncOut.d.ts.map +1 -0
- package/dist/syncOut.js +271 -0
- package/dist/syncOut.js.map +1 -0
- package/dist/templates/blank/.env.example +1 -0
- package/dist/templates/blank/main.mts +2 -0
- package/dist/templates/parallel-planner/.env.example +1 -0
- package/dist/templates/parallel-planner/main.mts +5 -2
- package/dist/templates/sequential-reviewer/.env.example +1 -0
- package/dist/templates/sequential-reviewer/main.mts +3 -1
- package/dist/templates/simple-loop/.env.example +1 -0
- package/dist/templates/simple-loop/main.mts +4 -0
- package/package.json +5 -1
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;AAEvC,OAAO,EACL,YAAY,EACZ,OAAO,EACP,WAAW,GAEZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,4BAA4B,EAC5B,
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IsolatedSandboxHandle } from "./SandboxProvider.js";
|
|
2
|
+
/** Execute a command on the host side, returning stdout. Throws on non-zero exit. */
|
|
3
|
+
export declare const execHost: (command: string, cwd: string) => Promise<string>;
|
|
4
|
+
/** Execute a command in the sandbox, throwing if it fails. */
|
|
5
|
+
export declare const execOk: (handle: IsolatedSandboxHandle, command: string, options?: {
|
|
6
|
+
cwd?: string | undefined;
|
|
7
|
+
} | undefined) => Promise<{
|
|
8
|
+
stdout: string;
|
|
9
|
+
stderr: string;
|
|
10
|
+
exitCode: number;
|
|
11
|
+
}>;
|
|
12
|
+
//# sourceMappingURL=sandboxExec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandboxExec.d.ts","sourceRoot":"","sources":["../src/sandboxExec.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAIlE,qFAAqF;AACrF,eAAO,MAAM,QAAQ,mDAcpB,CAAC;AAEF,8DAA8D;AAC9D,eAAO,MAAM,MAAM;;;;;;EAYlB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
const execAsync = promisify(exec);
|
|
4
|
+
/** Execute a command on the host side, returning stdout. Throws on non-zero exit. */
|
|
5
|
+
export const execHost = async (command, cwd) => {
|
|
6
|
+
try {
|
|
7
|
+
const { stdout } = await execAsync(command, {
|
|
8
|
+
cwd,
|
|
9
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
10
|
+
});
|
|
11
|
+
return stdout;
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15
|
+
throw new Error(`Host command failed: ${command}\n${message}`);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
/** Execute a command in the sandbox, throwing if it fails. */
|
|
19
|
+
export const execOk = async (handle, command, options) => {
|
|
20
|
+
const result = await handle.exec(command, options);
|
|
21
|
+
if (result.exitCode !== 0) {
|
|
22
|
+
throw new Error(`Sandbox command failed (exit ${result.exitCode}): ${command}\n${result.stderr}`);
|
|
23
|
+
}
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=sandboxExec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandboxExec.js","sourceRoot":"","sources":["../src/sandboxExec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC,qFAAqF;AACrF,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,EAC3B,OAAe,EACf,GAAW,EACM,EAAE;IACnB,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE;YAC1C,GAAG;YACH,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;SAC5B,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,KAAK,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC,CAAC;AAEF,8DAA8D;AAC9D,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,EACzB,MAA6B,EAC7B,OAAe,EACf,OAA0B,EACqC,EAAE;IACjE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACnD,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,gCAAgC,MAAM,CAAC,QAAQ,MAAM,OAAO,KAAK,MAAM,CAAC,MAAM,EAAE,CACjF,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docker sandbox provider — wraps DockerLifecycle into a SandboxProvider.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* import { docker } from "sandcastle/sandboxes/docker";
|
|
6
|
+
* await run({ agent: claudeCode("claude-opus-4-6"), sandbox: docker() });
|
|
7
|
+
*/
|
|
8
|
+
import { type BindMountBranchStrategy, type SandboxProvider } from "../SandboxProvider.js";
|
|
9
|
+
export interface DockerOptions {
|
|
10
|
+
/** Docker image name (default: derived from repo directory name). */
|
|
11
|
+
readonly imageName?: string;
|
|
12
|
+
/** Branch strategy for this provider. Defaults to { type: "head" }. */
|
|
13
|
+
readonly branchStrategy?: BindMountBranchStrategy;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create a Docker sandbox provider.
|
|
17
|
+
*
|
|
18
|
+
* The returned provider creates Docker containers with bind-mounts
|
|
19
|
+
* for the worktree and git directories.
|
|
20
|
+
*/
|
|
21
|
+
export declare const docker: (options?: DockerOptions | undefined) => SandboxProvider;
|
|
22
|
+
/**
|
|
23
|
+
* Derive the default Docker image name from the repo directory.
|
|
24
|
+
* Returns `sandcastle:<dir-name>` where dir-name is the last path segment,
|
|
25
|
+
* lowercased and sanitized for Docker image tag rules.
|
|
26
|
+
*/
|
|
27
|
+
export declare const defaultImageName: (repoDir: string) => string;
|
|
28
|
+
//# sourceMappingURL=docker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../src/sandboxes/docker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAWH,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EAIrB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,cAAc,CAAC,EAAE,uBAAuB,CAAC;CACnD;AAED;;;;;GAKG;AACH,eAAO,MAAM,MAAM,0DAwJlB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,6BAI5B,CAAC"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docker sandbox provider — wraps DockerLifecycle into a SandboxProvider.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* import { docker } from "sandcastle/sandboxes/docker";
|
|
6
|
+
* await run({ agent: claudeCode("claude-opus-4-6"), sandbox: docker() });
|
|
7
|
+
*/
|
|
8
|
+
import { execFile, execFileSync, spawn } from "node:child_process";
|
|
9
|
+
import { randomUUID } from "node:crypto";
|
|
10
|
+
import { createInterface } from "node:readline";
|
|
11
|
+
import { Effect } from "effect";
|
|
12
|
+
import { startContainer, removeContainer, chownInContainer, } from "../DockerLifecycle.js";
|
|
13
|
+
import { createBindMountSandboxProvider, } from "../SandboxProvider.js";
|
|
14
|
+
/**
|
|
15
|
+
* Create a Docker sandbox provider.
|
|
16
|
+
*
|
|
17
|
+
* The returned provider creates Docker containers with bind-mounts
|
|
18
|
+
* for the worktree and git directories.
|
|
19
|
+
*/
|
|
20
|
+
export const docker = (options) => {
|
|
21
|
+
const configuredImageName = options?.imageName;
|
|
22
|
+
return createBindMountSandboxProvider({
|
|
23
|
+
name: "docker",
|
|
24
|
+
branchStrategy: options?.branchStrategy,
|
|
25
|
+
create: async (createOptions) => {
|
|
26
|
+
const containerName = `sandcastle-${randomUUID()}`;
|
|
27
|
+
const workspacePath = createOptions.mounts.find((m) => m.hostPath === createOptions.worktreePath)?.sandboxPath ?? "/home/agent/workspace";
|
|
28
|
+
// Build volume mount strings
|
|
29
|
+
const volumeMounts = createOptions.mounts.map((m) => {
|
|
30
|
+
const base = `${m.hostPath}:${m.sandboxPath}`;
|
|
31
|
+
return m.readonly ? `${base}:ro` : base;
|
|
32
|
+
});
|
|
33
|
+
// Resolve image name
|
|
34
|
+
const imageName = configuredImageName ?? defaultImageName(createOptions.hostRepoPath);
|
|
35
|
+
const hostUid = process.getuid?.() ?? 1000;
|
|
36
|
+
const hostGid = process.getgid?.() ?? 1000;
|
|
37
|
+
// Start container
|
|
38
|
+
await Effect.runPromise(startContainer(containerName, imageName, {
|
|
39
|
+
...createOptions.env,
|
|
40
|
+
HOME: "/home/agent",
|
|
41
|
+
}, {
|
|
42
|
+
volumeMounts,
|
|
43
|
+
workdir: workspacePath,
|
|
44
|
+
user: `${hostUid}:${hostGid}`,
|
|
45
|
+
}).pipe(Effect.andThen(chownInContainer(containerName, `${hostUid}:${hostGid}`, "/home/agent"))));
|
|
46
|
+
// Set up signal handlers for cleanup
|
|
47
|
+
const onExit = () => {
|
|
48
|
+
try {
|
|
49
|
+
execFileSync("docker", ["rm", "-f", containerName], {
|
|
50
|
+
stdio: "ignore",
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
/* best-effort */
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const onSignal = () => {
|
|
58
|
+
onExit();
|
|
59
|
+
process.exit(1);
|
|
60
|
+
};
|
|
61
|
+
process.on("exit", onExit);
|
|
62
|
+
process.on("SIGINT", onSignal);
|
|
63
|
+
process.on("SIGTERM", onSignal);
|
|
64
|
+
const handle = {
|
|
65
|
+
workspacePath,
|
|
66
|
+
exec: (command, opts) => new Promise((resolve, reject) => {
|
|
67
|
+
const args = ["exec"];
|
|
68
|
+
if (opts?.cwd)
|
|
69
|
+
args.push("-w", opts.cwd);
|
|
70
|
+
args.push(containerName, "sh", "-c", command);
|
|
71
|
+
execFile("docker", args, { maxBuffer: 10 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
72
|
+
if (error && error.code === undefined) {
|
|
73
|
+
reject(new Error(`docker exec failed: ${error.message}`));
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
resolve({
|
|
77
|
+
stdout: stdout.toString(),
|
|
78
|
+
stderr: stderr.toString(),
|
|
79
|
+
exitCode: typeof error?.code === "number" ? error.code : 0,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}),
|
|
84
|
+
execStreaming: (command, onLine, opts) => new Promise((resolve, reject) => {
|
|
85
|
+
const args = ["exec"];
|
|
86
|
+
if (opts?.cwd)
|
|
87
|
+
args.push("-w", opts.cwd);
|
|
88
|
+
args.push(containerName, "sh", "-c", command);
|
|
89
|
+
const proc = spawn("docker", args, {
|
|
90
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
91
|
+
});
|
|
92
|
+
const stdoutChunks = [];
|
|
93
|
+
const stderrChunks = [];
|
|
94
|
+
const rl = createInterface({ input: proc.stdout });
|
|
95
|
+
rl.on("line", (line) => {
|
|
96
|
+
stdoutChunks.push(line);
|
|
97
|
+
onLine(line);
|
|
98
|
+
});
|
|
99
|
+
proc.stderr.on("data", (chunk) => {
|
|
100
|
+
stderrChunks.push(chunk.toString());
|
|
101
|
+
});
|
|
102
|
+
proc.on("error", (error) => {
|
|
103
|
+
reject(new Error(`docker exec streaming failed: ${error.message}`));
|
|
104
|
+
});
|
|
105
|
+
proc.on("close", (code) => {
|
|
106
|
+
resolve({
|
|
107
|
+
stdout: stdoutChunks.join("\n"),
|
|
108
|
+
stderr: stderrChunks.join(""),
|
|
109
|
+
exitCode: code ?? 0,
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}),
|
|
113
|
+
close: async () => {
|
|
114
|
+
process.removeListener("exit", onExit);
|
|
115
|
+
process.removeListener("SIGINT", onSignal);
|
|
116
|
+
process.removeListener("SIGTERM", onSignal);
|
|
117
|
+
await Effect.runPromise(removeContainer(containerName));
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
return handle;
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Derive the default Docker image name from the repo directory.
|
|
126
|
+
* Returns `sandcastle:<dir-name>` where dir-name is the last path segment,
|
|
127
|
+
* lowercased and sanitized for Docker image tag rules.
|
|
128
|
+
*/
|
|
129
|
+
export const defaultImageName = (repoDir) => {
|
|
130
|
+
const dirName = repoDir.replace(/\/+$/, "").split("/").pop() ?? "local";
|
|
131
|
+
const sanitized = dirName.toLowerCase().replace(/[^a-z0-9_.-]/g, "-");
|
|
132
|
+
return `sandcastle:${sanitized}`;
|
|
133
|
+
};
|
|
134
|
+
//# sourceMappingURL=docker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker.js","sourceRoot":"","sources":["../../src/sandboxes/docker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem-based test isolated sandbox provider.
|
|
3
|
+
*
|
|
4
|
+
* Uses a temp directory on the local filesystem as the "sandbox".
|
|
5
|
+
* Intended for testing the isolated provider abstraction without
|
|
6
|
+
* requiring a real remote environment.
|
|
7
|
+
*/
|
|
8
|
+
import { type IsolatedBranchStrategy, type IsolatedSandboxProvider } from "../SandboxProvider.js";
|
|
9
|
+
export interface TestIsolatedOptions {
|
|
10
|
+
/** Branch strategy for this provider. Defaults to { type: "merge-to-head" }. */
|
|
11
|
+
readonly branchStrategy?: IsolatedBranchStrategy;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create a filesystem-based test isolated sandbox provider.
|
|
15
|
+
*
|
|
16
|
+
* The "sandbox" is a temp directory. `exec` runs shell commands in it,
|
|
17
|
+
* `copyIn`/`copyOut` copy files between host and the temp dir,
|
|
18
|
+
* and `close` removes the temp dir.
|
|
19
|
+
*/
|
|
20
|
+
export declare const testIsolated: (options?: TestIsolatedOptions | undefined) => IsolatedSandboxProvider;
|
|
21
|
+
//# sourceMappingURL=test-isolated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-isolated.d.ts","sourceRoot":"","sources":["../../src/sandboxes/test-isolated.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,EAGL,KAAK,sBAAsB,EAE3B,KAAK,uBAAuB,EAC7B,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,mBAAmB;IAClC,gFAAgF;IAChF,QAAQ,CAAC,cAAc,CAAC,EAAE,sBAAsB,CAAC;CAClD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,wEAkGrB,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem-based test isolated sandbox provider.
|
|
3
|
+
*
|
|
4
|
+
* Uses a temp directory on the local filesystem as the "sandbox".
|
|
5
|
+
* Intended for testing the isolated provider abstraction without
|
|
6
|
+
* requiring a real remote environment.
|
|
7
|
+
*/
|
|
8
|
+
import { execFile, spawn } from "node:child_process";
|
|
9
|
+
import { copyFile, mkdir, mkdtemp, rm } from "node:fs/promises";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
import { createInterface } from "node:readline";
|
|
13
|
+
import { createIsolatedSandboxProvider, } from "../SandboxProvider.js";
|
|
14
|
+
/**
|
|
15
|
+
* Create a filesystem-based test isolated sandbox provider.
|
|
16
|
+
*
|
|
17
|
+
* The "sandbox" is a temp directory. `exec` runs shell commands in it,
|
|
18
|
+
* `copyIn`/`copyOut` copy files between host and the temp dir,
|
|
19
|
+
* and `close` removes the temp dir.
|
|
20
|
+
*/
|
|
21
|
+
export const testIsolated = (options) => createIsolatedSandboxProvider({
|
|
22
|
+
name: "test-isolated",
|
|
23
|
+
branchStrategy: options?.branchStrategy,
|
|
24
|
+
create: async () => {
|
|
25
|
+
const sandboxRoot = await mkdtemp(join(tmpdir(), "sandcastle-test-"));
|
|
26
|
+
const workspacePath = join(sandboxRoot, "workspace");
|
|
27
|
+
await mkdir(workspacePath, { recursive: true });
|
|
28
|
+
return {
|
|
29
|
+
workspacePath,
|
|
30
|
+
exec: (command, options) => new Promise((resolve, reject) => {
|
|
31
|
+
execFile("sh", ["-c", command], {
|
|
32
|
+
cwd: options?.cwd ?? workspacePath,
|
|
33
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
34
|
+
}, (error, stdout, stderr) => {
|
|
35
|
+
if (error && error.code === undefined) {
|
|
36
|
+
reject(new Error(`exec failed: ${error.message}`));
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
resolve({
|
|
40
|
+
stdout: stdout.toString(),
|
|
41
|
+
stderr: stderr.toString(),
|
|
42
|
+
exitCode: typeof error?.code === "number" ? error.code : 0,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}),
|
|
47
|
+
execStreaming: (command, onLine, options) => new Promise((resolve, reject) => {
|
|
48
|
+
const proc = spawn("sh", ["-c", command], {
|
|
49
|
+
cwd: options?.cwd ?? workspacePath,
|
|
50
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
51
|
+
});
|
|
52
|
+
const stdoutChunks = [];
|
|
53
|
+
const stderrChunks = [];
|
|
54
|
+
const rl = createInterface({ input: proc.stdout });
|
|
55
|
+
rl.on("line", (line) => {
|
|
56
|
+
stdoutChunks.push(line);
|
|
57
|
+
onLine(line);
|
|
58
|
+
});
|
|
59
|
+
proc.stderr.on("data", (chunk) => {
|
|
60
|
+
stderrChunks.push(chunk.toString());
|
|
61
|
+
});
|
|
62
|
+
proc.on("error", (error) => {
|
|
63
|
+
reject(new Error(`exec streaming failed: ${error.message}`));
|
|
64
|
+
});
|
|
65
|
+
proc.on("close", (code) => {
|
|
66
|
+
resolve({
|
|
67
|
+
stdout: stdoutChunks.join("\n"),
|
|
68
|
+
stderr: stderrChunks.join(""),
|
|
69
|
+
exitCode: code ?? 0,
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}),
|
|
73
|
+
copyIn: async (hostPath, sandboxPath) => {
|
|
74
|
+
await mkdir(dirname(sandboxPath), { recursive: true });
|
|
75
|
+
await copyFile(hostPath, sandboxPath);
|
|
76
|
+
},
|
|
77
|
+
copyOut: async (sandboxPath, hostPath) => {
|
|
78
|
+
await mkdir(dirname(hostPath), { recursive: true });
|
|
79
|
+
await copyFile(sandboxPath, hostPath);
|
|
80
|
+
},
|
|
81
|
+
close: async () => {
|
|
82
|
+
await rm(sandboxRoot, { recursive: true, force: true });
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=test-isolated.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-isolated.js","sourceRoot":"","sources":["../../src/sandboxes/test-isolated.ts"],"names":[],"mappings":"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"}
|
package/dist/syncIn.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync-in: transfer a host git repo into an isolated sandbox via git bundle.
|
|
3
|
+
*
|
|
4
|
+
* Creates a git bundle capturing all refs from the host repo,
|
|
5
|
+
* copies it into the sandbox via the provider's copyIn, and
|
|
6
|
+
* clones from the bundle inside the sandbox.
|
|
7
|
+
*/
|
|
8
|
+
import { Effect } from "effect";
|
|
9
|
+
import type { IsolatedSandboxHandle } from "./SandboxProvider.js";
|
|
10
|
+
import { SyncError } from "./errors.js";
|
|
11
|
+
/**
|
|
12
|
+
* Sync a host git repo into an isolated sandbox.
|
|
13
|
+
*
|
|
14
|
+
* 1. `git bundle create --all` on the host
|
|
15
|
+
* 2. `copyIn` the bundle to the sandbox
|
|
16
|
+
* 3. `git clone` from the bundle inside the sandbox
|
|
17
|
+
* 4. Verify HEAD matches
|
|
18
|
+
*
|
|
19
|
+
* @returns The branch name that was checked out
|
|
20
|
+
*/
|
|
21
|
+
export declare const syncIn: (hostRepoDir: string, handle: IsolatedSandboxHandle) => Effect.Effect<{
|
|
22
|
+
branch: string;
|
|
23
|
+
}, SyncError, never>;
|
|
24
|
+
//# sourceMappingURL=syncIn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"syncIn.d.ts","sourceRoot":"","sources":["../src/syncIn.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAwDxC;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM;;oBA2Ff,CAAC"}
|
package/dist/syncIn.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync-in: transfer a host git repo into an isolated sandbox via git bundle.
|
|
3
|
+
*
|
|
4
|
+
* Creates a git bundle capturing all refs from the host repo,
|
|
5
|
+
* copies it into the sandbox via the provider's copyIn, and
|
|
6
|
+
* clones from the bundle inside the sandbox.
|
|
7
|
+
*/
|
|
8
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { Effect } from "effect";
|
|
12
|
+
import { SyncError } from "./errors.js";
|
|
13
|
+
/**
|
|
14
|
+
* Execute a command on the host side, returning stdout.
|
|
15
|
+
* Fails with SyncError on non-zero exit.
|
|
16
|
+
*/
|
|
17
|
+
const execHost = (command, cwd) => Effect.tryPromise({
|
|
18
|
+
try: async () => {
|
|
19
|
+
const { exec } = await import("node:child_process");
|
|
20
|
+
const { promisify } = await import("node:util");
|
|
21
|
+
const execAsync = promisify(exec);
|
|
22
|
+
const { stdout } = await execAsync(command, {
|
|
23
|
+
cwd,
|
|
24
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
25
|
+
});
|
|
26
|
+
return stdout;
|
|
27
|
+
},
|
|
28
|
+
catch: (e) => new SyncError({
|
|
29
|
+
message: `Host command failed: ${command}\n${e instanceof Error ? e.message : String(e)}`,
|
|
30
|
+
}),
|
|
31
|
+
});
|
|
32
|
+
/**
|
|
33
|
+
* Execute a command in the sandbox, failing with SyncError if it exits non-zero.
|
|
34
|
+
*/
|
|
35
|
+
const execOk = (handle, command, options) => Effect.tryPromise({
|
|
36
|
+
try: () => handle.exec(command, options),
|
|
37
|
+
catch: (e) => new SyncError({
|
|
38
|
+
message: `Sandbox exec failed: ${command}\n${e instanceof Error ? e.message : String(e)}`,
|
|
39
|
+
}),
|
|
40
|
+
}).pipe(Effect.flatMap((result) => result.exitCode !== 0
|
|
41
|
+
? Effect.fail(new SyncError({
|
|
42
|
+
message: `Sandbox command failed (exit ${result.exitCode}): ${command}\n${result.stderr}`,
|
|
43
|
+
}))
|
|
44
|
+
: Effect.succeed(result)));
|
|
45
|
+
/**
|
|
46
|
+
* Sync a host git repo into an isolated sandbox.
|
|
47
|
+
*
|
|
48
|
+
* 1. `git bundle create --all` on the host
|
|
49
|
+
* 2. `copyIn` the bundle to the sandbox
|
|
50
|
+
* 3. `git clone` from the bundle inside the sandbox
|
|
51
|
+
* 4. Verify HEAD matches
|
|
52
|
+
*
|
|
53
|
+
* @returns The branch name that was checked out
|
|
54
|
+
*/
|
|
55
|
+
export const syncIn = (hostRepoDir, handle) => Effect.gen(function* () {
|
|
56
|
+
// Get current branch from host
|
|
57
|
+
const branch = (yield* execHost("git rev-parse --abbrev-ref HEAD", hostRepoDir)).trim();
|
|
58
|
+
// Create git bundle on host capturing all refs
|
|
59
|
+
const bundleDir = yield* Effect.tryPromise({
|
|
60
|
+
try: () => mkdtemp(join(tmpdir(), "sandcastle-bundle-")),
|
|
61
|
+
catch: (e) => new SyncError({
|
|
62
|
+
message: `Failed to create temp dir: ${e instanceof Error ? e.message : String(e)}`,
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
65
|
+
const bundleHostPath = join(bundleDir, "repo.bundle");
|
|
66
|
+
yield* Effect.ensuring(Effect.gen(function* () {
|
|
67
|
+
yield* execHost(`git bundle create "${bundleHostPath}" --all`, hostRepoDir);
|
|
68
|
+
// Create temp dir in sandbox and copy bundle in
|
|
69
|
+
const mkTempResult = yield* execOk(handle, "mktemp -d -t sandcastle-XXXXXX");
|
|
70
|
+
const sandboxTmpDir = mkTempResult.stdout.trim();
|
|
71
|
+
const bundleSandboxPath = `${sandboxTmpDir}/repo.bundle`;
|
|
72
|
+
yield* Effect.tryPromise({
|
|
73
|
+
try: () => handle.copyIn(bundleHostPath, bundleSandboxPath),
|
|
74
|
+
catch: (e) => new SyncError({
|
|
75
|
+
message: `Failed to copy bundle into sandbox: ${e instanceof Error ? e.message : String(e)}`,
|
|
76
|
+
}),
|
|
77
|
+
});
|
|
78
|
+
// Clone from bundle into the workspace
|
|
79
|
+
const workspacePath = handle.workspacePath;
|
|
80
|
+
yield* execOk(handle, `git clone "${bundleSandboxPath}" "${workspacePath}_clone"`);
|
|
81
|
+
// Move contents from clone into workspace (git clone requires empty target)
|
|
82
|
+
yield* execOk(handle, `rm -rf "${workspacePath}" && mv "${workspacePath}_clone" "${workspacePath}"`);
|
|
83
|
+
// Checkout the correct branch
|
|
84
|
+
yield* execOk(handle, `git checkout "${branch}"`, {
|
|
85
|
+
cwd: workspacePath,
|
|
86
|
+
});
|
|
87
|
+
// Clean up sandbox temp files
|
|
88
|
+
yield* Effect.tryPromise({
|
|
89
|
+
try: () => handle.exec(`rm -rf "${sandboxTmpDir}"`),
|
|
90
|
+
catch: () => new SyncError({ message: "Failed to clean up sandbox temp dir" }),
|
|
91
|
+
});
|
|
92
|
+
// Verify sync succeeded
|
|
93
|
+
const hostHead = (yield* execHost("git rev-parse HEAD", hostRepoDir)).trim();
|
|
94
|
+
const sandboxHead = (yield* execOk(handle, "git rev-parse HEAD", {
|
|
95
|
+
cwd: workspacePath,
|
|
96
|
+
})).stdout.trim();
|
|
97
|
+
if (hostHead !== sandboxHead) {
|
|
98
|
+
yield* Effect.fail(new SyncError({
|
|
99
|
+
message: `HEAD mismatch after sync-in: host=${hostHead} sandbox=${sandboxHead}`,
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
}),
|
|
103
|
+
// Clean up host-side bundle temp dir (runs regardless of success/failure)
|
|
104
|
+
Effect.promise(() => rm(bundleDir, { recursive: true, force: true })));
|
|
105
|
+
return { branch };
|
|
106
|
+
});
|
|
107
|
+
//# sourceMappingURL=syncIn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"syncIn.js","sourceRoot":"","sources":["../src/syncIn.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync-out: extract changes from an isolated sandbox back to the host.
|
|
3
|
+
*
|
|
4
|
+
* Two-phase approach:
|
|
5
|
+
* 1. Save phase: eagerly save all artifacts (patches, diff, untracked files)
|
|
6
|
+
* to `.sandcastle/patches/<timestamp>/` before attempting to apply.
|
|
7
|
+
* 2. Apply phase: apply from the saved directory.
|
|
8
|
+
* - On success: clean up the patch directory.
|
|
9
|
+
* - On failure: preserve the patch directory and print recovery commands.
|
|
10
|
+
*
|
|
11
|
+
* Three-prong extraction within each phase:
|
|
12
|
+
* 1. Committed changes: `git format-patch` + `git am --3way`
|
|
13
|
+
* 2. Uncommitted changes (staged + unstaged): `git diff HEAD` + `git apply`
|
|
14
|
+
* 3. Untracked files: `git ls-files --others` + `copyOut` each file
|
|
15
|
+
*/
|
|
16
|
+
import { Effect } from "effect";
|
|
17
|
+
import type { IsolatedSandboxHandle } from "./SandboxProvider.js";
|
|
18
|
+
import { SyncError } from "./errors.js";
|
|
19
|
+
/**
|
|
20
|
+
* Sync changes from an isolated sandbox back to the host repo.
|
|
21
|
+
*
|
|
22
|
+
* Two-phase extraction with artifact persistence:
|
|
23
|
+
* 1. Save all artifacts to `.sandcastle/patches/<timestamp>/`
|
|
24
|
+
* 2. Apply from saved directory; on failure, preserve artifacts and print recovery
|
|
25
|
+
*/
|
|
26
|
+
export declare const syncOut: (hostRepoDir: string, handle: IsolatedSandboxHandle) => Effect.Effect<void, SyncError, never>;
|
|
27
|
+
//# sourceMappingURL=syncOut.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"syncOut.d.ts","sourceRoot":"","sources":["../src/syncOut.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAYH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AA+HxC;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,+FAgNhB,CAAC"}
|