@ai-hero/sandcastle 0.4.8 → 0.5.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 (69) hide show
  1. package/README.md +125 -61
  2. package/dist/AgentProvider.d.ts +9 -0
  3. package/dist/AgentProvider.d.ts.map +1 -1
  4. package/dist/AgentProvider.js +14 -2
  5. package/dist/AgentProvider.js.map +1 -1
  6. package/dist/ErrorHandler.d.ts.map +1 -1
  7. package/dist/ErrorHandler.js +2 -0
  8. package/dist/ErrorHandler.js.map +1 -1
  9. package/dist/Orchestrator.d.ts +13 -1
  10. package/dist/Orchestrator.d.ts.map +1 -1
  11. package/dist/Orchestrator.js +52 -7
  12. package/dist/Orchestrator.js.map +1 -1
  13. package/dist/PodmanLifecycle.d.ts +10 -0
  14. package/dist/PodmanLifecycle.d.ts.map +1 -1
  15. package/dist/PodmanLifecycle.js +22 -0
  16. package/dist/PodmanLifecycle.js.map +1 -1
  17. package/dist/SandboxFactory.d.ts +6 -2
  18. package/dist/SandboxFactory.d.ts.map +1 -1
  19. package/dist/SandboxFactory.js +41 -21
  20. package/dist/SandboxFactory.js.map +1 -1
  21. package/dist/SandboxLifecycle.d.ts +23 -5
  22. package/dist/SandboxLifecycle.d.ts.map +1 -1
  23. package/dist/SandboxLifecycle.js +59 -13
  24. package/dist/SandboxLifecycle.js.map +1 -1
  25. package/dist/SandboxProvider.d.ts +4 -0
  26. package/dist/SandboxProvider.d.ts.map +1 -1
  27. package/dist/SandboxProvider.js.map +1 -1
  28. package/dist/SessionStore.d.ts +50 -0
  29. package/dist/SessionStore.d.ts.map +1 -0
  30. package/dist/SessionStore.js +120 -0
  31. package/dist/SessionStore.js.map +1 -0
  32. package/dist/createSandbox.d.ts +7 -15
  33. package/dist/createSandbox.d.ts.map +1 -1
  34. package/dist/createSandbox.js +40 -16
  35. package/dist/createSandbox.js.map +1 -1
  36. package/dist/createWorktree.d.ts +9 -9
  37. package/dist/createWorktree.d.ts.map +1 -1
  38. package/dist/createWorktree.js +6 -2
  39. package/dist/createWorktree.js.map +1 -1
  40. package/dist/errors.d.ts +10 -1
  41. package/dist/errors.d.ts.map +1 -1
  42. package/dist/errors.js +3 -0
  43. package/dist/errors.js.map +1 -1
  44. package/dist/index.d.ts +4 -1
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +1 -0
  47. package/dist/index.js.map +1 -1
  48. package/dist/interactive.d.ts.map +1 -1
  49. package/dist/interactive.js +9 -1
  50. package/dist/interactive.js.map +1 -1
  51. package/dist/run.d.ts +9 -9
  52. package/dist/run.d.ts.map +1 -1
  53. package/dist/run.js +18 -1
  54. package/dist/run.js.map +1 -1
  55. package/dist/sandboxes/docker.d.ts.map +1 -1
  56. package/dist/sandboxes/docker.js +20 -0
  57. package/dist/sandboxes/docker.js.map +1 -1
  58. package/dist/sandboxes/podman.d.ts.map +1 -1
  59. package/dist/sandboxes/podman.js +26 -0
  60. package/dist/sandboxes/podman.js.map +1 -1
  61. package/dist/sandboxes/test-bind-mount.d.ts +17 -0
  62. package/dist/sandboxes/test-bind-mount.d.ts.map +1 -0
  63. package/dist/sandboxes/test-bind-mount.js +91 -0
  64. package/dist/sandboxes/test-bind-mount.js.map +1 -0
  65. package/dist/templates/parallel-planner/main.mts +1 -1
  66. package/dist/templates/parallel-planner-with-review/main.mts +1 -1
  67. package/dist/templates/sequential-reviewer/main.mts +1 -1
  68. package/dist/templates/simple-loop/main.mts +7 -5
  69. package/package.json +1 -1
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Filesystem-based test bind-mount sandbox provider.
3
+ *
4
+ * Uses a temp directory on the local filesystem as the "sandbox".
5
+ * Intended for testing the bind-mount provider abstraction without
6
+ * requiring Docker or Podman.
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 { createBindMountSandboxProvider, } from "../SandboxProvider.js";
14
+ /**
15
+ * Create a filesystem-based test bind-mount sandbox provider.
16
+ *
17
+ * The "sandbox" is a temp directory. `exec` runs shell commands in it,
18
+ * `copyFileIn`/`copyFileOut` copy single files between host and the temp dir,
19
+ * and `close` removes the temp dir.
20
+ */
21
+ export const testBindMount = () => createBindMountSandboxProvider({
22
+ name: "test-bind-mount",
23
+ create: async () => {
24
+ const sandboxRoot = await mkdtemp(join(tmpdir(), "sandcastle-test-bm-"));
25
+ const worktreePath = join(sandboxRoot, "workspace");
26
+ await mkdir(worktreePath, { recursive: true });
27
+ return {
28
+ worktreePath,
29
+ exec: (command, options) => {
30
+ if (options?.onLine) {
31
+ const onLine = options.onLine;
32
+ return new Promise((resolve, reject) => {
33
+ const proc = spawn("sh", ["-c", command], {
34
+ cwd: options?.cwd ?? worktreePath,
35
+ stdio: ["ignore", "pipe", "pipe"],
36
+ });
37
+ const stdoutChunks = [];
38
+ const stderrChunks = [];
39
+ const rl = createInterface({ input: proc.stdout });
40
+ rl.on("line", (line) => {
41
+ stdoutChunks.push(line);
42
+ onLine(line);
43
+ });
44
+ proc.stderr.on("data", (chunk) => {
45
+ stderrChunks.push(chunk.toString());
46
+ });
47
+ proc.on("error", (error) => {
48
+ reject(new Error(`exec failed: ${error.message}`));
49
+ });
50
+ proc.on("close", (code) => {
51
+ resolve({
52
+ stdout: stdoutChunks.join("\n"),
53
+ stderr: stderrChunks.join(""),
54
+ exitCode: code ?? 0,
55
+ });
56
+ });
57
+ });
58
+ }
59
+ return new Promise((resolve, reject) => {
60
+ execFile("sh", ["-c", command], {
61
+ cwd: options?.cwd ?? worktreePath,
62
+ maxBuffer: 10 * 1024 * 1024,
63
+ }, (error, stdout, stderr) => {
64
+ if (error && error.code === undefined) {
65
+ reject(new Error(`exec failed: ${error.message}`));
66
+ }
67
+ else {
68
+ resolve({
69
+ stdout: stdout.toString(),
70
+ stderr: stderr.toString(),
71
+ exitCode: typeof error?.code === "number" ? error.code : 0,
72
+ });
73
+ }
74
+ });
75
+ });
76
+ },
77
+ copyFileIn: async (hostPath, sandboxPath) => {
78
+ await mkdir(dirname(sandboxPath), { recursive: true });
79
+ await copyFile(hostPath, sandboxPath);
80
+ },
81
+ copyFileOut: async (sandboxPath, hostPath) => {
82
+ await mkdir(dirname(hostPath), { recursive: true });
83
+ await copyFile(sandboxPath, hostPath);
84
+ },
85
+ close: async () => {
86
+ await rm(sandboxRoot, { recursive: true, force: true });
87
+ },
88
+ };
89
+ },
90
+ });
91
+ //# sourceMappingURL=test-bind-mount.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-bind-mount.js","sourceRoot":"","sources":["../../src/sandboxes/test-bind-mount.ts"],"names":[],"mappings":"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"}
@@ -30,7 +30,7 @@ const MAX_ITERATIONS = 10;
30
30
  // Hooks run inside the sandbox before the agent starts each iteration.
