@ai-hero/sandcastle 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +160 -31
- package/dist/AgentProvider.d.ts +28 -4
- package/dist/AgentProvider.d.ts.map +1 -1
- package/dist/AgentProvider.js +193 -49
- package/dist/AgentProvider.js.map +1 -1
- package/dist/InitService.d.ts +16 -3
- package/dist/InitService.d.ts.map +1 -1
- package/dist/InitService.js +166 -19
- package/dist/InitService.js.map +1 -1
- package/dist/Orchestrator.d.ts +9 -34
- package/dist/Orchestrator.d.ts.map +1 -1
- package/dist/Orchestrator.js +38 -105
- package/dist/Orchestrator.js.map +1 -1
- package/dist/SandboxFactory.d.ts +14 -5
- package/dist/SandboxFactory.d.ts.map +1 -1
- package/dist/SandboxFactory.js +86 -36
- package/dist/SandboxFactory.js.map +1 -1
- package/dist/WorktreeManager.d.ts +10 -5
- package/dist/WorktreeManager.d.ts.map +1 -1
- package/dist/WorktreeManager.js +13 -8
- package/dist/WorktreeManager.js.map +1 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +75 -27
- package/dist/cli.js.map +1 -1
- package/dist/createSandbox.d.ts +82 -0
- package/dist/createSandbox.d.ts.map +1 -0
- package/dist/createSandbox.js +192 -0
- package/dist/createSandbox.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/run.d.ts +22 -6
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +36 -31
- package/dist/run.js.map +1 -1
- package/dist/templates/blank/.env.example +4 -0
- package/dist/templates/blank/main.ts +2 -1
- package/dist/templates/parallel-planner/.env.example +4 -0
- package/dist/templates/parallel-planner/main.ts +4 -4
- package/dist/templates/sequential-reviewer/.env.example +4 -0
- package/dist/templates/sequential-reviewer/main.ts +3 -3
- package/dist/templates/simple-loop/.env.example +4 -0
- package/dist/templates/simple-loop/main.ts +6 -5
- package/package.json +2 -2
package/dist/InitService.js
CHANGED
|
@@ -2,6 +2,7 @@ import { FileSystem } from "@effect/platform";
|
|
|
2
2
|
import { Effect } from "effect";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { SANDBOX_WORKSPACE_DIR } from "./SandboxFactory.js";
|
|
5
6
|
const GITIGNORE = `.env
|
|
6
7
|
logs/
|
|
7
8
|
worktrees/
|
|
@@ -25,13 +26,135 @@ const TEMPLATES = [
|
|
|
25
26
|
},
|
|
26
27
|
];
|
|
27
28
|
export const listTemplates = () => TEMPLATES;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
const CLAUDE_CODE_DOCKERFILE = `FROM node:22-bookworm
|
|
30
|
+
|
|
31
|
+
# Install system dependencies
|
|
32
|
+
RUN apt-get update && apt-get install -y \\
|
|
33
|
+
git \\
|
|
34
|
+
curl \\
|
|
35
|
+
jq \\
|
|
36
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
37
|
+
|
|
38
|
+
# Install GitHub CLI
|
|
39
|
+
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \\
|
|
40
|
+
| dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \\
|
|
41
|
+
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \\
|
|
42
|
+
| tee /etc/apt/sources.list.d/github-cli.list > /dev/null \\
|
|
43
|
+
&& apt-get update && apt-get install -y gh \\
|
|
44
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
45
|
+
|
|
46
|
+
# Create a non-root user for Claude to run as
|
|
47
|
+
RUN useradd -m -s /bin/bash agent
|
|
48
|
+
USER agent
|
|
49
|
+
|
|
50
|
+
# Install Claude Code CLI
|
|
51
|
+
RUN curl -fsSL https://claude.ai/install.sh | bash
|
|
52
|
+
|
|
53
|
+
# Add Claude to PATH
|
|
54
|
+
ENV PATH="/home/agent/.local/bin:$PATH"
|
|
55
|
+
|
|
56
|
+
WORKDIR /home/agent
|
|
57
|
+
|
|
58
|
+
# In worktree sandbox mode, Sandcastle bind-mounts the git worktree at ${SANDBOX_WORKSPACE_DIR}
|
|
59
|
+
# and overrides the working directory to ${SANDBOX_WORKSPACE_DIR} at container start.
|
|
60
|
+
# Structure your Dockerfile so that ${SANDBOX_WORKSPACE_DIR} can serve as the project root.
|
|
61
|
+
ENTRYPOINT ["sleep", "infinity"]
|
|
62
|
+
`;
|
|
63
|
+
const PI_DOCKERFILE = `FROM node:22-bookworm
|
|
64
|
+
|
|
65
|
+
# Install system dependencies
|
|
66
|
+
RUN apt-get update && apt-get install -y \\
|
|
67
|
+
git \\
|
|
68
|
+
curl \\
|
|
69
|
+
jq \\
|
|
70
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
71
|
+
|
|
72
|
+
# Install GitHub CLI
|
|
73
|
+
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \\
|
|
74
|
+
| dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \\
|
|
75
|
+
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \\
|
|
76
|
+
| tee /etc/apt/sources.list.d/github-cli.list > /dev/null \\
|
|
77
|
+
&& apt-get update && apt-get install -y gh \\
|
|
78
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
79
|
+
|
|
80
|
+
# Create a non-root user
|
|
81
|
+
RUN useradd -m -s /bin/bash agent
|
|
82
|
+
USER agent
|
|
83
|
+
|
|
84
|
+
# Install pi coding agent
|
|
85
|
+
RUN npm install -g @mariozechner/pi-coding-agent
|
|
86
|
+
|
|
87
|
+
WORKDIR /home/agent
|
|
88
|
+
|
|
89
|
+
# In worktree sandbox mode, Sandcastle bind-mounts the git worktree at ${SANDBOX_WORKSPACE_DIR}
|
|
90
|
+
# and overrides the working directory to ${SANDBOX_WORKSPACE_DIR} at container start.
|
|
91
|
+
# Structure your Dockerfile so that ${SANDBOX_WORKSPACE_DIR} can serve as the project root.
|
|
92
|
+
ENTRYPOINT ["sleep", "infinity"]
|
|
93
|
+
`;
|
|
94
|
+
const CODEX_DOCKERFILE = `FROM node:22-bookworm
|
|
95
|
+
|
|
96
|
+
# Install system dependencies
|
|
97
|
+
RUN apt-get update && apt-get install -y \\
|
|
98
|
+
git \\
|
|
99
|
+
curl \\
|
|
100
|
+
jq \\
|
|
101
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
102
|
+
|
|
103
|
+
# Install GitHub CLI
|
|
104
|
+
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \\
|
|
105
|
+
| dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \\
|
|
106
|
+
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \\
|
|
107
|
+
| tee /etc/apt/sources.list.d/github-cli.list > /dev/null \\
|
|
108
|
+
&& apt-get update && apt-get install -y gh \\
|
|
109
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
110
|
+
|
|
111
|
+
# Create a non-root user
|
|
112
|
+
RUN useradd -m -s /bin/bash agent
|
|
113
|
+
USER agent
|
|
114
|
+
|
|
115
|
+
# Install Codex CLI
|
|
116
|
+
RUN npm install -g @openai/codex
|
|
117
|
+
|
|
118
|
+
WORKDIR /home/agent
|
|
119
|
+
|
|
120
|
+
# In worktree sandbox mode, Sandcastle bind-mounts the git worktree at ${SANDBOX_WORKSPACE_DIR}
|
|
121
|
+
# and overrides the working directory to ${SANDBOX_WORKSPACE_DIR} at container start.
|
|
122
|
+
# Structure your Dockerfile so that ${SANDBOX_WORKSPACE_DIR} can serve as the project root.
|
|
123
|
+
ENTRYPOINT ["sleep", "infinity"]
|
|
124
|
+
`;
|
|
125
|
+
const AGENT_REGISTRY = [
|
|
126
|
+
{
|
|
127
|
+
name: "claude-code",
|
|
128
|
+
label: "Claude Code",
|
|
129
|
+
defaultModel: "claude-opus-4-6",
|
|
130
|
+
factoryImport: "claudeCode",
|
|
131
|
+
dockerfileTemplate: CLAUDE_CODE_DOCKERFILE,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: "pi",
|
|
135
|
+
label: "Pi",
|
|
136
|
+
defaultModel: "claude-sonnet-4-6",
|
|
137
|
+
factoryImport: "pi",
|
|
138
|
+
dockerfileTemplate: PI_DOCKERFILE,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: "codex",
|
|
142
|
+
label: "Codex",
|
|
143
|
+
defaultModel: "gpt-5.4-mini",
|
|
144
|
+
factoryImport: "codex",
|
|
145
|
+
dockerfileTemplate: CODEX_DOCKERFILE,
|
|
146
|
+
},
|
|
147
|
+
];
|
|
148
|
+
export const listAgents = () => AGENT_REGISTRY;
|
|
149
|
+
export const getAgent = (name) => AGENT_REGISTRY.find((a) => a.name === name);
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// Next steps
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
export function getNextStepsLines(template) {
|
|
31
154
|
if (template === "blank") {
|
|
32
155
|
return [
|
|
33
156
|
"Next steps:",
|
|
34
|
-
|
|
157
|
+
`1. Set the required env vars in .sandcastle/.env (see .sandcastle/.env.example)`,
|
|
35
158
|
"2. Read and customize .sandcastle/prompt.md to describe what you want the agent to do",
|
|
36
159
|
`3. Customize .sandcastle/main.ts — it uses the JS API (\`run()\`) to control how the agent runs`,
|
|
37
160
|
`4. Add "sandcastle": "npx tsx .sandcastle/main.ts" to your package.json scripts`,
|
|
@@ -41,7 +164,7 @@ export function getNextStepsLines(template, provider) {
|
|
|
41
164
|
else {
|
|
42
165
|
return [
|
|
43
166
|
"Next steps:",
|
|
44
|
-
|
|
167
|
+
`1. Set the required env vars in .sandcastle/.env (see .sandcastle/.env.example)`,
|
|
45
168
|
`2. Add "sandcastle": "npx tsx .sandcastle/main.ts" to your package.json scripts`,
|
|
46
169
|
'3. Templates use `copyToSandbox: ["node_modules"]` to copy your host node_modules into the sandbox for fast startup — the `npm install` in the onSandboxReady hook is a safety net for platform-specific binaries. Adjust both if you use a different package manager',
|
|
47
170
|
"4. Read and customize the prompt files in .sandcastle/ — they shape what the agent does",
|
|
@@ -49,11 +172,9 @@ export function getNextStepsLines(template, provider) {
|
|
|
49
172
|
];
|
|
50
173
|
}
|
|
51
174
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
.join("\n") + "\n");
|
|
56
|
-
}
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
// Scaffolding helpers
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
57
178
|
function getTemplatesDir() {
|
|
58
179
|
const thisFile = fileURLToPath(import.meta.url);
|
|
59
180
|
return join(dirname(thisFile), "templates");
|
|
@@ -66,6 +187,7 @@ const getTemplateDir = (templateName) => Effect.gen(function* () {
|
|
|
66
187
|
}
|
|
67
188
|
return join(getTemplatesDir(), templateName);
|
|
68
189
|
});
|
|
190
|
+
const COMPILED_FILE_EXTENSIONS = [".js", ".js.map", ".d.ts", ".d.ts.map"];
|
|
69
191
|
const copyTemplateFiles = (templateDir, destDir) => Effect.gen(function* () {
|
|
70
192
|
const fs = yield* FileSystem.FileSystem;
|
|
71
193
|
const files = yield* fs
|
|
@@ -73,15 +195,41 @@ const copyTemplateFiles = (templateDir, destDir) => Effect.gen(function* () {
|
|
|
73
195
|
.pipe(Effect.mapError((e) => new Error(e.message)));
|
|
74
196
|
yield* Effect.all(files
|
|
75
197
|
.filter((f) => f !== "template.json" &&
|
|
76
|
-
!f.endsWith(
|
|
77
|
-
!f.endsWith(".js.map") &&
|
|
78
|
-
!f.endsWith(".d.ts") &&
|
|
79
|
-
!f.endsWith(".d.ts.map"))
|
|
198
|
+
!COMPILED_FILE_EXTENSIONS.some((ext) => f.endsWith(ext)))
|
|
80
199
|
.map((f) => fs
|
|
81
200
|
.copyFile(join(templateDir, f), join(destDir, f))
|
|
82
201
|
.pipe(Effect.mapError((e) => new Error(e.message)))), { concurrency: "unbounded" });
|
|
83
202
|
});
|
|
84
|
-
|
|
203
|
+
/**
|
|
204
|
+
* Replace the agent factory import and call in a scaffolded main.ts.
|
|
205
|
+
*
|
|
206
|
+
* Templates use `claudeCode` as the default factory. When a different agent or
|
|
207
|
+
* model is selected, this function rewrites the import and factory calls.
|
|
208
|
+
*/
|
|
209
|
+
const rewriteMainTs = (configDir, agent, model) => Effect.gen(function* () {
|
|
210
|
+
const fs = yield* FileSystem.FileSystem;
|
|
211
|
+
const mainTsPath = join(configDir, "main.ts");
|
|
212
|
+
const exists = yield* fs
|
|
213
|
+
.exists(mainTsPath)
|
|
214
|
+
.pipe(Effect.mapError((e) => new Error(e.message)));
|
|
215
|
+
if (!exists)
|
|
216
|
+
return;
|
|
217
|
+
let content = yield* fs
|
|
218
|
+
.readFileString(mainTsPath)
|
|
219
|
+
.pipe(Effect.mapError((e) => new Error(e.message)));
|
|
220
|
+
// Replace factory function name in imports (e.g. claudeCode → pi)
|
|
221
|
+
// and all factory calls with the correct model.
|
|
222
|
+
// Templates always use claudeCode as the placeholder factory.
|
|
223
|
+
content = content.replace(/\bclaudeCode\b/g, agent.factoryImport);
|
|
224
|
+
// Replace model strings in factory calls: factoryImport("any-model")
|
|
225
|
+
const factoryCallRe = new RegExp(`${agent.factoryImport}\\(["']([^"']+)["']\\)`, "g");
|
|
226
|
+
content = content.replace(factoryCallRe, `${agent.factoryImport}("${model}")`);
|
|
227
|
+
yield* fs
|
|
228
|
+
.writeFileString(mainTsPath, content)
|
|
229
|
+
.pipe(Effect.mapError((e) => new Error(e.message)));
|
|
230
|
+
});
|
|
231
|
+
export const scaffold = (repoDir, options) => Effect.gen(function* () {
|
|
232
|
+
const { agent, model, templateName = "blank" } = options;
|
|
85
233
|
const fs = yield* FileSystem.FileSystem;
|
|
86
234
|
const configDir = join(repoDir, ".sandcastle");
|
|
87
235
|
const exists = yield* fs
|
|
@@ -96,15 +244,14 @@ export const scaffold = (repoDir, provider, templateName = "blank") => Effect.ge
|
|
|
96
244
|
const templateDir = yield* getTemplateDir(templateName);
|
|
97
245
|
yield* Effect.all([
|
|
98
246
|
fs
|
|
99
|
-
.writeFileString(join(configDir, "Dockerfile"),
|
|
100
|
-
.pipe(Effect.mapError((e) => new Error(e.message))),
|
|
101
|
-
fs
|
|
102
|
-
.writeFileString(join(configDir, ".env.example"), buildEnvExample(provider.envManifest))
|
|
247
|
+
.writeFileString(join(configDir, "Dockerfile"), agent.dockerfileTemplate)
|
|
103
248
|
.pipe(Effect.mapError((e) => new Error(e.message))),
|
|
104
249
|
fs
|
|
105
250
|
.writeFileString(join(configDir, ".gitignore"), GITIGNORE)
|
|
106
251
|
.pipe(Effect.mapError((e) => new Error(e.message))),
|
|
107
252
|
copyTemplateFiles(templateDir, configDir),
|
|
108
253
|
], { concurrency: "unbounded" });
|
|
254
|
+
// Rewrite main.ts with the selected agent factory and model
|
|
255
|
+
yield* rewriteMainTs(configDir, agent, model);
|
|
109
256
|
});
|
|
110
257
|
//# sourceMappingURL=InitService.js.map
|
package/dist/InitService.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InitService.js","sourceRoot":"","sources":["../src/InitService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"InitService.js","sourceRoot":"","sources":["../src/InitService.ts"],"names":[],"mappings":"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"}
|
package/dist/Orchestrator.d.ts
CHANGED
|
@@ -3,38 +3,9 @@ import { Display } from "./Display.js";
|
|
|
3
3
|
import type { SandboxError } from "./errors.js";
|
|
4
4
|
import { SandboxFactory } from "./SandboxFactory.js";
|
|
5
5
|
import { type SandboxHooks } from "./SandboxLifecycle.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
readonly cache_read_input_tokens: number;
|
|
10
|
-
readonly cache_creation_input_tokens: number;
|
|
11
|
-
readonly total_cost_usd: number;
|
|
12
|
-
readonly num_turns: number;
|
|
13
|
-
readonly duration_ms: number;
|
|
14
|
-
}
|
|
15
|
-
export declare const DEFAULT_MODEL = "claude-opus-4-6";
|
|
16
|
-
export type ParsedStreamEvent = {
|
|
17
|
-
type: "text";
|
|
18
|
-
text: string;
|
|
19
|
-
} | {
|
|
20
|
-
type: "result";
|
|
21
|
-
result: string;
|
|
22
|
-
usage: TokenUsage | null;
|
|
23
|
-
} | {
|
|
24
|
-
type: "tool_call";
|
|
25
|
-
name: string;
|
|
26
|
-
args: string;
|
|
27
|
-
};
|
|
28
|
-
/** Extract displayable events from a stream-json line */
|
|
29
|
-
export declare const parseStreamJsonLine: (line: string) => ParsedStreamEvent[];
|
|
30
|
-
/**
|
|
31
|
-
* Format a tool call for display. Returns null if the tool is not in the
|
|
32
|
-
* allowlist or the required arg field is missing.
|
|
33
|
-
*/
|
|
34
|
-
export declare const formatToolCall: (name: string, input: Record<string, unknown>) => {
|
|
35
|
-
name: string;
|
|
36
|
-
formattedArgs: string;
|
|
37
|
-
} | null;
|
|
6
|
+
import type { AgentProvider } from "./AgentProvider.js";
|
|
7
|
+
export type { TokenUsage } from "./AgentProvider.js";
|
|
8
|
+
export type { ParsedStreamEvent } from "./AgentProvider.js";
|
|
38
9
|
export interface OrchestrateOptions {
|
|
39
10
|
readonly hostRepoDir: string;
|
|
40
11
|
readonly sandboxRepoDir: string;
|
|
@@ -42,12 +13,14 @@ export interface OrchestrateOptions {
|
|
|
42
13
|
readonly hooks?: SandboxHooks;
|
|
43
14
|
readonly prompt: string;
|
|
44
15
|
readonly branch?: string;
|
|
45
|
-
readonly
|
|
16
|
+
readonly provider: AgentProvider;
|
|
46
17
|
readonly completionSignal?: string | string[];
|
|
47
|
-
/** Idle timeout in seconds. If the agent produces no output for this long, it fails with TimeoutError. Default:
|
|
18
|
+
/** Idle timeout in seconds. If the agent produces no output for this long, it fails with TimeoutError. Default: 600 (10 minutes) */
|
|
48
19
|
readonly idleTimeoutSeconds?: number;
|
|
49
20
|
/** Optional name for the run, prepended to status messages as [name] */
|
|
50
21
|
readonly name?: string;
|
|
22
|
+
/** @internal Test-only override for the idle warning interval in milliseconds. Default: 60000 (1 minute). */
|
|
23
|
+
readonly _idleWarningIntervalMs?: number;
|
|
51
24
|
}
|
|
52
25
|
export interface OrchestrateResult {
|
|
53
26
|
readonly iterationsRun: number;
|
|
@@ -58,6 +31,8 @@ export interface OrchestrateResult {
|
|
|
58
31
|
sha: string;
|
|
59
32
|
}[];
|
|
60
33
|
readonly branch: string;
|
|
34
|
+
/** Host path to the preserved worktree from the last iteration, set when the worktree was left behind due to uncommitted changes on a successful run. */
|
|
35
|
+
readonly preservedWorktreePath?: string;
|
|
61
36
|
}
|
|
62
37
|
export declare const orchestrate: (options: OrchestrateOptions) => Effect.Effect<OrchestrateResult, SandboxError, Display | SandboxFactory>;
|
|
63
38
|
//# sourceMappingURL=Orchestrator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Orchestrator.d.ts","sourceRoot":"","sources":["../src/Orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"Orchestrator.d.ts","sourceRoot":"","sources":["../src/Orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,oBAAoB,CAAC;AAEpE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAiH5D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC9C,oIAAoI;IACpI,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,wEAAwE;IACxE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,6GAA6G;IAC7G,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAC1C;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,wEAAwE;IACxE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,yJAAyJ;IACzJ,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;CACzC;AAED,eAAO,MAAM,WAAW,2GA0IvB,CAAC"}
|
package/dist/Orchestrator.js
CHANGED
|
@@ -4,108 +4,26 @@ import { preprocessPrompt } from "./PromptPreprocessor.js";
|
|
|
4
4
|
import { AgentError, TimeoutError } from "./errors.js";
|
|
5
5
|
import { SandboxFactory } from "./SandboxFactory.js";
|
|
6
6
|
import { withSandboxLifecycle } from "./SandboxLifecycle.js";
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
const usage = obj.usage;
|
|
10
|
-
if (!usage ||
|
|
11
|
-
typeof usage.input_tokens !== "number" ||
|
|
12
|
-
typeof usage.output_tokens !== "number") {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
return {
|
|
16
|
-
input_tokens: usage.input_tokens,
|
|
17
|
-
output_tokens: usage.output_tokens,
|
|
18
|
-
cache_read_input_tokens: typeof usage.cache_read_input_tokens === "number"
|
|
19
|
-
? usage.cache_read_input_tokens
|
|
20
|
-
: 0,
|
|
21
|
-
cache_creation_input_tokens: typeof usage.cache_creation_input_tokens === "number"
|
|
22
|
-
? usage.cache_creation_input_tokens
|
|
23
|
-
: 0,
|
|
24
|
-
total_cost_usd: typeof obj.total_cost_usd === "number" ? obj.total_cost_usd : 0,
|
|
25
|
-
num_turns: typeof obj.num_turns === "number" ? obj.num_turns : 0,
|
|
26
|
-
duration_ms: typeof obj.duration_ms === "number" ? obj.duration_ms : 0,
|
|
27
|
-
};
|
|
28
|
-
};
|
|
29
|
-
/** Maps allowlisted tool names to the input field containing the display arg */
|
|
30
|
-
const TOOL_ARG_FIELDS = {
|
|
31
|
-
Bash: "command",
|
|
32
|
-
WebSearch: "query",
|
|
33
|
-
WebFetch: "url",
|
|
34
|
-
Agent: "description",
|
|
35
|
-
};
|
|
36
|
-
/** Extract displayable events from a stream-json line */
|
|
37
|
-
export const parseStreamJsonLine = (line) => {
|
|
38
|
-
if (!line.startsWith("{"))
|
|
39
|
-
return [];
|
|
40
|
-
try {
|
|
41
|
-
const obj = JSON.parse(line);
|
|
42
|
-
if (obj.type === "assistant" && Array.isArray(obj.message?.content)) {
|
|
43
|
-
const events = [];
|
|
44
|
-
const texts = [];
|
|
45
|
-
for (const block of obj.message.content) {
|
|
46
|
-
if (block.type === "text" && typeof block.text === "string") {
|
|
47
|
-
texts.push(block.text);
|
|
48
|
-
}
|
|
49
|
-
else if (block.type === "tool_use" &&
|
|
50
|
-
typeof block.name === "string" &&
|
|
51
|
-
block.input !== undefined) {
|
|
52
|
-
const argField = TOOL_ARG_FIELDS[block.name];
|
|
53
|
-
if (argField === undefined)
|
|
54
|
-
continue; // not allowlisted
|
|
55
|
-
const argValue = block.input[argField];
|
|
56
|
-
if (typeof argValue !== "string")
|
|
57
|
-
continue; // missing/wrong arg field
|
|
58
|
-
if (texts.length > 0) {
|
|
59
|
-
events.push({ type: "text", text: texts.join("") });
|
|
60
|
-
texts.length = 0;
|
|
61
|
-
}
|
|
62
|
-
events.push({
|
|
63
|
-
type: "tool_call",
|
|
64
|
-
name: block.name,
|
|
65
|
-
args: argValue,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if (texts.length > 0) {
|
|
70
|
-
events.push({ type: "text", text: texts.join("") });
|
|
71
|
-
}
|
|
72
|
-
return events;
|
|
73
|
-
}
|
|
74
|
-
if (obj.type === "result" && typeof obj.result === "string") {
|
|
75
|
-
return [{ type: "result", result: obj.result, usage: extractUsage(obj) }];
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
// Not valid JSON — skip
|
|
80
|
-
}
|
|
81
|
-
return [];
|
|
82
|
-
};
|
|
83
|
-
const TOOL_ARG_EXTRACTORS = {
|
|
84
|
-
Bash: (input) => typeof input.command === "string" ? input.command : undefined,
|
|
85
|
-
WebSearch: (input) => typeof input.query === "string" ? input.query : undefined,
|
|
86
|
-
WebFetch: (input) => (typeof input.url === "string" ? input.url : undefined),
|
|
87
|
-
Agent: (input) => typeof input.description === "string" ? input.description : undefined,
|
|
88
|
-
};
|
|
89
|
-
/**
|
|
90
|
-
* Format a tool call for display. Returns null if the tool is not in the
|
|
91
|
-
* allowlist or the required arg field is missing.
|
|
92
|
-
*/
|
|
93
|
-
export const formatToolCall = (name, input) => {
|
|
94
|
-
const extractor = TOOL_ARG_EXTRACTORS[name];
|
|
95
|
-
if (!extractor)
|
|
96
|
-
return null;
|
|
97
|
-
const arg = extractor(input);
|
|
98
|
-
if (arg === undefined)
|
|
99
|
-
return null;
|
|
100
|
-
return { name, formattedArgs: arg };
|
|
101
|
-
};
|
|
102
|
-
const invokeAgent = (sandbox, sandboxRepoDir, prompt, model, idleTimeoutMs, onText, onToolCall) => Effect.gen(function* () {
|
|
7
|
+
const IDLE_WARNING_INTERVAL_MS = 60_000;
|
|
8
|
+
const invokeAgent = (sandbox, sandboxRepoDir, prompt, provider, idleTimeoutMs, onText, onToolCall, onIdleWarning, idleWarningIntervalMs = IDLE_WARNING_INTERVAL_MS) => Effect.gen(function* () {
|
|
103
9
|
let resultText = "";
|
|
104
10
|
let tokenUsage = null;
|
|
105
11
|
// Deferred that will be failed when the idle timer fires
|
|
106
12
|
const timeoutSignal = yield* Deferred.make();
|
|
107
13
|
let timeoutHandle = null;
|
|
108
14
|
const idleTimeoutSeconds = idleTimeoutMs / 1000;
|
|
15
|
+
// Periodic idle warning state
|
|
16
|
+
let warningHandle = null;
|
|
17
|
+
let idleMinuteCounter = 0;
|
|
18
|
+
const startWarningInterval = () => {
|
|
19
|
+
if (warningHandle !== null)
|
|
20
|
+
clearInterval(warningHandle);
|
|
21
|
+
idleMinuteCounter = 0;
|
|
22
|
+
warningHandle = setInterval(() => {
|
|
23
|
+
idleMinuteCounter++;
|
|
24
|
+
onIdleWarning(idleMinuteCounter);
|
|
25
|
+
}, idleWarningIntervalMs);
|
|
26
|
+
};
|
|
109
27
|
const resetIdleTimer = () => {
|
|
110
28
|
if (timeoutHandle !== null)
|
|
111
29
|
clearTimeout(timeoutHandle);
|
|
@@ -115,11 +33,13 @@ const invokeAgent = (sandbox, sandboxRepoDir, prompt, model, idleTimeoutMs, onTe
|
|
|
115
33
|
idleTimeoutSeconds,
|
|
116
34
|
}))).catch(() => { });
|
|
117
35
|
}, idleTimeoutMs);
|
|
36
|
+
// Reset warning interval on activity
|
|
37
|
+
startWarningInterval();
|
|
118
38
|
};
|
|
119
39
|
resetIdleTimer();
|
|
120
40
|
const execEffect = Effect.gen(function* () {
|
|
121
|
-
const execResult = yield* sandbox.execStreaming(
|
|
122
|
-
for (const parsed of
|
|
41
|
+
const execResult = yield* sandbox.execStreaming(provider.buildPrintCommand(prompt), (line) => {
|
|
42
|
+
for (const parsed of provider.parseStreamLine(line)) {
|
|
123
43
|
if (parsed.type === "text") {
|
|
124
44
|
resetIdleTimer();
|
|
125
45
|
onText(parsed.text);
|
|
@@ -136,7 +56,7 @@ const invokeAgent = (sandbox, sandboxRepoDir, prompt, model, idleTimeoutMs, onTe
|
|
|
136
56
|
}, { cwd: sandboxRepoDir });
|
|
137
57
|
if (execResult.exitCode !== 0) {
|
|
138
58
|
return yield* Effect.fail(new AgentError({
|
|
139
|
-
message:
|
|
59
|
+
message: `${provider.name} exited with code ${execResult.exitCode}:\n${execResult.stderr}`,
|
|
140
60
|
}));
|
|
141
61
|
}
|
|
142
62
|
return { result: resultText || execResult.stdout, usage: tokenUsage };
|
|
@@ -145,24 +65,26 @@ const invokeAgent = (sandbox, sandboxRepoDir, prompt, model, idleTimeoutMs, onTe
|
|
|
145
65
|
clearTimeout(timeoutHandle);
|
|
146
66
|
timeoutHandle = null;
|
|
147
67
|
}
|
|
68
|
+
if (warningHandle !== null) {
|
|
69
|
+
clearInterval(warningHandle);
|
|
70
|
+
warningHandle = null;
|
|
71
|
+
}
|
|
148
72
|
})));
|
|
149
73
|
return yield* Effect.raceFirst(execEffect, Deferred.await(timeoutSignal));
|
|
150
74
|
});
|
|
151
|
-
const shellEscape = (s) => "'" + s.replace(/'/g, "'\\''") + "'";
|
|
152
75
|
const formatNumber = (n) => n.toLocaleString("en-US");
|
|
153
76
|
const formatUsageRows = (usage) => ({
|
|
154
77
|
Tokens: `${formatNumber(usage.input_tokens)} in / ${formatNumber(usage.output_tokens)} out`,
|
|
155
78
|
Turns: `${usage.num_turns}`,
|
|
156
79
|
});
|
|
157
80
|
const DEFAULT_COMPLETION_SIGNAL = "<promise>COMPLETE</promise>";
|
|
158
|
-
const DEFAULT_IDLE_TIMEOUT_SECONDS =
|
|
81
|
+
const DEFAULT_IDLE_TIMEOUT_SECONDS = 10 * 60; // 600 seconds
|
|
159
82
|
export const orchestrate = (options) => {
|
|
160
83
|
const idleTimeoutMs = (options.idleTimeoutSeconds ?? DEFAULT_IDLE_TIMEOUT_SECONDS) * 1000;
|
|
161
84
|
return Effect.gen(function* () {
|
|
162
85
|
const factory = yield* SandboxFactory;
|
|
163
86
|
const display = yield* Display;
|
|
164
|
-
const { hostRepoDir, sandboxRepoDir, iterations, hooks, prompt, branch } = options;
|
|
165
|
-
const resolvedModel = options.model ?? DEFAULT_MODEL;
|
|
87
|
+
const { hostRepoDir, sandboxRepoDir, iterations, hooks, prompt, branch, provider, } = options;
|
|
166
88
|
let completionSignals;
|
|
167
89
|
if (options.completionSignal === undefined) {
|
|
168
90
|
completionSignals = [DEFAULT_COMPLETION_SIGNAL];
|
|
@@ -177,9 +99,10 @@ export const orchestrate = (options) => {
|
|
|
177
99
|
const allCommits = [];
|
|
178
100
|
let allStdout = "";
|
|
179
101
|
let resolvedBranch = "";
|
|
102
|
+
let iterationPreservedPath;
|
|
180
103
|
for (let i = 1; i <= iterations; i++) {
|
|
181
104
|
yield* display.status(label(`Iteration ${i}/${iterations}`), "info");
|
|
182
|
-
const
|
|
105
|
+
const sandboxResult = yield* factory.withSandbox(({ hostWorktreePath }) => withSandboxLifecycle({
|
|
183
106
|
hostRepoDir,
|
|
184
107
|
sandboxRepoDir,
|
|
185
108
|
hooks,
|
|
@@ -196,7 +119,13 @@ export const orchestrate = (options) => {
|
|
|
196
119
|
const onToolCall = (name, formattedArgs) => {
|
|
197
120
|
Effect.runPromise(display.toolCall(name, formattedArgs));
|
|
198
121
|
};
|
|
199
|
-
const
|
|
122
|
+
const onIdleWarning = (minutes) => {
|
|
123
|
+
const msg = minutes === 1
|
|
124
|
+
? "Agent idle for 1 minute"
|
|
125
|
+
: `Agent idle for ${minutes} minutes`;
|
|
126
|
+
Effect.runPromise(display.status(label(msg), "warn"));
|
|
127
|
+
};
|
|
128
|
+
const { result: agentOutput, usage } = yield* invokeAgent(ctx.sandbox, ctx.sandboxRepoDir, fullPrompt, provider, idleTimeoutMs, onText, onToolCall, onIdleWarning, options._idleWarningIntervalMs);
|
|
200
129
|
yield* display.status(label("Agent stopped"), "info");
|
|
201
130
|
// Log usage summary
|
|
202
131
|
if (usage) {
|
|
@@ -209,6 +138,8 @@ export const orchestrate = (options) => {
|
|
|
209
138
|
stdout: agentOutput,
|
|
210
139
|
};
|
|
211
140
|
})));
|
|
141
|
+
const lifecycleResult = sandboxResult.value;
|
|
142
|
+
iterationPreservedPath = sandboxResult.preservedWorktreePath;
|
|
212
143
|
allCommits.push(...lifecycleResult.commits);
|
|
213
144
|
allStdout += lifecycleResult.result.stdout;
|
|
214
145
|
resolvedBranch = lifecycleResult.branch;
|
|
@@ -220,6 +151,7 @@ export const orchestrate = (options) => {
|
|
|
220
151
|
stdout: allStdout,
|
|
221
152
|
commits: allCommits,
|
|
222
153
|
branch: resolvedBranch,
|
|
154
|
+
preservedWorktreePath: iterationPreservedPath,
|
|
223
155
|
};
|
|
224
156
|
}
|
|
225
157
|
}
|
|
@@ -230,6 +162,7 @@ export const orchestrate = (options) => {
|
|
|
230
162
|
stdout: allStdout,
|
|
231
163
|
commits: allCommits,
|
|
232
164
|
branch: resolvedBranch,
|
|
165
|
+
preservedWorktreePath: iterationPreservedPath,
|
|
233
166
|
};
|
|
234
167
|
});
|
|
235
168
|
};
|
package/dist/Orchestrator.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Orchestrator.js","sourceRoot":"","sources":["../src/Orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAqB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"Orchestrator.js","sourceRoot":"","sources":["../src/Orchestrator.ts"],"names":[],"mappings":"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"}
|