smol-symphony 0.1.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/AGENTS.md +73 -0
- package/DESIGN.md +453 -0
- package/LICENSE +21 -0
- package/PRODUCT.md +106 -0
- package/README.md +232 -0
- package/SPEC.md +2169 -0
- package/WORKFLOW.md +269 -0
- package/WORKFLOW.template.md +307 -0
- package/dist/agent/acp.js +304 -0
- package/dist/agent/acp.js.map +1 -0
- package/dist/agent/adapters.js +275 -0
- package/dist/agent/adapters.js.map +1 -0
- package/dist/agent/codex.js +439 -0
- package/dist/agent/codex.js.map +1 -0
- package/dist/agent/runner.js +394 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/agent/smolvm.js +174 -0
- package/dist/agent/smolvm.js.map +1 -0
- package/dist/bin/symphony.js +205 -0
- package/dist/bin/symphony.js.map +1 -0
- package/dist/http.js +1189 -0
- package/dist/http.js.map +1 -0
- package/dist/logging.js +45 -0
- package/dist/logging.js.map +1 -0
- package/dist/mcp.js +478 -0
- package/dist/mcp.js.map +1 -0
- package/dist/orchestrator.js +683 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/prompt.js +65 -0
- package/dist/prompt.js.map +1 -0
- package/dist/trackers/local.js +344 -0
- package/dist/trackers/local.js.map +1 -0
- package/dist/trackers/types.js +10 -0
- package/dist/trackers/types.js.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/workflow.js +385 -0
- package/dist/workflow.js.map +1 -0
- package/dist/workspace.js +196 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +68 -0
- package/scripts/build-vm.sh +67 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
// Agent Runner (SPEC §10.7): workspace + prompt + ACP session, with continuation turns up
|
|
2
|
+
// to agent.max_turns. The ACP adapter (claude-agent-acp / codex-acp / opencode acp) runs
|
|
3
|
+
// inside a per-issue smolvm machine. The host workspace directory is volume-mounted into
|
|
4
|
+
// the VM at the same absolute path so cwd values are consistent.
|
|
5
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
6
|
+
import { WorkspaceManager, sanitizeWorkspaceKey } from '../workspace.js';
|
|
7
|
+
import { renderPrompt } from '../prompt.js';
|
|
8
|
+
import { SmolvmClient } from './smolvm.js';
|
|
9
|
+
import { AcpClient } from './acp.js';
|
|
10
|
+
import { ADAPTERS, deriveAcpCommand, isKnownAdapter, stageCredential, } from './adapters.js';
|
|
11
|
+
import { withIssue } from '../logging.js';
|
|
12
|
+
const CONTINUATION_PROMPT_WITH_MCP = 'Continue working on the same issue. Pick up where the prior turn left off and proceed with the next concrete action. If the work is fully complete, summarize what changed and call the symphony.mark_done tool.';
|
|
13
|
+
const CONTINUATION_PROMPT_NO_MCP = 'Continue working on the same issue. Pick up where the prior turn left off and proceed with the next concrete action. If the work is fully complete, summarize what changed and stop.';
|
|
14
|
+
function continuationPrompt(mcpEnabled) {
|
|
15
|
+
return mcpEnabled ? CONTINUATION_PROMPT_WITH_MCP : CONTINUATION_PROMPT_NO_MCP;
|
|
16
|
+
}
|
|
17
|
+
function buildSteeringReplyPrompt(question, context, reply) {
|
|
18
|
+
const ctxBlock = context && context.length > 0 ? `\n\nContext you provided:\n${context}` : '';
|
|
19
|
+
return [
|
|
20
|
+
'The human operator has responded to your steering request.',
|
|
21
|
+
'',
|
|
22
|
+
'Your question was:',
|
|
23
|
+
question,
|
|
24
|
+
ctxBlock,
|
|
25
|
+
'',
|
|
26
|
+
'The human responded:',
|
|
27
|
+
reply,
|
|
28
|
+
'',
|
|
29
|
+
'Continue work on the issue, taking the human response into account. If the work is fully complete, call symphony.mark_done. If you need to ask another question, call symphony.request_human_steering again.',
|
|
30
|
+
]
|
|
31
|
+
.join('\n')
|
|
32
|
+
.replace(/\n{3,}/g, '\n\n');
|
|
33
|
+
}
|
|
34
|
+
export class AgentRunner {
|
|
35
|
+
cfg;
|
|
36
|
+
workflow;
|
|
37
|
+
workspaces;
|
|
38
|
+
tracker;
|
|
39
|
+
smolvm;
|
|
40
|
+
events;
|
|
41
|
+
mcp;
|
|
42
|
+
constructor(cfg, workflow, workspaces, tracker, smolvm, events, mcp = null) {
|
|
43
|
+
this.cfg = cfg;
|
|
44
|
+
this.workflow = workflow;
|
|
45
|
+
this.workspaces = workspaces;
|
|
46
|
+
this.tracker = tracker;
|
|
47
|
+
this.smolvm = smolvm;
|
|
48
|
+
this.events = events;
|
|
49
|
+
this.mcp = mcp;
|
|
50
|
+
}
|
|
51
|
+
updateConfig(cfg, workflow) {
|
|
52
|
+
this.cfg = cfg;
|
|
53
|
+
this.workflow = workflow;
|
|
54
|
+
}
|
|
55
|
+
setMcpRegistry(mcp) {
|
|
56
|
+
this.mcp = mcp;
|
|
57
|
+
}
|
|
58
|
+
vmNameFor(issue) {
|
|
59
|
+
return `symphony-${sanitizeWorkspaceKey(issue.identifier)}`.toLowerCase();
|
|
60
|
+
}
|
|
61
|
+
async runAttempt(issue, attempt, cancelSignal, runningEntry) {
|
|
62
|
+
const logger = withIssue({ issue_id: issue.id, issue_identifier: issue.identifier });
|
|
63
|
+
let workspace;
|
|
64
|
+
try {
|
|
65
|
+
workspace = await this.workspaces.ensureFor(issue.identifier);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
logger.error('workspace error', { error: err.message });
|
|
69
|
+
return { ok: false, reason: 'workspace error', threadId: null, turnsCompleted: 0 };
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
await this.workspaces.runBeforeRun(workspace.path, this.cfg.hooks);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
logger.error('before_run hook failed', { error: err.message });
|
|
76
|
+
return { ok: false, reason: 'before_run hook error', threadId: null, turnsCompleted: 0 };
|
|
77
|
+
}
|
|
78
|
+
// Resolve which adapter binary to launch and how to feed it credentials. Two
|
|
79
|
+
// paths:
|
|
80
|
+
// 1. acp.command is set in WORKFLOW.md → use it verbatim (operator owns
|
|
81
|
+
// credential handling; symphony stays out of the way).
|
|
82
|
+
// 2. acp.command is null → look up the adapter profile, stage the host
|
|
83
|
+
// credential into the workspace, and synthesize a launch command that
|
|
84
|
+
// copies the cred into the adapter's expected location and exec's the
|
|
85
|
+
// adapter binary.
|
|
86
|
+
let effectiveAcpCommand;
|
|
87
|
+
if (this.cfg.acp.command !== null) {
|
|
88
|
+
effectiveAcpCommand = this.cfg.acp.command;
|
|
89
|
+
}
|
|
90
|
+
else if (isKnownAdapter(this.cfg.acp.adapter)) {
|
|
91
|
+
const profile = ADAPTERS[this.cfg.acp.adapter];
|
|
92
|
+
let staged;
|
|
93
|
+
try {
|
|
94
|
+
staged = await stageCredential(workspace.path, profile);
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
logger.error('credential staging failed', {
|
|
98
|
+
adapter: profile.id,
|
|
99
|
+
error: err.message,
|
|
100
|
+
});
|
|
101
|
+
await this.workspaces.runAfterRunBestEffort(workspace.path, this.cfg.hooks);
|
|
102
|
+
return { ok: false, reason: 'credential staging error', threadId: null, turnsCompleted: 0 };
|
|
103
|
+
}
|
|
104
|
+
effectiveAcpCommand = deriveAcpCommand(profile, staged.relPath);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// validateDispatch should have caught this, but defend in depth.
|
|
108
|
+
logger.error('no acp launch path', { adapter: this.cfg.acp.adapter });
|
|
109
|
+
return { ok: false, reason: 'no acp launch path configured', threadId: null, turnsCompleted: 0 };
|
|
110
|
+
}
|
|
111
|
+
const vmName = this.vmNameFor(issue);
|
|
112
|
+
const mounts = [
|
|
113
|
+
{ host: workspace.path, guest: workspace.path, readonly: false },
|
|
114
|
+
];
|
|
115
|
+
if (this.cfg.smolvm.bin_path) {
|
|
116
|
+
mounts.push({ host: this.cfg.smolvm.bin_path, guest: '/opt/codex', readonly: true });
|
|
117
|
+
}
|
|
118
|
+
for (const v of this.cfg.smolvm.volumes) {
|
|
119
|
+
mounts.push({ host: v.host, guest: v.guest, readonly: v.readonly });
|
|
120
|
+
}
|
|
121
|
+
const env = {};
|
|
122
|
+
for (const k of this.cfg.smolvm.forward_env) {
|
|
123
|
+
const v = process.env[k];
|
|
124
|
+
if (v && v.length > 0)
|
|
125
|
+
env[k] = v;
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
await this.smolvm.ensureRunning(vmName, {
|
|
129
|
+
image: this.cfg.smolvm.image,
|
|
130
|
+
from: this.cfg.smolvm.from,
|
|
131
|
+
cpus: this.cfg.smolvm.cpus,
|
|
132
|
+
memMib: this.cfg.smolvm.mem_mib,
|
|
133
|
+
net: this.cfg.smolvm.net,
|
|
134
|
+
mounts,
|
|
135
|
+
env,
|
|
136
|
+
workdir: workspace.path,
|
|
137
|
+
sshAgent: false,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
logger.error('smolvm bring-up failed', { error: err.message });
|
|
142
|
+
await this.workspaces.runAfterRunBestEffort(workspace.path, this.cfg.hooks);
|
|
143
|
+
return { ok: false, reason: 'smolvm bring-up error', threadId: null, turnsCompleted: 0 };
|
|
144
|
+
}
|
|
145
|
+
const execStream = this.smolvm.execInteractive(vmName, {
|
|
146
|
+
command: [this.cfg.acp.shell, '-lc', effectiveAcpCommand],
|
|
147
|
+
workdir: workspace.path,
|
|
148
|
+
env: {},
|
|
149
|
+
timeoutMs: null,
|
|
150
|
+
});
|
|
151
|
+
const cleanup = async (reason) => {
|
|
152
|
+
try {
|
|
153
|
+
execStream.kill();
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
/* ignore */
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
await execStream.exit;
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
/* ignore */
|
|
163
|
+
}
|
|
164
|
+
if (this.mcp && runningEntry) {
|
|
165
|
+
this.mcp.deactivate(runningEntry.identifier);
|
|
166
|
+
}
|
|
167
|
+
logger.debug('agent runner cleanup', { reason });
|
|
168
|
+
await this.workspaces.runAfterRunBestEffort(workspace.path, this.cfg.hooks);
|
|
169
|
+
};
|
|
170
|
+
const onCancel = () => {
|
|
171
|
+
if (cancelSignal.cancelled) {
|
|
172
|
+
client.cancel().catch(() => undefined);
|
|
173
|
+
execStream.kill();
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const cancelCheckTimer = setInterval(onCancel, 500);
|
|
177
|
+
// Register with the MCP registry so the agent's tool calls can be routed back.
|
|
178
|
+
// MCP is required for symphony operations: mark_done is the only way for the agent
|
|
179
|
+
// to signal completion, and request_human_steering is the only way to defer to a
|
|
180
|
+
// human. If we can't construct a reachable URL — no bound HTTP port and no explicit
|
|
181
|
+
// override — we abort the attempt rather than dispatch a tool-less agent.
|
|
182
|
+
const mcpServers = [];
|
|
183
|
+
if (this.cfg.mcp.enabled && runningEntry) {
|
|
184
|
+
if (!this.mcp) {
|
|
185
|
+
clearInterval(cancelCheckTimer);
|
|
186
|
+
await cleanup('mcp_registry_unavailable');
|
|
187
|
+
logger.error('mcp is required but no registry is wired into the runner', {});
|
|
188
|
+
return {
|
|
189
|
+
ok: false,
|
|
190
|
+
reason: 'mcp required but registry unavailable',
|
|
191
|
+
threadId: null,
|
|
192
|
+
turnsCompleted: 0,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
const url = this.mcp.buildUrl(runningEntry.identifier, {
|
|
196
|
+
host: this.cfg.mcp.host,
|
|
197
|
+
explicit_host_url: this.cfg.mcp.explicit_host_url,
|
|
198
|
+
});
|
|
199
|
+
if (!url) {
|
|
200
|
+
clearInterval(cancelCheckTimer);
|
|
201
|
+
await cleanup('mcp_url_unavailable');
|
|
202
|
+
logger.error('mcp is required but no reachable URL is configured', {
|
|
203
|
+
host: this.cfg.mcp.host,
|
|
204
|
+
explicit_host_url: this.cfg.mcp.explicit_host_url,
|
|
205
|
+
});
|
|
206
|
+
return {
|
|
207
|
+
ok: false,
|
|
208
|
+
reason: 'mcp required but URL unavailable (start the HTTP server or set mcp.host_url)',
|
|
209
|
+
threadId: null,
|
|
210
|
+
turnsCompleted: 0,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
const token = this.mcp.activate(runningEntry);
|
|
214
|
+
mcpServers.push({
|
|
215
|
+
type: 'http',
|
|
216
|
+
name: 'symphony',
|
|
217
|
+
url,
|
|
218
|
+
headers: [{ name: 'Authorization', value: `Bearer ${token}` }],
|
|
219
|
+
});
|
|
220
|
+
logger.debug('mcp registered', { url });
|
|
221
|
+
}
|
|
222
|
+
const client = new AcpClient({
|
|
223
|
+
stdin: execStream.stdin,
|
|
224
|
+
stdout: execStream.stdout,
|
|
225
|
+
stderr: execStream.stderr,
|
|
226
|
+
cwd: workspace.path,
|
|
227
|
+
readTimeoutMs: this.cfg.acp.read_timeout_ms,
|
|
228
|
+
promptTimeoutMs: this.cfg.acp.prompt_timeout_ms,
|
|
229
|
+
onEvent: (event) => this.events.onRuntimeEvent(issue.id, event),
|
|
230
|
+
onTokenUsage: (u) => this.events.onTokenUsage(issue.id, u),
|
|
231
|
+
mcpServers,
|
|
232
|
+
});
|
|
233
|
+
let sessionId;
|
|
234
|
+
try {
|
|
235
|
+
const sess = await client.initSession();
|
|
236
|
+
sessionId = sess.sessionId;
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
clearInterval(cancelCheckTimer);
|
|
240
|
+
logger.error('acp init failed', {
|
|
241
|
+
error: err.message,
|
|
242
|
+
adapter: this.cfg.acp.adapter,
|
|
243
|
+
});
|
|
244
|
+
this.events.onRuntimeEvent(issue.id, {
|
|
245
|
+
at: new Date().toISOString(),
|
|
246
|
+
event: 'startup_failed',
|
|
247
|
+
message: err.message,
|
|
248
|
+
});
|
|
249
|
+
await cleanup('init_failed');
|
|
250
|
+
return { ok: false, reason: 'agent session startup error', threadId: null, turnsCompleted: 0 };
|
|
251
|
+
}
|
|
252
|
+
this.events.onSessionStarted?.({
|
|
253
|
+
issueId: issue.id,
|
|
254
|
+
sessionId,
|
|
255
|
+
threadId: sessionId,
|
|
256
|
+
pid: execStream.pid ? String(execStream.pid) : null,
|
|
257
|
+
});
|
|
258
|
+
let turnsCompleted = 0;
|
|
259
|
+
let autonomousTurns = 0;
|
|
260
|
+
let lastReason = 'unknown';
|
|
261
|
+
let agentFailure = null;
|
|
262
|
+
let currentIssue = issue;
|
|
263
|
+
let pendingSteering = null;
|
|
264
|
+
let firstTurn = true;
|
|
265
|
+
const activeStates = new Set(this.cfg.tracker.active_states.map((s) => s.toLowerCase()));
|
|
266
|
+
// Decoupled from max_turns: the loop runs as long as the agent keeps engaging. Only
|
|
267
|
+
// autonomous turns (turns without a pending human reply) count against max_turns.
|
|
268
|
+
// Turns driven by a human steering reply run free; the human is in the loop and can
|
|
269
|
+
// stop work at any time by walking away or by giving an instruction that ends in
|
|
270
|
+
// mark_done.
|
|
271
|
+
while (true) {
|
|
272
|
+
if (cancelSignal.cancelled) {
|
|
273
|
+
lastReason = 'cancelled_by_reconciliation';
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
let prompt;
|
|
277
|
+
const isSteeringReply = pendingSteering !== null;
|
|
278
|
+
try {
|
|
279
|
+
if (pendingSteering) {
|
|
280
|
+
prompt = buildSteeringReplyPrompt(pendingSteering.question, pendingSteering.context, pendingSteering.reply);
|
|
281
|
+
pendingSteering = null;
|
|
282
|
+
}
|
|
283
|
+
else if (firstTurn) {
|
|
284
|
+
prompt = await renderPrompt({
|
|
285
|
+
template: this.workflow.prompt_template,
|
|
286
|
+
issue: currentIssue,
|
|
287
|
+
attempt: attempt === null ? null : attempt,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
prompt = continuationPrompt(this.cfg.mcp.enabled);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
catch (err) {
|
|
295
|
+
clearInterval(cancelCheckTimer);
|
|
296
|
+
logger.error('prompt rendering failed', { error: err.message });
|
|
297
|
+
await cleanup('prompt_error');
|
|
298
|
+
return { ok: false, reason: 'prompt error', threadId: sessionId, turnsCompleted };
|
|
299
|
+
}
|
|
300
|
+
firstTurn = false;
|
|
301
|
+
// Label is the 1-based ordinal of the turn about to run, counting every turn
|
|
302
|
+
// (autonomous + steering reply), so the running snapshot never shows duplicate
|
|
303
|
+
// turn_count values across a steering boundary.
|
|
304
|
+
this.events.onTurn(issue.id, turnsCompleted + 1);
|
|
305
|
+
const outcome = await client.runPrompt(prompt);
|
|
306
|
+
if (outcome.reason !== 'end_turn') {
|
|
307
|
+
// mark_done is authoritative: if the agent moved the issue to a terminal state
|
|
308
|
+
// mid-turn, reconcile may have tripped cancelSignal before the prompt returned.
|
|
309
|
+
// The work is done regardless of how the prompt ended; honor that.
|
|
310
|
+
if (runningEntry?.marked_done) {
|
|
311
|
+
lastReason = 'agent_marked_done';
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
lastReason = outcome.reason;
|
|
315
|
+
agentFailure = `agent turn ${outcome.reason}: ${outcome.message}`;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
turnsCompleted++;
|
|
319
|
+
// Count this completed turn against max_turns iff it was an autonomous turn (i.e.
|
|
320
|
+
// not itself a reply to a human steering message). Steering-reply turns are free.
|
|
321
|
+
// Steering-REQUEST turns (autonomous turns that called request_human_steering)
|
|
322
|
+
// still count: the agent did autonomous work before deferring to a human.
|
|
323
|
+
if (!isSteeringReply) {
|
|
324
|
+
autonomousTurns++;
|
|
325
|
+
}
|
|
326
|
+
// Tool-driven exits: the MCP handler has already done the work; we just read the flag.
|
|
327
|
+
if (runningEntry?.marked_done) {
|
|
328
|
+
lastReason = 'agent_marked_done';
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
// Steering: pause the autonomous loop and wait for a human reply. The wait does not
|
|
332
|
+
// count against max_turns; cancellation breaks us out via the registry's cancel-aware
|
|
333
|
+
// resolver. The next iteration uses the steering-reply prompt.
|
|
334
|
+
if (runningEntry?.steering_requested && this.mcp) {
|
|
335
|
+
const question = runningEntry.steering_question ?? '';
|
|
336
|
+
const ctx = runningEntry.steering_context;
|
|
337
|
+
this.events.onRuntimeEvent(issue.id, {
|
|
338
|
+
at: new Date().toISOString(),
|
|
339
|
+
event: 'awaiting_human_steering',
|
|
340
|
+
message: question.length > 240 ? question.slice(0, 240) + '…' : question,
|
|
341
|
+
});
|
|
342
|
+
const reply = await this.mcp.awaitSteeringReply(issue.identifier, cancelSignal);
|
|
343
|
+
if (reply === null) {
|
|
344
|
+
lastReason = 'cancelled_while_awaiting_steering';
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
runningEntry.steering_requested = false;
|
|
348
|
+
runningEntry.steering_question = null;
|
|
349
|
+
runningEntry.steering_context = null;
|
|
350
|
+
pendingSteering = { question, context: ctx, reply };
|
|
351
|
+
this.events.onRuntimeEvent(issue.id, {
|
|
352
|
+
at: new Date().toISOString(),
|
|
353
|
+
event: 'human_steering_received',
|
|
354
|
+
message: reply.length > 240 ? reply.slice(0, 240) + '…' : reply,
|
|
355
|
+
});
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
// Autonomous turn finished without a tool-driven exit. Refresh tracker state and
|
|
359
|
+
// decide whether to continue.
|
|
360
|
+
let refreshed;
|
|
361
|
+
try {
|
|
362
|
+
refreshed = await this.tracker.fetchIssueStatesByIds([issue.id]);
|
|
363
|
+
}
|
|
364
|
+
catch (err) {
|
|
365
|
+
clearInterval(cancelCheckTimer);
|
|
366
|
+
logger.error('issue state refresh failed', { error: err.message });
|
|
367
|
+
await cleanup('issue_state_refresh_failed');
|
|
368
|
+
return { ok: false, reason: 'issue state refresh error', threadId: sessionId, turnsCompleted };
|
|
369
|
+
}
|
|
370
|
+
const found = refreshed[0];
|
|
371
|
+
if (!found) {
|
|
372
|
+
lastReason = 'issue_no_longer_present';
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
currentIssue = found;
|
|
376
|
+
if (!activeStates.has(found.state.toLowerCase())) {
|
|
377
|
+
lastReason = 'issue_no_longer_active';
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
380
|
+
if (autonomousTurns >= this.cfg.agent.max_turns) {
|
|
381
|
+
lastReason = 'max_turns_reached';
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
384
|
+
await delay(25);
|
|
385
|
+
}
|
|
386
|
+
clearInterval(cancelCheckTimer);
|
|
387
|
+
await cleanup(lastReason);
|
|
388
|
+
if (agentFailure) {
|
|
389
|
+
return { ok: false, reason: agentFailure, threadId: sessionId, turnsCompleted };
|
|
390
|
+
}
|
|
391
|
+
return { ok: true, reason: lastReason, threadId: sessionId, turnsCompleted };
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/agent/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// Thin wrapper around the smolvm CLI for per-issue microVM isolation.
|
|
2
|
+
//
|
|
3
|
+
// We use the local `smolvm` binary because the npm package is a stub and the HTTP API does
|
|
4
|
+
// not support bidirectional stdio for `machine exec`. The CLI form `machine exec -i` exposes
|
|
5
|
+
// the VM-process stdin/stdout directly, which is exactly what the Codex app-server JSON-RPC
|
|
6
|
+
// transport needs.
|
|
7
|
+
import { spawn } from 'node:child_process';
|
|
8
|
+
import { promisify } from 'node:util';
|
|
9
|
+
import { execFile as execFileCb } from 'node:child_process';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
import { log } from '../logging.js';
|
|
12
|
+
const execFile = promisify(execFileCb);
|
|
13
|
+
export class SmolvmError extends Error {
|
|
14
|
+
code;
|
|
15
|
+
constructor(code, message) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.code = code;
|
|
18
|
+
this.name = 'SmolvmError';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class SmolvmClient {
|
|
22
|
+
cfg;
|
|
23
|
+
constructor(cfg) {
|
|
24
|
+
this.cfg = cfg;
|
|
25
|
+
}
|
|
26
|
+
// The smolvm binary is invoked directly. The endpoint config is reserved for a future HTTP
|
|
27
|
+
// transport but is not threaded through the CLI today — the CLI talks to the local daemon
|
|
28
|
+
// automatically.
|
|
29
|
+
// Redact secret-bearing argv values before logging. `--env KEY=value` carries forwarded
|
|
30
|
+
// tokens (OPENAI_API_KEY, ANTHROPIC_API_KEY, …) and must never reach stderr or log sinks.
|
|
31
|
+
redactArgv(args) {
|
|
32
|
+
const out = [];
|
|
33
|
+
for (let i = 0; i < args.length; i++) {
|
|
34
|
+
const a = args[i];
|
|
35
|
+
if (a === '--env' || a === '-e') {
|
|
36
|
+
out.push(a);
|
|
37
|
+
const next = args[i + 1];
|
|
38
|
+
if (next !== undefined) {
|
|
39
|
+
const eq = next.indexOf('=');
|
|
40
|
+
out.push(eq >= 0 ? `${next.slice(0, eq)}=<redacted>` : next);
|
|
41
|
+
i += 1;
|
|
42
|
+
}
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
out.push(a);
|
|
46
|
+
}
|
|
47
|
+
return out.join(' ');
|
|
48
|
+
}
|
|
49
|
+
async run(args, opts = {}) {
|
|
50
|
+
log.debug('smolvm cli', { argv: this.redactArgv(args) });
|
|
51
|
+
try {
|
|
52
|
+
const { stdout, stderr } = await execFile('smolvm', args, {
|
|
53
|
+
maxBuffer: 32 * 1024 * 1024,
|
|
54
|
+
timeout: opts.timeoutMs,
|
|
55
|
+
});
|
|
56
|
+
return { stdout, stderr };
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
const e = err;
|
|
60
|
+
throw new SmolvmError('smolvm_cli_failed', `smolvm ${args.join(' ')} failed: ${e.stderr ?? e.message ?? e.code ?? 'unknown'}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async exists(name) {
|
|
64
|
+
try {
|
|
65
|
+
const { stdout } = await this.run(['machine', 'ls', '--json'], { timeoutMs: 10_000 });
|
|
66
|
+
const parsed = JSON.parse(stdout);
|
|
67
|
+
const list = Array.isArray(parsed) ? parsed : parsed.machines ?? [];
|
|
68
|
+
return list.some((m) => m.name === name);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async create(name, opts) {
|
|
75
|
+
const args = ['machine', 'create', name];
|
|
76
|
+
if (opts.from) {
|
|
77
|
+
args.push('--from', opts.from);
|
|
78
|
+
}
|
|
79
|
+
else if (opts.image) {
|
|
80
|
+
args.push('--image', opts.image);
|
|
81
|
+
}
|
|
82
|
+
args.push('--cpus', String(opts.cpus));
|
|
83
|
+
args.push('--mem', String(opts.memMib));
|
|
84
|
+
if (opts.net)
|
|
85
|
+
args.push('--net');
|
|
86
|
+
if (opts.sshAgent)
|
|
87
|
+
args.push('--ssh-agent');
|
|
88
|
+
if (opts.workdir)
|
|
89
|
+
args.push('--workdir', opts.workdir);
|
|
90
|
+
for (const m of opts.mounts) {
|
|
91
|
+
const spec = `${path.resolve(m.host)}:${m.guest}${m.readonly ? ':ro' : ''}`;
|
|
92
|
+
args.push('--volume', spec);
|
|
93
|
+
}
|
|
94
|
+
for (const [k, v] of Object.entries(opts.env)) {
|
|
95
|
+
args.push('--env', `${k}=${v}`);
|
|
96
|
+
}
|
|
97
|
+
await this.run(args, { timeoutMs: 120_000 });
|
|
98
|
+
}
|
|
99
|
+
async start(name) {
|
|
100
|
+
await this.run(['machine', 'start', '--name', name], { timeoutMs: 60_000 });
|
|
101
|
+
}
|
|
102
|
+
async stop(name) {
|
|
103
|
+
try {
|
|
104
|
+
await this.run(['machine', 'stop', '--name', name], { timeoutMs: 30_000 });
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
log.warn('smolvm stop failed', { name, error: err.message });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async destroy(name) {
|
|
111
|
+
try {
|
|
112
|
+
await this.run(['machine', 'delete', name, '-f'], { timeoutMs: 30_000 });
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
log.warn('smolvm delete failed', { name, error: err.message });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async ensureRunning(name, opts) {
|
|
119
|
+
const exists = await this.exists(name);
|
|
120
|
+
if (!exists) {
|
|
121
|
+
await this.create(name, opts);
|
|
122
|
+
}
|
|
123
|
+
await this.start(name);
|
|
124
|
+
}
|
|
125
|
+
// Spawn an interactive exec session inside the VM. Returns a ChildProcessByStdio with all
|
|
126
|
+
// three stdio streams piped, which is suitable for stdio JSON-RPC.
|
|
127
|
+
execInteractive(name, opts) {
|
|
128
|
+
const args = ['machine', 'exec', '--name', name, '-i'];
|
|
129
|
+
if (opts.workdir)
|
|
130
|
+
args.push('--workdir', opts.workdir);
|
|
131
|
+
for (const [k, v] of Object.entries(opts.env)) {
|
|
132
|
+
args.push('--env', `${k}=${v}`);
|
|
133
|
+
}
|
|
134
|
+
if (opts.timeoutMs && opts.timeoutMs > 0) {
|
|
135
|
+
args.push('--timeout', `${opts.timeoutMs}ms`);
|
|
136
|
+
}
|
|
137
|
+
args.push('--', ...opts.command);
|
|
138
|
+
const child = spawn('smolvm', args, {
|
|
139
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
140
|
+
});
|
|
141
|
+
const exit = new Promise((resolve) => {
|
|
142
|
+
child.on('close', (code, signal) => resolve({ code: code, signal: signal ?? null }));
|
|
143
|
+
});
|
|
144
|
+
let killed = false;
|
|
145
|
+
return {
|
|
146
|
+
child,
|
|
147
|
+
stdin: child.stdin,
|
|
148
|
+
stdout: child.stdout,
|
|
149
|
+
stderr: child.stderr,
|
|
150
|
+
pid: child.pid,
|
|
151
|
+
exit,
|
|
152
|
+
kill: () => {
|
|
153
|
+
if (killed)
|
|
154
|
+
return;
|
|
155
|
+
killed = true;
|
|
156
|
+
try {
|
|
157
|
+
child.kill('SIGTERM');
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// ignore
|
|
161
|
+
}
|
|
162
|
+
setTimeout(() => {
|
|
163
|
+
try {
|
|
164
|
+
child.kill('SIGKILL');
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// ignore
|
|
168
|
+
}
|
|
169
|
+
}, 3_000).unref();
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=smolvm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smolvm.js","sourceRoot":"","sources":["../../src/agent/smolvm.ts"],"names":[],"mappings":"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"}
|