31
31
  // npm install ensures the sandbox always has fresh dependencies.
32
32
  const hooks = {
33
- onSandboxReady: [{ command: "npm install" }],
33
+ sandbox: { onSandboxReady: [{ command: "npm install" }] },
34
34
  };
35
35
 
36
36
  // Copy node_modules from the host into the worktree before each sandbox
@@ -35,7 +35,7 @@ const MAX_ITERATIONS = 10;
35
35
  // Hooks run inside the sandbox before the agent starts each iteration.
36
36
  // npm install ensures the sandbox always has fresh dependencies.
37
37
  const hooks = {
38
- onSandboxReady: [{ command: "npm install" }],
38
+ sandbox: { onSandboxReady: [{ command: "npm install" }] },
39
39
  };
40
40
 
41
41
  // Copy node_modules from the host into the worktree before each sandbox
@@ -30,7 +30,7 @@ const MAX_ITERATIONS = 10;
30
30
  // Hooks run inside the sandbox before the agent starts each iteration.
31
31
  // npm install ensures the sandbox always has fresh dependencies.
32
32
  const hooks = {
33
- onSandboxReady: [{ command: "npm install" }],
33
+ sandbox: { onSandboxReady: [{ command: "npm install" }] },
34
34
  };
35
35
 
36
36
  // Copy node_modules from the host into the worktree before each sandbox
@@ -38,11 +38,13 @@ await run({
38
38
  // platform-specific binaries and any packages added since the last copy.
39
39
  copyToWorktree: ["node_modules"],
40
40
 
41
- // Lifecycle hooks — commands that run inside the sandbox at specific points.
41
+ // Lifecycle hooks — commands grouped by where they run (host or sandbox).
42
42
  hooks: {
43
- // onSandboxReady runs once after the sandbox is initialised and the repo is
44
- // synced in, before the agent starts. Use it to install dependencies or run
45
- // any other setup steps your project needs.
46
- onSandboxReady: [{ command: "npm install" }],
43
+ sandbox: {
44
+ // onSandboxReady runs once after the sandbox is initialised and the repo is
45
+ // synced in, before the agent starts. Use it to install dependencies or run
46
+ // any other setup steps your project needs.
47
+ onSandboxReady: [{ command: "npm install" }],
48
+ },
47
49
  },
48
50
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-hero/sandcastle",
3
- "version": "0.4.8",
3
+ "version": "0.5.0",
4
4
  "description": "CLI for orchestrating AI agents in isolated sandbox environments",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",