@sandagent/runner-cli 0.2.9 → 0.2.10
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 +26 -0
- 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/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
|
@@ -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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"}
|
|
@@ -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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"}
|
package/dist/bundle.mjs
CHANGED
|
@@ -3,9 +3,136 @@
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { parseArgs } from "node:util";
|
|
5
5
|
|
|
6
|
+
// src/build-image.ts
|
|
7
|
+
import { execSync } from "node:child_process";
|
|
8
|
+
import {
|
|
9
|
+
copyFileSync,
|
|
10
|
+
existsSync,
|
|
11
|
+
mkdirSync,
|
|
12
|
+
readFileSync,
|
|
13
|
+
readdirSync,
|
|
14
|
+
statSync,
|
|
15
|
+
writeFileSync
|
|
16
|
+
} from "node:fs";
|
|
17
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
18
|
+
import { fileURLToPath } from "node:url";
|
|
19
|
+
function getPackageRoot() {
|
|
20
|
+
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
return resolve(thisDir, "..");
|
|
22
|
+
}
|
|
23
|
+
function getShippedDockerfile() {
|
|
24
|
+
const packageRoot = getPackageRoot();
|
|
25
|
+
const candidates = [
|
|
26
|
+
join(packageRoot, "Dockerfile"),
|
|
27
|
+
resolve(
|
|
28
|
+
packageRoot,
|
|
29
|
+
"..",
|
|
30
|
+
"..",
|
|
31
|
+
"docker",
|
|
32
|
+
"sandagent-claude",
|
|
33
|
+
"Dockerfile"
|
|
34
|
+
)
|
|
35
|
+
];
|
|
36
|
+
for (const p of candidates) {
|
|
37
|
+
if (existsSync(p)) return p;
|
|
38
|
+
}
|
|
39
|
+
console.error(
|
|
40
|
+
`\u274C Dockerfile not found. Searched:
|
|
41
|
+
${candidates.map((c) => ` ${c}`).join("\n")}`
|
|
42
|
+
);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
function run(cmd, cwd) {
|
|
46
|
+
execSync(cmd, { stdio: "inherit", cwd });
|
|
47
|
+
}
|
|
48
|
+
function ensureDocker() {
|
|
49
|
+
try {
|
|
50
|
+
execSync("docker info", { stdio: "ignore" });
|
|
51
|
+
} catch {
|
|
52
|
+
console.error("\u274C Docker is not running. Please start Docker first.");
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function resolveTemplatePath(template) {
|
|
57
|
+
const abs = resolve(process.cwd(), template);
|
|
58
|
+
if (!existsSync(abs)) {
|
|
59
|
+
console.error(`\u274C Template directory not found: ${abs}`);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
return abs;
|
|
63
|
+
}
|
|
64
|
+
function copyDirSync(src, dest) {
|
|
65
|
+
mkdirSync(dest, { recursive: true });
|
|
66
|
+
for (const entry of readdirSync(src)) {
|
|
67
|
+
const srcPath = join(src, entry);
|
|
68
|
+
const destPath = join(dest, entry);
|
|
69
|
+
if (statSync(srcPath).isDirectory()) {
|
|
70
|
+
copyDirSync(srcPath, destPath);
|
|
71
|
+
} else {
|
|
72
|
+
copyFileSync(srcPath, destPath);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function buildImage(opts) {
|
|
77
|
+
const templatePath = opts.template ? resolveTemplatePath(opts.template) : null;
|
|
78
|
+
const templateName = templatePath ? basename(templatePath) : null;
|
|
79
|
+
const localImage = opts.image ?? `${opts.name}:${opts.tag}`;
|
|
80
|
+
console.log("\u{1F4E6} SandAgent Docker Image Builder");
|
|
81
|
+
console.log("========================");
|
|
82
|
+
console.log(` Image: ${localImage}`);
|
|
83
|
+
console.log(` Platform: ${opts.platform}`);
|
|
84
|
+
console.log(` Template: ${templateName ?? "(none)"}`);
|
|
85
|
+
console.log(` Push: ${opts.push}`);
|
|
86
|
+
console.log("");
|
|
87
|
+
ensureDocker();
|
|
88
|
+
const buildContext = join(process.cwd(), ".docker-staging");
|
|
89
|
+
mkdirSync(buildContext, { recursive: true });
|
|
90
|
+
let dockerfile = readFileSync(getShippedDockerfile(), "utf8");
|
|
91
|
+
if (templatePath && templateName) {
|
|
92
|
+
const destDir = join(buildContext, "templates", templateName);
|
|
93
|
+
mkdirSync(destDir, { recursive: true });
|
|
94
|
+
const claudeMd = join(templatePath, "CLAUDE.md");
|
|
95
|
+
if (existsSync(claudeMd))
|
|
96
|
+
copyFileSync(claudeMd, join(destDir, "CLAUDE.md"));
|
|
97
|
+
const claudeDir = join(templatePath, ".claude");
|
|
98
|
+
if (existsSync(claudeDir)) copyDirSync(claudeDir, join(destDir, ".claude"));
|
|
99
|
+
let copyLines = "\n# Template files\nRUN mkdir -p /opt/sandagent/templates";
|
|
100
|
+
if (existsSync(join(destDir, "CLAUDE.md"))) {
|
|
101
|
+
copyLines += `
|
|
102
|
+
COPY templates/${templateName}/CLAUDE.md /opt/sandagent/templates/CLAUDE.md`;
|
|
103
|
+
}
|
|
104
|
+
if (existsSync(join(destDir, ".claude"))) {
|
|
105
|
+
copyLines += `
|
|
106
|
+
COPY templates/${templateName}/.claude /opt/sandagent/templates/.claude`;
|
|
107
|
+
}
|
|
108
|
+
dockerfile = dockerfile.replace(/^CMD /m, `${copyLines}
|
|
109
|
+
|
|
110
|
+
CMD `);
|
|
111
|
+
console.log("\u{1F9E9} Injected template files into Dockerfile");
|
|
112
|
+
}
|
|
113
|
+
writeFileSync(join(buildContext, "Dockerfile"), dockerfile);
|
|
114
|
+
console.log("\u{1F433} Building Docker image...");
|
|
115
|
+
run(
|
|
116
|
+
`docker build --platform=${opts.platform} -t ${localImage} -f ${join(buildContext, "Dockerfile")} ${buildContext}`
|
|
117
|
+
);
|
|
118
|
+
console.log(`
|
|
119
|
+
\u2705 Image built: ${localImage}`);
|
|
120
|
+
if (!opts.push) return;
|
|
121
|
+
if (!localImage.includes("/")) {
|
|
122
|
+
console.error(
|
|
123
|
+
"\u274C --push requires --name to include namespace (e.g. vikadata/sandagent-seo)"
|
|
124
|
+
);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
console.log("\u{1F680} Pushing image...");
|
|
128
|
+
run(`docker push ${localImage}`);
|
|
129
|
+
console.log(`
|
|
130
|
+
\u2705 Image pushed: ${localImage}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
6
133
|
// ../../packages/runner-claude/dist/ai-sdk-stream.js
|
|
7
134
|
import { writeFile } from "node:fs/promises";
|
|
8
|
-
import { join } from "node:path";
|
|
135
|
+
import { join as join2 } from "node:path";
|
|
9
136
|
var UNKNOWN_TOOL_NAME = "unknown-tool";
|
|
10
137
|
function formatDataStream(data) {
|
|
11
138
|
return `data: ${JSON.stringify(data)}
|
|
@@ -233,7 +360,7 @@ var AISDKStreamConverter = class {
|
|
|
233
360
|
} finally {
|
|
234
361
|
if (debugMessages.length > 0 && process.env.DEBUG === "true") {
|
|
235
362
|
const debugDir = options?.cwd ?? process.cwd();
|
|
236
|
-
const debugFile =
|
|
363
|
+
const debugFile = join2(debugDir, `claude-message-stream-debug.json`);
|
|
237
364
|
writeFile(debugFile, JSON.stringify(debugMessages, null, 2), "utf-8").catch((writeError) => {
|
|
238
365
|
console.error(`[AISDKStream] Failed to write debug file:`, writeError);
|
|
239
366
|
});
|
|
@@ -286,7 +413,7 @@ function createCanUseToolCallback(claudeOptions) {
|
|
|
286
413
|
}
|
|
287
414
|
} catch {
|
|
288
415
|
}
|
|
289
|
-
await new Promise((
|
|
416
|
+
await new Promise((resolve2) => setTimeout(resolve2, 500));
|
|
290
417
|
}
|
|
291
418
|
try {
|
|
292
419
|
fs.unlinkSync(approvalFile);
|
|
@@ -506,7 +633,7 @@ Documentation: https://platform.claude.com/docs/en/agent-sdk/typescript-v2-previ
|
|
|
506
633
|
id: textId,
|
|
507
634
|
delta: word + " "
|
|
508
635
|
});
|
|
509
|
-
await new Promise((
|
|
636
|
+
await new Promise((resolve2) => setTimeout(resolve2, 20));
|
|
510
637
|
}
|
|
511
638
|
yield formatDataStream({ type: "text-end", id: textId });
|
|
512
639
|
yield formatDataStream({
|
|
@@ -594,14 +721,41 @@ async function runAgent(options) {
|
|
|
594
721
|
}
|
|
595
722
|
|
|
596
723
|
// src/cli.ts
|
|
597
|
-
function
|
|
724
|
+
function getSubcommand() {
|
|
725
|
+
for (let i = 2; i < process.argv.length; i++) {
|
|
726
|
+
const a = process.argv[i];
|
|
727
|
+
if (a === "--") break;
|
|
728
|
+
if (!a.startsWith("-")) return a;
|
|
729
|
+
}
|
|
730
|
+
return void 0;
|
|
731
|
+
}
|
|
732
|
+
function getSubSubcommand() {
|
|
733
|
+
let found = 0;
|
|
734
|
+
for (let i = 2; i < process.argv.length; i++) {
|
|
735
|
+
const a = process.argv[i];
|
|
736
|
+
if (a === "--") break;
|
|
737
|
+
if (!a.startsWith("-")) {
|
|
738
|
+
found++;
|
|
739
|
+
if (found === 2) return a;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
return void 0;
|
|
743
|
+
}
|
|
744
|
+
function argsAfterPositionals(n) {
|
|
745
|
+
let found = 0;
|
|
746
|
+
for (let i = 2; i < process.argv.length; i++) {
|
|
747
|
+
if (!process.argv[i].startsWith("-") && process.argv[i] !== "--") {
|
|
748
|
+
found++;
|
|
749
|
+
if (found === n) return process.argv.slice(i + 1);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
return [];
|
|
753
|
+
}
|
|
754
|
+
function parseRunArgs() {
|
|
598
755
|
const { values, positionals } = parseArgs({
|
|
756
|
+
args: argsAfterPositionals(1),
|
|
599
757
|
options: {
|
|
600
|
-
runner: {
|
|
601
|
-
type: "string",
|
|
602
|
-
short: "r",
|
|
603
|
-
default: "claude"
|
|
604
|
-
},
|
|
758
|
+
runner: { type: "string", short: "r", default: "claude" },
|
|
605
759
|
model: {
|
|
606
760
|
type: "string",
|
|
607
761
|
short: "m",
|
|
@@ -612,49 +766,26 @@ function parseCliArgs() {
|
|
|
612
766
|
short: "c",
|
|
613
767
|
default: process.env.SANDAGENT_WORKSPACE ?? process.cwd()
|
|
614
768
|
},
|
|
615
|
-
"system-prompt": {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
},
|
|
619
|
-
"
|
|
620
|
-
|
|
621
|
-
short: "t"
|
|
622
|
-
},
|
|
623
|
-
"allowed-tools": {
|
|
624
|
-
type: "string",
|
|
625
|
-
short: "a"
|
|
626
|
-
},
|
|
627
|
-
resume: {
|
|
628
|
-
type: "string",
|
|
629
|
-
short: "r"
|
|
630
|
-
},
|
|
631
|
-
"output-format": {
|
|
632
|
-
type: "string",
|
|
633
|
-
short: "o"
|
|
634
|
-
},
|
|
635
|
-
help: {
|
|
636
|
-
type: "boolean",
|
|
637
|
-
short: "h"
|
|
638
|
-
}
|
|
769
|
+
"system-prompt": { type: "string", short: "s" },
|
|
770
|
+
"max-turns": { type: "string", short: "t" },
|
|
771
|
+
"allowed-tools": { type: "string", short: "a" },
|
|
772
|
+
resume: { type: "string" },
|
|
773
|
+
"output-format": { type: "string", short: "o" },
|
|
774
|
+
help: { type: "boolean", short: "h" }
|
|
639
775
|
},
|
|
640
776
|
allowPositionals: true,
|
|
641
777
|
strict: true
|
|
642
778
|
});
|
|
643
779
|
if (values.help) {
|
|
644
|
-
|
|
780
|
+
printRunHelp();
|
|
645
781
|
process.exit(0);
|
|
646
782
|
}
|
|
647
|
-
if (positionals[0] !== "run") {
|
|
648
|
-
console.error('Error: Expected "run" command');
|
|
649
|
-
console.error('Usage: sandagent run [options] -- "<user input>"');
|
|
650
|
-
process.exit(1);
|
|
651
|
-
}
|
|
652
783
|
const dashIndex = process.argv.indexOf("--");
|
|
653
784
|
let userInput = "";
|
|
654
785
|
if (dashIndex !== -1 && dashIndex < process.argv.length - 1) {
|
|
655
786
|
userInput = process.argv.slice(dashIndex + 1).join(" ");
|
|
656
|
-
} else if (positionals.length >
|
|
657
|
-
userInput = positionals.
|
|
787
|
+
} else if (positionals.length > 0) {
|
|
788
|
+
userInput = positionals.join(" ");
|
|
658
789
|
}
|
|
659
790
|
if (!userInput) {
|
|
660
791
|
console.error("Error: User input is required");
|
|
@@ -687,57 +818,156 @@ function parseCliArgs() {
|
|
|
687
818
|
userInput
|
|
688
819
|
};
|
|
689
820
|
}
|
|
690
|
-
function
|
|
821
|
+
function parseImageBuildArgs() {
|
|
822
|
+
const { values } = parseArgs({
|
|
823
|
+
args: argsAfterPositionals(2),
|
|
824
|
+
options: {
|
|
825
|
+
name: { type: "string", default: "sandagent" },
|
|
826
|
+
tag: { type: "string", default: "latest" },
|
|
827
|
+
image: { type: "string" },
|
|
828
|
+
platform: { type: "string", default: "linux/amd64" },
|
|
829
|
+
template: { type: "string" },
|
|
830
|
+
push: { type: "boolean", default: false },
|
|
831
|
+
help: { type: "boolean", short: "h" }
|
|
832
|
+
},
|
|
833
|
+
allowPositionals: false,
|
|
834
|
+
strict: true
|
|
835
|
+
});
|
|
836
|
+
if (values.help) {
|
|
837
|
+
printImageBuildHelp();
|
|
838
|
+
process.exit(0);
|
|
839
|
+
}
|
|
840
|
+
return {
|
|
841
|
+
name: values.name,
|
|
842
|
+
tag: values.tag,
|
|
843
|
+
image: values.image,
|
|
844
|
+
platform: values.platform,
|
|
845
|
+
template: values.template,
|
|
846
|
+
push: values.push ?? false
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
function printRunHelp() {
|
|
691
850
|
console.log(`
|
|
692
|
-
\u{1F916} SandAgent Runner CLI
|
|
851
|
+
\u{1F916} SandAgent Runner CLI \u2014 run
|
|
693
852
|
|
|
694
|
-
|
|
695
|
-
Streams AI SDK UI messages directly to stdout.
|
|
853
|
+
Runs an agent locally in your terminal, streaming AI SDK UI messages to stdout.
|
|
696
854
|
|
|
697
855
|
Usage:
|
|
698
856
|
sandagent run [options] -- "<user input>"
|
|
699
857
|
|
|
700
858
|
Options:
|
|
701
|
-
-r, --runner <runner> Runner
|
|
702
|
-
-m, --model <model> Model
|
|
703
|
-
-c, --cwd <path> Working directory (default:
|
|
859
|
+
-r, --runner <runner> Runner: claude, codex, copilot (default: claude)
|
|
860
|
+
-m, --model <model> Model (default: claude-sonnet-4-20250514)
|
|
861
|
+
-c, --cwd <path> Working directory (default: cwd)
|
|
704
862
|
-s, --system-prompt <prompt> Custom system prompt
|
|
705
|
-
-t, --max-turns <n>
|
|
706
|
-
-a, --allowed-tools <tools> Comma-separated
|
|
707
|
-
|
|
708
|
-
-o, --output-format <
|
|
709
|
-
|
|
710
|
-
|
|
863
|
+
-t, --max-turns <n> Max conversation turns
|
|
864
|
+
-a, --allowed-tools <tools> Comma-separated allowed tools
|
|
865
|
+
--resume <session-id> Resume a previous session
|
|
866
|
+
-o, --output-format <fmt> text | json | stream-json | stream (default: stream)
|
|
867
|
+
-h, --help Show this help
|
|
868
|
+
|
|
869
|
+
Environment:
|
|
870
|
+
ANTHROPIC_API_KEY Anthropic API key (required)
|
|
871
|
+
SANDAGENT_WORKSPACE Default workspace path
|
|
872
|
+
`);
|
|
873
|
+
}
|
|
874
|
+
function printImageBuildHelp() {
|
|
875
|
+
console.log(`
|
|
876
|
+
\u{1F433} SandAgent Runner CLI \u2014 image build
|
|
877
|
+
|
|
878
|
+
Build (and optionally push) a SandAgent Docker image.
|
|
879
|
+
The image includes Claude Agent SDK + runner-cli pre-installed.
|
|
711
880
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
881
|
+
Usage:
|
|
882
|
+
sandagent image build [options]
|
|
883
|
+
|
|
884
|
+
Options:
|
|
885
|
+
--name <name> Image name, e.g. vikadata/sandagent-seo (default: sandagent)
|
|
886
|
+
--tag <tag> Image tag (default: latest)
|
|
887
|
+
--image <full> Full image name override (e.g. myorg/myimage:v1)
|
|
888
|
+
--platform <plat> Build platform (default: linux/amd64)
|
|
889
|
+
--template <path> Path to agent template directory to bake into the image
|
|
890
|
+
--push Push image to registry after build
|
|
891
|
+
-h, --help Show this help
|
|
716
892
|
|
|
717
893
|
Examples:
|
|
718
|
-
|
|
719
|
-
sandagent
|
|
894
|
+
sandagent image build --name vikadata/sandagent-seo --tag 0.1.0
|
|
895
|
+
sandagent image build --name vikadata/sandagent-seo --tag 0.1.0 --template ./templates/seo-agent
|
|
896
|
+
sandagent image build --name vikadata/sandagent-seo --tag 0.1.0 --template ./templates/seo-agent --push
|
|
897
|
+
`);
|
|
898
|
+
}
|
|
899
|
+
function printImageHelp() {
|
|
900
|
+
console.log(`
|
|
901
|
+
\u{1F433} SandAgent Runner CLI \u2014 image
|
|
720
902
|
|
|
721
|
-
|
|
722
|
-
sandagent run --system-prompt "You are a coding assistant" -- "Build a REST API with Express"
|
|
903
|
+
Manage SandAgent Docker images.
|
|
723
904
|
|
|
724
|
-
|
|
725
|
-
sandagent
|
|
905
|
+
Usage:
|
|
906
|
+
sandagent image <subcommand> [options]
|
|
907
|
+
|
|
908
|
+
Subcommands:
|
|
909
|
+
build Build (and optionally push) a Docker image
|
|
910
|
+
|
|
911
|
+
Run "sandagent image build --help" for build options.
|
|
912
|
+
`);
|
|
913
|
+
}
|
|
914
|
+
function printGlobalHelp() {
|
|
915
|
+
console.log(`
|
|
916
|
+
\u{1F916} SandAgent Runner CLI
|
|
917
|
+
|
|
918
|
+
Usage:
|
|
919
|
+
sandagent <command> [options]
|
|
920
|
+
|
|
921
|
+
Commands:
|
|
922
|
+
run Run an agent locally (streams AI SDK UI messages to stdout)
|
|
923
|
+
image build Build a SandAgent Docker image (with optional --push)
|
|
924
|
+
|
|
925
|
+
Run "sandagent <command> --help" for command-specific options.
|
|
726
926
|
`);
|
|
727
927
|
}
|
|
728
928
|
async function main() {
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
929
|
+
const sub = getSubcommand();
|
|
930
|
+
if (!sub || sub === "--help" || sub === "-h") {
|
|
931
|
+
printGlobalHelp();
|
|
932
|
+
process.exit(0);
|
|
933
|
+
}
|
|
934
|
+
switch (sub) {
|
|
935
|
+
case "run": {
|
|
936
|
+
const args = parseRunArgs();
|
|
937
|
+
process.chdir(args.cwd);
|
|
938
|
+
await runAgent({
|
|
939
|
+
runner: args.runner,
|
|
940
|
+
model: args.model,
|
|
941
|
+
userInput: args.userInput,
|
|
942
|
+
systemPrompt: args.systemPrompt,
|
|
943
|
+
maxTurns: args.maxTurns,
|
|
944
|
+
allowedTools: args.allowedTools,
|
|
945
|
+
resume: args.resume,
|
|
946
|
+
outputFormat: args.outputFormat
|
|
947
|
+
});
|
|
948
|
+
break;
|
|
949
|
+
}
|
|
950
|
+
case "image": {
|
|
951
|
+
const subSub = getSubSubcommand();
|
|
952
|
+
if (!subSub || subSub === "--help" || subSub === "-h") {
|
|
953
|
+
printImageHelp();
|
|
954
|
+
process.exit(0);
|
|
955
|
+
}
|
|
956
|
+
if (subSub === "build") {
|
|
957
|
+
const args = parseImageBuildArgs();
|
|
958
|
+
await buildImage(args);
|
|
959
|
+
} else {
|
|
960
|
+
console.error(`Unknown image subcommand: ${subSub}`);
|
|
961
|
+
printImageHelp();
|
|
962
|
+
process.exit(1);
|
|
963
|
+
}
|
|
964
|
+
break;
|
|
965
|
+
}
|
|
966
|
+
default:
|
|
967
|
+
console.error(`Unknown command: ${sub}`);
|
|
968
|
+
printGlobalHelp();
|
|
969
|
+
process.exit(1);
|
|
970
|
+
}
|
|
741
971
|
}
|
|
742
972
|
main().catch((error) => {
|
|
743
973
|
console.error("Fatal error:", error.message);
|
package/dist/cli.d.ts
CHANGED
|
@@ -2,14 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* SandAgent Runner CLI
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* sandagent run [options] -- "<user input>"
|
|
10
|
-
*
|
|
11
|
-
* The CLI is designed to be executed in a specific working directory
|
|
12
|
-
* and outputs AI SDK UI messages directly.
|
|
5
|
+
* Subcommands:
|
|
6
|
+
* sandagent run [options] -- "<user input>" Run an agent locally
|
|
7
|
+
* sandagent image build [options] Build (and optionally push) a Docker image
|
|
13
8
|
*/
|
|
14
9
|
export {};
|
|
15
10
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;GAMG"}
|
package/dist/cli.js
CHANGED
|
@@ -2,25 +2,59 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* SandAgent Runner CLI
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* sandagent run [options] -- "<user input>"
|
|
10
|
-
*
|
|
11
|
-
* The CLI is designed to be executed in a specific working directory
|
|
12
|
-
* and outputs AI SDK UI messages directly.
|
|
5
|
+
* Subcommands:
|
|
6
|
+
* sandagent run [options] -- "<user input>" Run an agent locally
|
|
7
|
+
* sandagent image build [options] Build (and optionally push) a Docker image
|
|
13
8
|
*/
|
|
14
9
|
import { parseArgs } from "node:util";
|
|
10
|
+
import { buildImage } from "./build-image.js";
|
|
15
11
|
import { runAgent } from "./runner.js";
|
|
16
|
-
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Shared helpers
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
/** Get the first positional arg (top-level subcommand). */
|
|
16
|
+
function getSubcommand() {
|
|
17
|
+
for (let i = 2; i < process.argv.length; i++) {
|
|
18
|
+
const a = process.argv[i];
|
|
19
|
+
if (a === "--")
|
|
20
|
+
break;
|
|
21
|
+
if (!a.startsWith("-"))
|
|
22
|
+
return a;
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
/** Get the second positional arg (sub-subcommand, e.g. "build" in "image build"). */
|
|
27
|
+
function getSubSubcommand() {
|
|
28
|
+
let found = 0;
|
|
29
|
+
for (let i = 2; i < process.argv.length; i++) {
|
|
30
|
+
const a = process.argv[i];
|
|
31
|
+
if (a === "--")
|
|
32
|
+
break;
|
|
33
|
+
if (!a.startsWith("-")) {
|
|
34
|
+
found++;
|
|
35
|
+
if (found === 2)
|
|
36
|
+
return a;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
/** Slice process.argv to args after N positionals. */
|
|
42
|
+
function argsAfterPositionals(n) {
|
|
43
|
+
let found = 0;
|
|
44
|
+
for (let i = 2; i < process.argv.length; i++) {
|
|
45
|
+
if (!process.argv[i].startsWith("-") && process.argv[i] !== "--") {
|
|
46
|
+
found++;
|
|
47
|
+
if (found === n)
|
|
48
|
+
return process.argv.slice(i + 1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
function parseRunArgs() {
|
|
17
54
|
const { values, positionals } = parseArgs({
|
|
55
|
+
args: argsAfterPositionals(1),
|
|
18
56
|
options: {
|
|
19
|
-
runner: {
|
|
20
|
-
type: "string",
|
|
21
|
-
short: "r",
|
|
22
|
-
default: "claude",
|
|
23
|
-
},
|
|
57
|
+
runner: { type: "string", short: "r", default: "claude" },
|
|
24
58
|
model: {
|
|
25
59
|
type: "string",
|
|
26
60
|
short: "m",
|
|
@@ -31,65 +65,38 @@ function parseCliArgs() {
|
|
|
31
65
|
short: "c",
|
|
32
66
|
default: process.env.SANDAGENT_WORKSPACE ?? process.cwd(),
|
|
33
67
|
},
|
|
34
|
-
"system-prompt": {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
},
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
short: "t",
|
|
41
|
-
},
|
|
42
|
-
"allowed-tools": {
|
|
43
|
-
type: "string",
|
|
44
|
-
short: "a",
|
|
45
|
-
},
|
|
46
|
-
resume: {
|
|
47
|
-
type: "string",
|
|
48
|
-
short: "r",
|
|
49
|
-
},
|
|
50
|
-
"output-format": {
|
|
51
|
-
type: "string",
|
|
52
|
-
short: "o",
|
|
53
|
-
},
|
|
54
|
-
help: {
|
|
55
|
-
type: "boolean",
|
|
56
|
-
short: "h",
|
|
57
|
-
},
|
|
68
|
+
"system-prompt": { type: "string", short: "s" },
|
|
69
|
+
"max-turns": { type: "string", short: "t" },
|
|
70
|
+
"allowed-tools": { type: "string", short: "a" },
|
|
71
|
+
resume: { type: "string" },
|
|
72
|
+
"output-format": { type: "string", short: "o" },
|
|
73
|
+
help: { type: "boolean", short: "h" },
|
|
58
74
|
},
|
|
59
75
|
allowPositionals: true,
|
|
60
76
|
strict: true,
|
|
61
77
|
});
|
|
62
78
|
if (values.help) {
|
|
63
|
-
|
|
79
|
+
printRunHelp();
|
|
64
80
|
process.exit(0);
|
|
65
81
|
}
|
|
66
|
-
// Check for "run" command
|
|
67
|
-
if (positionals[0] !== "run") {
|
|
68
|
-
console.error('Error: Expected "run" command');
|
|
69
|
-
console.error('Usage: sandagent run [options] -- "<user input>"');
|
|
70
|
-
process.exit(1);
|
|
71
|
-
}
|
|
72
|
-
// Get user input from positionals after "--"
|
|
73
82
|
const dashIndex = process.argv.indexOf("--");
|
|
74
83
|
let userInput = "";
|
|
75
84
|
if (dashIndex !== -1 && dashIndex < process.argv.length - 1) {
|
|
76
85
|
userInput = process.argv.slice(dashIndex + 1).join(" ");
|
|
77
86
|
}
|
|
78
|
-
else if (positionals.length >
|
|
79
|
-
userInput = positionals.
|
|
87
|
+
else if (positionals.length > 0) {
|
|
88
|
+
userInput = positionals.join(" ");
|
|
80
89
|
}
|
|
81
90
|
if (!userInput) {
|
|
82
91
|
console.error("Error: User input is required");
|
|
83
92
|
console.error('Usage: sandagent run [options] -- "<user input>"');
|
|
84
93
|
process.exit(1);
|
|
85
94
|
}
|
|
86
|
-
// Validate runner
|
|
87
95
|
const runner = values.runner;
|
|
88
96
|
if (!["claude", "codex", "copilot"].includes(runner)) {
|
|
89
97
|
console.error('Error: --runner must be one of: "claude", "codex", "copilot"');
|
|
90
98
|
process.exit(1);
|
|
91
99
|
}
|
|
92
|
-
// Validate output-format
|
|
93
100
|
const outputFormat = values["output-format"];
|
|
94
101
|
if (outputFormat &&
|
|
95
102
|
!["text", "json", "stream-json", "stream"].includes(outputFormat)) {
|
|
@@ -110,62 +117,165 @@ function parseCliArgs() {
|
|
|
110
117
|
userInput,
|
|
111
118
|
};
|
|
112
119
|
}
|
|
113
|
-
function
|
|
120
|
+
function parseImageBuildArgs() {
|
|
121
|
+
const { values } = parseArgs({
|
|
122
|
+
args: argsAfterPositionals(2),
|
|
123
|
+
options: {
|
|
124
|
+
name: { type: "string", default: "sandagent" },
|
|
125
|
+
tag: { type: "string", default: "latest" },
|
|
126
|
+
image: { type: "string" },
|
|
127
|
+
platform: { type: "string", default: "linux/amd64" },
|
|
128
|
+
template: { type: "string" },
|
|
129
|
+
push: { type: "boolean", default: false },
|
|
130
|
+
help: { type: "boolean", short: "h" },
|
|
131
|
+
},
|
|
132
|
+
allowPositionals: false,
|
|
133
|
+
strict: true,
|
|
134
|
+
});
|
|
135
|
+
if (values.help) {
|
|
136
|
+
printImageBuildHelp();
|
|
137
|
+
process.exit(0);
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
name: values.name,
|
|
141
|
+
tag: values.tag,
|
|
142
|
+
image: values.image,
|
|
143
|
+
platform: values.platform,
|
|
144
|
+
template: values.template,
|
|
145
|
+
push: values.push ?? false,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
// Help text
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
function printRunHelp() {
|
|
114
152
|
console.log(`
|
|
115
|
-
🤖 SandAgent Runner CLI
|
|
153
|
+
🤖 SandAgent Runner CLI — run
|
|
116
154
|
|
|
117
|
-
|
|
118
|
-
Streams AI SDK UI messages directly to stdout.
|
|
155
|
+
Runs an agent locally in your terminal, streaming AI SDK UI messages to stdout.
|
|
119
156
|
|
|
120
157
|
Usage:
|
|
121
158
|
sandagent run [options] -- "<user input>"
|
|
122
159
|
|
|
123
160
|
Options:
|
|
124
|
-
-r, --runner <runner> Runner
|
|
125
|
-
-m, --model <model> Model
|
|
126
|
-
-c, --cwd <path> Working directory (default:
|
|
161
|
+
-r, --runner <runner> Runner: claude, codex, copilot (default: claude)
|
|
162
|
+
-m, --model <model> Model (default: claude-sonnet-4-20250514)
|
|
163
|
+
-c, --cwd <path> Working directory (default: cwd)
|
|
127
164
|
-s, --system-prompt <prompt> Custom system prompt
|
|
128
|
-
-t, --max-turns <n>
|
|
129
|
-
-a, --allowed-tools <tools> Comma-separated
|
|
130
|
-
|
|
131
|
-
-o, --output-format <
|
|
132
|
-
|
|
133
|
-
|
|
165
|
+
-t, --max-turns <n> Max conversation turns
|
|
166
|
+
-a, --allowed-tools <tools> Comma-separated allowed tools
|
|
167
|
+
--resume <session-id> Resume a previous session
|
|
168
|
+
-o, --output-format <fmt> text | json | stream-json | stream (default: stream)
|
|
169
|
+
-h, --help Show this help
|
|
170
|
+
|
|
171
|
+
Environment:
|
|
172
|
+
ANTHROPIC_API_KEY Anthropic API key (required)
|
|
173
|
+
SANDAGENT_WORKSPACE Default workspace path
|
|
174
|
+
`);
|
|
175
|
+
}
|
|
176
|
+
function printImageBuildHelp() {
|
|
177
|
+
console.log(`
|
|
178
|
+
🐳 SandAgent Runner CLI — image build
|
|
134
179
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
180
|
+
Build (and optionally push) a SandAgent Docker image.
|
|
181
|
+
The image includes Claude Agent SDK + runner-cli pre-installed.
|
|
182
|
+
|
|
183
|
+
Usage:
|
|
184
|
+
sandagent image build [options]
|
|
185
|
+
|
|
186
|
+
Options:
|
|
187
|
+
--name <name> Image name, e.g. vikadata/sandagent-seo (default: sandagent)
|
|
188
|
+
--tag <tag> Image tag (default: latest)
|
|
189
|
+
--image <full> Full image name override (e.g. myorg/myimage:v1)
|
|
190
|
+
--platform <plat> Build platform (default: linux/amd64)
|
|
191
|
+
--template <path> Path to agent template directory to bake into the image
|
|
192
|
+
--push Push image to registry after build
|
|
193
|
+
-h, --help Show this help
|
|
139
194
|
|
|
140
195
|
Examples:
|
|
141
|
-
|
|
142
|
-
sandagent
|
|
196
|
+
sandagent image build --name vikadata/sandagent-seo --tag 0.1.0
|
|
197
|
+
sandagent image build --name vikadata/sandagent-seo --tag 0.1.0 --template ./templates/seo-agent
|
|
198
|
+
sandagent image build --name vikadata/sandagent-seo --tag 0.1.0 --template ./templates/seo-agent --push
|
|
199
|
+
`);
|
|
200
|
+
}
|
|
201
|
+
function printImageHelp() {
|
|
202
|
+
console.log(`
|
|
203
|
+
🐳 SandAgent Runner CLI — image
|
|
143
204
|
|
|
144
|
-
|
|
145
|
-
sandagent run --system-prompt "You are a coding assistant" -- "Build a REST API with Express"
|
|
205
|
+
Manage SandAgent Docker images.
|
|
146
206
|
|
|
147
|
-
|
|
148
|
-
sandagent
|
|
207
|
+
Usage:
|
|
208
|
+
sandagent image <subcommand> [options]
|
|
209
|
+
|
|
210
|
+
Subcommands:
|
|
211
|
+
build Build (and optionally push) a Docker image
|
|
212
|
+
|
|
213
|
+
Run "sandagent image build --help" for build options.
|
|
149
214
|
`);
|
|
150
215
|
}
|
|
216
|
+
function printGlobalHelp() {
|
|
217
|
+
console.log(`
|
|
218
|
+
🤖 SandAgent Runner CLI
|
|
219
|
+
|
|
220
|
+
Usage:
|
|
221
|
+
sandagent <command> [options]
|
|
222
|
+
|
|
223
|
+
Commands:
|
|
224
|
+
run Run an agent locally (streams AI SDK UI messages to stdout)
|
|
225
|
+
image build Build a SandAgent Docker image (with optional --push)
|
|
226
|
+
|
|
227
|
+
Run "sandagent <command> --help" for command-specific options.
|
|
228
|
+
`);
|
|
229
|
+
}
|
|
230
|
+
// ---------------------------------------------------------------------------
|
|
231
|
+
// Main
|
|
232
|
+
// ---------------------------------------------------------------------------
|
|
151
233
|
async function main() {
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
234
|
+
const sub = getSubcommand();
|
|
235
|
+
if (!sub || sub === "--help" || sub === "-h") {
|
|
236
|
+
printGlobalHelp();
|
|
237
|
+
process.exit(0);
|
|
238
|
+
}
|
|
239
|
+
switch (sub) {
|
|
240
|
+
case "run": {
|
|
241
|
+
const args = parseRunArgs();
|
|
242
|
+
process.chdir(args.cwd);
|
|
243
|
+
await runAgent({
|
|
244
|
+
runner: args.runner,
|
|
245
|
+
model: args.model,
|
|
246
|
+
userInput: args.userInput,
|
|
247
|
+
systemPrompt: args.systemPrompt,
|
|
248
|
+
maxTurns: args.maxTurns,
|
|
249
|
+
allowedTools: args.allowedTools,
|
|
250
|
+
resume: args.resume,
|
|
251
|
+
outputFormat: args.outputFormat,
|
|
252
|
+
});
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
case "image": {
|
|
256
|
+
const subSub = getSubSubcommand();
|
|
257
|
+
if (!subSub || subSub === "--help" || subSub === "-h") {
|
|
258
|
+
printImageHelp();
|
|
259
|
+
process.exit(0);
|
|
260
|
+
}
|
|
261
|
+
if (subSub === "build") {
|
|
262
|
+
const args = parseImageBuildArgs();
|
|
263
|
+
await buildImage(args);
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
console.error(`Unknown image subcommand: ${subSub}`);
|
|
267
|
+
printImageHelp();
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
default:
|
|
273
|
+
console.error(`Unknown command: ${sub}`);
|
|
274
|
+
printGlobalHelp();
|
|
275
|
+
process.exit(1);
|
|
276
|
+
}
|
|
166
277
|
}
|
|
167
278
|
main().catch((error) => {
|
|
168
|
-
// Errors go to stderr, not stdout
|
|
169
279
|
console.error("Fatal error:", error.message);
|
|
170
280
|
process.exit(1);
|
|
171
281
|
});
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
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,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,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,QAAQ,EAAwB,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAwB,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,UAAU,EAA0B,MAAM,kBAAkB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sandagent/runner-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"description": "SandAgent Runner CLI - Like gemini-cli or claude-code, runs in your local terminal with AI SDK UI streaming",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
|
-
"dist"
|
|
19
|
+
"dist",
|
|
20
|
+
"Dockerfile"
|
|
20
21
|
],
|
|
21
22
|
"repository": {
|
|
22
23
|
"type": "git",
|