@sandagent/runner-cli 0.2.9 ā 0.2.11
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 +29 -3
- package/dist/__tests__/build-image.test.d.ts +2 -0
- package/dist/__tests__/build-image.test.d.ts.map +1 -0
- package/dist/__tests__/build-image.test.js +145 -0
- package/dist/__tests__/build-image.test.js.map +1 -0
- package/dist/__tests__/runner-cli.integration.test.js +8 -1
- package/dist/__tests__/runner-cli.integration.test.js.map +1 -1
- package/dist/build-image.d.ts +16 -0
- package/dist/build-image.d.ts.map +1 -0
- package/dist/build-image.js +114 -0
- package/dist/build-image.js.map +1 -0
- package/dist/bundle.mjs +307 -77
- package/dist/cli.d.ts +3 -8
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +198 -88
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -33,10 +33,10 @@ Dependencies:
|
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
35
|
# Global install (recommended if you want the `sandagent` command)
|
|
36
|
-
npm install -g @sandagent/runner-cli@
|
|
36
|
+
npm install -g @sandagent/runner-cli@latest
|
|
37
37
|
|
|
38
38
|
# Or add to a project
|
|
39
|
-
npm install @sandagent/runner-cli@
|
|
39
|
+
npm install @sandagent/runner-cli@latest
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
## Usage
|
|
@@ -48,7 +48,7 @@ sandagent run [options] -- "<user input>"
|
|
|
48
48
|
Without installing globally, you can also run it via `npx`:
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
npx -y @sandagent/runner-cli@
|
|
51
|
+
npx -y @sandagent/runner-cli@latest run -- "Create a hello world script"
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
### Basic Examples
|
|
@@ -156,6 +156,32 @@ The CLI is designed to:
|
|
|
156
156
|
3. Stream AI SDK UI messages directly to stdout
|
|
157
157
|
4. Support both SSE stream and JSON output formats
|
|
158
158
|
|
|
159
|
+
## š³ Docker Image Build
|
|
160
|
+
|
|
161
|
+
Build Docker images with agent templates baked in:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Build image
|
|
165
|
+
sandagent image build --name vikadata/sandagent-seo --tag 0.1.0 --template ./templates/seo-agent
|
|
166
|
+
|
|
167
|
+
# Build and push
|
|
168
|
+
sandagent image build --name vikadata/sandagent-seo --tag 0.1.0 --template ./templates/seo-agent --push
|
|
169
|
+
|
|
170
|
+
# Without template
|
|
171
|
+
sandagent image build --name vikadata/sandagent --tag 0.1.0
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Image Build Options
|
|
175
|
+
|
|
176
|
+
| Option | Description | Default |
|
|
177
|
+
|--------|-------------|---------|
|
|
178
|
+
| `--name <name>` | Full image name (e.g. `vikadata/sandagent-seo`) | `sandagent` |
|
|
179
|
+
| `--tag <tag>` | Image tag | `latest` |
|
|
180
|
+
| `--image <full>` | Full image name override (e.g. `myorg/myimage:v1`) | - |
|
|
181
|
+
| `--platform <plat>` | Build platform | `linux/amd64` |
|
|
182
|
+
| `--template <path>` | Path to agent template directory | - |
|
|
183
|
+
| `--push` | Push image to registry after build | `false` |
|
|
184
|
+
|
|
159
185
|
## Related Documentation
|
|
160
186
|
|
|
161
187
|
- [Claude Agent SDK](https://platform.claude.com/docs/agent-sdk/typescript)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-image.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/build-image.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
// Mock child_process so we never actually run docker
|
|
5
|
+
vi.mock("node:child_process", () => ({
|
|
6
|
+
execSync: vi.fn((cmd) => {
|
|
7
|
+
// docker info check ā pretend docker is running
|
|
8
|
+
if (cmd === "docker info")
|
|
9
|
+
return Buffer.from("");
|
|
10
|
+
// Record the command for assertions
|
|
11
|
+
return Buffer.from("");
|
|
12
|
+
}),
|
|
13
|
+
}));
|
|
14
|
+
import { execSync } from "node:child_process";
|
|
15
|
+
import { buildImage } from "../build-image.js";
|
|
16
|
+
const mockedExecSync = vi.mocked(execSync);
|
|
17
|
+
const TEST_DIR = join(process.cwd(), ".test-build-image");
|
|
18
|
+
const BUILD_CONTEXT = join(TEST_DIR, ".docker-staging");
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
mkdirSync(TEST_DIR, { recursive: true });
|
|
21
|
+
mockedExecSync.mockClear();
|
|
22
|
+
});
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
25
|
+
rmSync(BUILD_CONTEXT, { recursive: true, force: true });
|
|
26
|
+
// Also clean up the default build context location
|
|
27
|
+
rmSync(join(process.cwd(), ".docker-staging"), {
|
|
28
|
+
recursive: true,
|
|
29
|
+
force: true,
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe("buildImage", () => {
|
|
33
|
+
it("builds a plain image without template", async () => {
|
|
34
|
+
await buildImage({
|
|
35
|
+
name: "myorg/sandagent",
|
|
36
|
+
tag: "0.1.0",
|
|
37
|
+
platform: "linux/amd64",
|
|
38
|
+
push: false,
|
|
39
|
+
});
|
|
40
|
+
// Should have called docker info + docker build
|
|
41
|
+
const calls = mockedExecSync.mock.calls.map((c) => c[0]);
|
|
42
|
+
expect(calls.some((c) => c === "docker info")).toBe(true);
|
|
43
|
+
expect(calls.some((c) => c.includes("docker build"))).toBe(true);
|
|
44
|
+
// docker build should reference the correct image name
|
|
45
|
+
const buildCmd = calls.find((c) => c.includes("docker build"));
|
|
46
|
+
expect(buildCmd).toContain("-t myorg/sandagent:0.1.0");
|
|
47
|
+
expect(buildCmd).toContain("--platform=linux/amd64");
|
|
48
|
+
// Should NOT have called docker push
|
|
49
|
+
expect(calls.some((c) => c.includes("docker push"))).toBe(false);
|
|
50
|
+
});
|
|
51
|
+
it("generates Dockerfile in build context", async () => {
|
|
52
|
+
await buildImage({
|
|
53
|
+
name: "myorg/sandagent",
|
|
54
|
+
tag: "1.0.0",
|
|
55
|
+
platform: "linux/amd64",
|
|
56
|
+
push: false,
|
|
57
|
+
});
|
|
58
|
+
const contextDir = join(process.cwd(), ".docker-staging");
|
|
59
|
+
const dockerfilePath = join(contextDir, "Dockerfile");
|
|
60
|
+
expect(existsSync(dockerfilePath)).toBe(true);
|
|
61
|
+
const content = readFileSync(dockerfilePath, "utf8");
|
|
62
|
+
expect(content).toContain("FROM node:20-slim");
|
|
63
|
+
expect(content).toContain("@sandagent/runner-cli");
|
|
64
|
+
expect(content).toContain('CMD ["sleep", "infinity"]');
|
|
65
|
+
});
|
|
66
|
+
it("uses --image override when provided", async () => {
|
|
67
|
+
await buildImage({
|
|
68
|
+
name: "sandagent",
|
|
69
|
+
tag: "latest",
|
|
70
|
+
image: "custom/image:v2",
|
|
71
|
+
platform: "linux/amd64",
|
|
72
|
+
push: false,
|
|
73
|
+
});
|
|
74
|
+
const calls = mockedExecSync.mock.calls.map((c) => c[0]);
|
|
75
|
+
const buildCmd = calls.find((c) => c.includes("docker build"));
|
|
76
|
+
expect(buildCmd).toContain("-t custom/image:v2");
|
|
77
|
+
});
|
|
78
|
+
it("builds with template and injects COPY instructions", async () => {
|
|
79
|
+
// Create a fake template directory
|
|
80
|
+
const templateDir = join(TEST_DIR, "my-agent");
|
|
81
|
+
mkdirSync(templateDir, { recursive: true });
|
|
82
|
+
writeFileSync(join(templateDir, "CLAUDE.md"), "# My Agent");
|
|
83
|
+
const claudeDir = join(templateDir, ".claude");
|
|
84
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
85
|
+
writeFileSync(join(claudeDir, "settings.json"), '{"max_tokens": 4096}');
|
|
86
|
+
await buildImage({
|
|
87
|
+
name: "myorg/sandagent",
|
|
88
|
+
tag: "0.1.0",
|
|
89
|
+
platform: "linux/amd64",
|
|
90
|
+
template: templateDir,
|
|
91
|
+
push: false,
|
|
92
|
+
});
|
|
93
|
+
// Image name should include template name
|
|
94
|
+
const calls = mockedExecSync.mock.calls.map((c) => c[0]);
|
|
95
|
+
const buildCmd = calls.find((c) => c.includes("docker build"));
|
|
96
|
+
expect(buildCmd).toContain("-t myorg/sandagent:0.1.0");
|
|
97
|
+
// Generated Dockerfile should have template COPY lines
|
|
98
|
+
const contextDir = join(process.cwd(), ".docker-staging");
|
|
99
|
+
const dockerfile = readFileSync(join(contextDir, "Dockerfile"), "utf8");
|
|
100
|
+
expect(dockerfile).toContain("COPY templates/my-agent/CLAUDE.md");
|
|
101
|
+
expect(dockerfile).toContain("COPY templates/my-agent/.claude");
|
|
102
|
+
expect(dockerfile).toContain("mkdir -p /opt/sandagent/templates");
|
|
103
|
+
// Template files should be copied into build context
|
|
104
|
+
expect(existsSync(join(contextDir, "templates", "my-agent", "CLAUDE.md"))).toBe(true);
|
|
105
|
+
expect(existsSync(join(contextDir, "templates", "my-agent", ".claude", "settings.json"))).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
it("pushes when --push is set", async () => {
|
|
108
|
+
await buildImage({
|
|
109
|
+
name: "myorg/sandagent",
|
|
110
|
+
tag: "0.1.0",
|
|
111
|
+
platform: "linux/amd64",
|
|
112
|
+
push: true,
|
|
113
|
+
});
|
|
114
|
+
const calls = mockedExecSync.mock.calls.map((c) => c[0]);
|
|
115
|
+
expect(calls.some((c) => c.includes("docker push"))).toBe(true);
|
|
116
|
+
expect(calls.some((c) => c.includes("docker push myorg/sandagent:0.1.0"))).toBe(true);
|
|
117
|
+
});
|
|
118
|
+
it("fails push when name has no namespace", async () => {
|
|
119
|
+
const mockExit = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
120
|
+
throw new Error("process.exit");
|
|
121
|
+
});
|
|
122
|
+
const mockError = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
123
|
+
await expect(buildImage({
|
|
124
|
+
name: "sandagent",
|
|
125
|
+
tag: "0.1.0",
|
|
126
|
+
platform: "linux/amd64",
|
|
127
|
+
push: true,
|
|
128
|
+
})).rejects.toThrow("process.exit");
|
|
129
|
+
expect(mockError).toHaveBeenCalledWith(expect.stringContaining("--push requires --name to include namespace"));
|
|
130
|
+
mockExit.mockRestore();
|
|
131
|
+
mockError.mockRestore();
|
|
132
|
+
});
|
|
133
|
+
it("does not push when --push is false", async () => {
|
|
134
|
+
await buildImage({
|
|
135
|
+
name: "myorg/sandagent",
|
|
136
|
+
tag: "0.1.0",
|
|
137
|
+
platform: "linux/amd64",
|
|
138
|
+
push: false,
|
|
139
|
+
});
|
|
140
|
+
const calls = mockedExecSync.mock.calls.map((c) => c[0]);
|
|
141
|
+
expect(calls.some((c) => c.includes("docker push"))).toBe(false);
|
|
142
|
+
expect(calls.some((c) => c.includes("docker tag"))).toBe(false);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
//# sourceMappingURL=build-image.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-image.test.js","sourceRoot":"","sources":["../../src/__tests__/build-image.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,9 +9,16 @@ import { describe, expect, it } from "vitest";
|
|
|
9
9
|
const CLI_PATH = join(process.cwd(), "dist/bundle.mjs");
|
|
10
10
|
describe("runner-cli Integration Tests", () => {
|
|
11
11
|
const TIMEOUT = 10000;
|
|
12
|
-
it("should display help
|
|
12
|
+
it("should display top-level help", async () => {
|
|
13
13
|
const output = await runCLI(["--help"]);
|
|
14
14
|
expect(output.stdout).toContain("SandAgent Runner CLI");
|
|
15
|
+
expect(output.stdout).toContain("run");
|
|
16
|
+
expect(output.stdout).toContain("image build");
|
|
17
|
+
expect(output.exitCode).toBe(0);
|
|
18
|
+
}, TIMEOUT);
|
|
19
|
+
it("should display run command options in run --help", async () => {
|
|
20
|
+
const output = await runCLI(["run", "--help"]);
|
|
21
|
+
expect(output.stdout).toContain("SandAgent Runner CLI");
|
|
15
22
|
expect(output.stdout).toContain("--runner");
|
|
16
23
|
expect(output.stdout).toContain("--model");
|
|
17
24
|
expect(output.exitCode).toBe(0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-cli.integration.test.js","sourceRoot":"","sources":["../../src/__tests__/runner-cli.integration.test.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,2DAA2D;AAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,iBAAiB,CAAC,CAAC;AAExD,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,MAAM,OAAO,GAAG,KAAK,CAAC;IAEtB,EAAE,CACA,
|
|
1
|
+
{"version":3,"file":"runner-cli.integration.test.js","sourceRoot":"","sources":["../../src/__tests__/runner-cli.integration.test.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,2DAA2D;AAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,iBAAiB,CAAC,CAAC;AAExD,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,MAAM,OAAO,GAAG,KAAK,CAAC;IAEtB,EAAE,CACA,+BAA+B,EAC/B,KAAK,IAAI,EAAE;QACT,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAExC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QACxD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,EACD,OAAO,CACR,CAAC;IAEF,EAAE,CACA,kDAAkD,EAClD,KAAK,IAAI,EAAE;QACT,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;QAE/C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QACxD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,EACD,OAAO,CACR,CAAC;IAEF,EAAE,CACA,+CAA+C,EAC/C,KAAK,IAAI,EAAE;QACT,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAErC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,EACD,OAAO,CACR,CAAC;IAEF,EAAE,CACA,sCAAsC,EACtC,KAAK,IAAI,EAAE;QACT,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC;YAC1B,KAAK;YACL,UAAU;YACV,SAAS;YACT,IAAI;YACJ,WAAW;SACZ,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,EACD,OAAO,CACR,CAAC;IAEF,EAAE,CACA,oCAAoC,EACpC,KAAK,IAAI,EAAE;QACT,uEAAuE;QACvE,MAAM,MAAM,GAAG,MAAM,MAAM,CACzB,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,CAAC,EACjD;YACE,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,iBAAiB,EAAE,EAAE,EAAE;SAC/C,CACF,CAAC;QAEF,2DAA2D;QAC3D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;IACvD,CAAC,EACD,OAAO,CACR,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH;;GAEG;AACH,SAAS,MAAM,CACb,IAAc,EACd,UAA4C,EAAE;IAE9C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE;YAC9C,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG;YAC/B,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAC/B,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAC/B,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,OAAO,CAAC;gBACN,MAAM;gBACN,MAAM;gBACN,QAAQ,EAAE,IAAI,IAAI,CAAC;aACpB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAEzB,UAAU;QACV,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACzC,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface BuildImageOptions {
|
|
2
|
+
/** Image name, e.g. "vikadata/sandagent-seo" */
|
|
3
|
+
name: string;
|
|
4
|
+
/** Image tag, e.g. "0.1.0" */
|
|
5
|
+
tag: string;
|
|
6
|
+
/** Full image override, e.g. "myorg/myimage:v1" */
|
|
7
|
+
image?: string;
|
|
8
|
+
/** Docker platform (default: linux/amd64) */
|
|
9
|
+
platform: string;
|
|
10
|
+
/** Path to agent template directory to bake into the image */
|
|
11
|
+
template?: string;
|
|
12
|
+
/** Push image to registry after build */
|
|
13
|
+
push: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function buildImage(opts: BuildImageOptions): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=build-image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-image.d.ts","sourceRoot":"","sources":["../src/build-image.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,iBAAiB;IAChC,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,IAAI,EAAE,OAAO,CAAC;CACf;AA2ED,wBAAsB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiEvE"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Helpers
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
function getPackageRoot() {
|
|
9
|
+
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
return resolve(thisDir, "..");
|
|
11
|
+
}
|
|
12
|
+
function getShippedDockerfile() {
|
|
13
|
+
// Look for Dockerfile in several locations:
|
|
14
|
+
// 1. Package root (apps/runner-cli/Dockerfile) ā shipped with npm package
|
|
15
|
+
// 2. docker/sandagent-claude/Dockerfile ā monorepo development
|
|
16
|
+
const packageRoot = getPackageRoot();
|
|
17
|
+
const candidates = [
|
|
18
|
+
join(packageRoot, "Dockerfile"),
|
|
19
|
+
resolve(packageRoot, "..", "..", "docker", "sandagent-claude", "Dockerfile"),
|
|
20
|
+
];
|
|
21
|
+
for (const p of candidates) {
|
|
22
|
+
if (existsSync(p))
|
|
23
|
+
return p;
|
|
24
|
+
}
|
|
25
|
+
console.error(`ā Dockerfile not found. Searched:\n${candidates.map((c) => ` ${c}`).join("\n")}`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
function run(cmd, cwd) {
|
|
29
|
+
execSync(cmd, { stdio: "inherit", cwd });
|
|
30
|
+
}
|
|
31
|
+
function ensureDocker() {
|
|
32
|
+
try {
|
|
33
|
+
execSync("docker info", { stdio: "ignore" });
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
console.error("ā Docker is not running. Please start Docker first.");
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function resolveTemplatePath(template) {
|
|
41
|
+
const abs = resolve(process.cwd(), template);
|
|
42
|
+
if (!existsSync(abs)) {
|
|
43
|
+
console.error(`ā Template directory not found: ${abs}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
return abs;
|
|
47
|
+
}
|
|
48
|
+
function copyDirSync(src, dest) {
|
|
49
|
+
mkdirSync(dest, { recursive: true });
|
|
50
|
+
for (const entry of readdirSync(src)) {
|
|
51
|
+
const srcPath = join(src, entry);
|
|
52
|
+
const destPath = join(dest, entry);
|
|
53
|
+
if (statSync(srcPath).isDirectory()) {
|
|
54
|
+
copyDirSync(srcPath, destPath);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
copyFileSync(srcPath, destPath);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Build (and optionally push)
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
export async function buildImage(opts) {
|
|
65
|
+
const templatePath = opts.template
|
|
66
|
+
? resolveTemplatePath(opts.template)
|
|
67
|
+
: null;
|
|
68
|
+
const templateName = templatePath ? basename(templatePath) : null;
|
|
69
|
+
const localImage = opts.image ?? `${opts.name}:${opts.tag}`;
|
|
70
|
+
console.log("š¦ SandAgent Docker Image Builder");
|
|
71
|
+
console.log("========================");
|
|
72
|
+
console.log(` Image: ${localImage}`);
|
|
73
|
+
console.log(` Platform: ${opts.platform}`);
|
|
74
|
+
console.log(` Template: ${templateName ?? "(none)"}`);
|
|
75
|
+
console.log(` Push: ${opts.push}`);
|
|
76
|
+
console.log("");
|
|
77
|
+
ensureDocker();
|
|
78
|
+
const buildContext = join(process.cwd(), ".docker-staging");
|
|
79
|
+
mkdirSync(buildContext, { recursive: true });
|
|
80
|
+
let dockerfile = readFileSync(getShippedDockerfile(), "utf8");
|
|
81
|
+
if (templatePath && templateName) {
|
|
82
|
+
const destDir = join(buildContext, "templates", templateName);
|
|
83
|
+
mkdirSync(destDir, { recursive: true });
|
|
84
|
+
const claudeMd = join(templatePath, "CLAUDE.md");
|
|
85
|
+
if (existsSync(claudeMd))
|
|
86
|
+
copyFileSync(claudeMd, join(destDir, "CLAUDE.md"));
|
|
87
|
+
const claudeDir = join(templatePath, ".claude");
|
|
88
|
+
if (existsSync(claudeDir))
|
|
89
|
+
copyDirSync(claudeDir, join(destDir, ".claude"));
|
|
90
|
+
let copyLines = "\n# Template files\nRUN mkdir -p /opt/sandagent/templates";
|
|
91
|
+
if (existsSync(join(destDir, "CLAUDE.md"))) {
|
|
92
|
+
copyLines += `\nCOPY templates/${templateName}/CLAUDE.md /opt/sandagent/templates/CLAUDE.md`;
|
|
93
|
+
}
|
|
94
|
+
if (existsSync(join(destDir, ".claude"))) {
|
|
95
|
+
copyLines += `\nCOPY templates/${templateName}/.claude /opt/sandagent/templates/.claude`;
|
|
96
|
+
}
|
|
97
|
+
dockerfile = dockerfile.replace(/^CMD /m, `${copyLines}\n\nCMD `);
|
|
98
|
+
console.log("š§© Injected template files into Dockerfile");
|
|
99
|
+
}
|
|
100
|
+
writeFileSync(join(buildContext, "Dockerfile"), dockerfile);
|
|
101
|
+
console.log("š³ Building Docker image...");
|
|
102
|
+
run(`docker build --platform=${opts.platform} -t ${localImage} -f ${join(buildContext, "Dockerfile")} ${buildContext}`);
|
|
103
|
+
console.log(`\nā
Image built: ${localImage}`);
|
|
104
|
+
if (!opts.push)
|
|
105
|
+
return;
|
|
106
|
+
if (!localImage.includes("/")) {
|
|
107
|
+
console.error("ā --push requires --name to include namespace (e.g. vikadata/sandagent-seo)");
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
console.log("š Pushing image...");
|
|
111
|
+
run(`docker push ${localImage}`);
|
|
112
|
+
console.log(`\nā
Image pushed: ${localImage}`);
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=build-image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-image.js","sourceRoot":"","sources":["../src/build-image.ts"],"names":[],"mappings":"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"}
|