@tangle-network/agent-runtime 0.73.0 → 0.75.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/dist/agent.d.ts +34 -2
- package/dist/agent.js +3 -2
- package/dist/agent.js.map +1 -1
- package/dist/analyst-loop.d.ts +1 -1
- package/dist/chunk-JPURCA2O.js +266 -0
- package/dist/chunk-JPURCA2O.js.map +1 -0
- package/dist/{chunk-7ODB76J5.js → chunk-MRWXCFV5.js} +2 -2
- package/dist/chunk-O2UPHN7X.js +114 -0
- package/dist/chunk-O2UPHN7X.js.map +1 -0
- package/dist/{chunk-U56XGKVY.js → chunk-QKNBYHMK.js} +3 -3
- package/dist/{chunk-HPYWEFVY.js → chunk-SA5GCF2X.js} +2 -2
- package/dist/{chunk-NCH4XUZ7.js → chunk-ZKMOIEOB.js} +13 -119
- package/dist/chunk-ZKMOIEOB.js.map +1 -0
- package/dist/{coordination-DU0saWeg.d.ts → coordination-DEVknvQo.d.ts} +3 -2
- package/dist/generator-YkAQrOoD.d.ts +382 -0
- package/dist/index.d.ts +13 -167
- package/dist/index.js +16 -264
- package/dist/index.js.map +1 -1
- package/dist/intelligence.d.ts +1 -1
- package/dist/lifecycle.d.ts +788 -200
- package/dist/lifecycle.js +814 -9
- package/dist/lifecycle.js.map +1 -1
- package/dist/local-harness-BE_h8szs.d.ts +93 -0
- package/dist/{loop-runner-bin-eD3m0rHW.d.ts → loop-runner-bin-BPthX22l.d.ts} +2 -2
- package/dist/loop-runner-bin.d.ts +6 -5
- package/dist/loop-runner-bin.js +4 -3
- package/dist/loops.d.ts +10 -9
- package/dist/loops.js +3 -2
- package/dist/mcp/bin.js +2 -1
- package/dist/mcp/bin.js.map +1 -1
- package/dist/mcp/index.d.ts +8 -6
- package/dist/mcp/index.js +6 -4
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp-serve-verifier-CT1KLTG_.d.ts +162 -0
- package/dist/{openai-tools-CBurv8Cu.d.ts → openai-tools-D-VCAEmw.d.ts} +1 -1
- package/dist/profiles.d.ts +1 -1
- package/dist/{types-JufmXF2a.d.ts → types-YimN9PQP.d.ts} +1 -1
- package/dist/{worktree-DaxOvw-C.d.ts → worktree-CtuEQ7bZ.d.ts} +2 -93
- package/dist/{worktree-fanout-DIffZohV.d.ts → worktree-fanout-Cdez8GR7.d.ts} +3 -2
- package/package.json +3 -3
- package/dist/chunk-NCH4XUZ7.js.map +0 -1
- /package/dist/{chunk-7ODB76J5.js.map → chunk-MRWXCFV5.js.map} +0 -0
- /package/dist/{chunk-U56XGKVY.js.map → chunk-QKNBYHMK.js.map} +0 -0
- /package/dist/{chunk-HPYWEFVY.js.map → chunk-SA5GCF2X.js.map} +0 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import {
|
|
2
|
+
runLocalHarness
|
|
3
|
+
} from "./chunk-O2UPHN7X.js";
|
|
4
|
+
|
|
5
|
+
// src/improvement/agentic-generator.ts
|
|
6
|
+
import { spawnSync } from "child_process";
|
|
7
|
+
function agenticGenerator(opts = {}) {
|
|
8
|
+
const harness = opts.harness ?? "claude";
|
|
9
|
+
const buildPrompt = opts.buildPrompt ?? defaultBuildPrompt;
|
|
10
|
+
const run = opts.runHarness ?? runLocalHarness;
|
|
11
|
+
const dirty = opts.isDirty ?? worktreeDirty;
|
|
12
|
+
const verify = opts.verify;
|
|
13
|
+
return {
|
|
14
|
+
kind: `agentic:${harness}`,
|
|
15
|
+
async generate({ worktreePath, report, findings, maxShots, signal }) {
|
|
16
|
+
const basePrompt = buildPrompt({ report, findings });
|
|
17
|
+
const shots = Math.max(1, maxShots);
|
|
18
|
+
let attemptNote = "";
|
|
19
|
+
for (let shot = 0; shot < shots; shot++) {
|
|
20
|
+
if (signal.aborted) break;
|
|
21
|
+
await run({
|
|
22
|
+
harness,
|
|
23
|
+
cwd: worktreePath,
|
|
24
|
+
taskPrompt: attemptNote ? `${basePrompt}
|
|
25
|
+
|
|
26
|
+
${attemptNote}` : basePrompt,
|
|
27
|
+
timeoutMs: opts.timeoutMs,
|
|
28
|
+
signal
|
|
29
|
+
});
|
|
30
|
+
if (!dirty(worktreePath)) {
|
|
31
|
+
attemptNote = EMPTY_TREE_NOTE;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (!verify) {
|
|
35
|
+
return { applied: true, summary: summarize(findings) };
|
|
36
|
+
}
|
|
37
|
+
const result = await verify(worktreePath);
|
|
38
|
+
if (result.ok) {
|
|
39
|
+
return { applied: true, summary: summarize(findings) };
|
|
40
|
+
}
|
|
41
|
+
attemptNote = failureNote(result.feedback);
|
|
42
|
+
}
|
|
43
|
+
return { applied: false, summary: "" };
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function defaultBuildPrompt(args) {
|
|
48
|
+
const lines = [
|
|
49
|
+
"You are improving this codebase based on an evaluation analysis.",
|
|
50
|
+
"Make the smallest set of edits that addresses the findings below, then stop.",
|
|
51
|
+
"Do not change unrelated code. Do not commit \u2014 leave changes in the working tree.",
|
|
52
|
+
"",
|
|
53
|
+
"Findings:"
|
|
54
|
+
];
|
|
55
|
+
for (const f of args.findings) {
|
|
56
|
+
const where = f.subject ? ` [${f.subject}]` : "";
|
|
57
|
+
lines.push(`- (${f.severity})${where} ${f.claim}`);
|
|
58
|
+
if (f.recommended_action) lines.push(` \u2192 ${f.recommended_action}`);
|
|
59
|
+
}
|
|
60
|
+
return lines.join("\n");
|
|
61
|
+
}
|
|
62
|
+
var EMPTY_TREE_NOTE = "NOTE: your previous attempt left the working tree unchanged. Make the concrete file edits now.";
|
|
63
|
+
function failureNote(feedback) {
|
|
64
|
+
const detail = feedback?.trim();
|
|
65
|
+
return [
|
|
66
|
+
"NOTE: your edits are in the working tree but verification FAILED.",
|
|
67
|
+
"Fix the problem in place \u2014 build on your existing edits, do not revert them.",
|
|
68
|
+
detail ? `Verifier output:
|
|
69
|
+
${truncate(detail, 4e3)}` : "No verifier detail was captured."
|
|
70
|
+
].join("\n");
|
|
71
|
+
}
|
|
72
|
+
function commandVerifier(command, args = [], timeoutMs = 3e5) {
|
|
73
|
+
return (worktreePath) => {
|
|
74
|
+
const result = spawnSync(command, args, {
|
|
75
|
+
cwd: worktreePath,
|
|
76
|
+
encoding: "utf-8",
|
|
77
|
+
timeout: timeoutMs
|
|
78
|
+
});
|
|
79
|
+
if (result.signal) {
|
|
80
|
+
return {
|
|
81
|
+
ok: false,
|
|
82
|
+
feedback: `verifier '${command}' killed by ${result.signal} (likely timeout after ${timeoutMs}ms)`
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (result.error) {
|
|
86
|
+
const code = result.error.code;
|
|
87
|
+
if (code === "ENOENT") {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`commandVerifier: '${command}' not found in PATH (setup bug, not a failed candidate)`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
throw new Error(`commandVerifier: '${command}' failed to spawn: ${result.error.message}`);
|
|
93
|
+
}
|
|
94
|
+
if (result.status === 0) return { ok: true };
|
|
95
|
+
const out = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
|
|
96
|
+
return { ok: false, feedback: out.length > 0 ? out : `exit ${result.status}` };
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function summarize(findings) {
|
|
100
|
+
if (findings.length === 0) return "agentic improvement";
|
|
101
|
+
if (findings.length === 1) return `agentic: ${truncate(findings[0].claim, 64)}`;
|
|
102
|
+
return `agentic: ${findings.length} findings addressed`;
|
|
103
|
+
}
|
|
104
|
+
function truncate(s, n) {
|
|
105
|
+
return s.length <= n ? s : `${s.slice(0, n - 1)}\u2026`;
|
|
106
|
+
}
|
|
107
|
+
function worktreeDirty(worktreePath) {
|
|
108
|
+
const result = spawnSync("git", ["status", "--porcelain"], {
|
|
109
|
+
cwd: worktreePath,
|
|
110
|
+
encoding: "utf-8"
|
|
111
|
+
});
|
|
112
|
+
if (result.error) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`agenticGenerator: git status failed to spawn in ${worktreePath}: ${result.error.message}`
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
if (result.status !== 0) {
|
|
118
|
+
throw new Error(
|
|
119
|
+
`agenticGenerator: git status exited ${result.status} in ${worktreePath}: ${result.stderr.trim()}`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
return result.stdout.trim().length > 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/improvement/build-prompts.ts
|
|
126
|
+
function findingLines(findings) {
|
|
127
|
+
return findings.map((f) => {
|
|
128
|
+
const where = f.subject ? ` [${f.subject}]` : "";
|
|
129
|
+
const action = f.recommended_action ? ` \u2192 ${f.recommended_action}` : "";
|
|
130
|
+
return `- (${f.severity})${where} ${f.claim}${action}`;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function toolBuildPrompt(args) {
|
|
134
|
+
return [
|
|
135
|
+
"You are building a new TOOL for this codebase to address the gaps below.",
|
|
136
|
+
"Write the tool as a small, self-contained module PLUS tests that exercise it.",
|
|
137
|
+
"The tool must compile and its tests must pass \u2014 they will be run automatically;",
|
|
138
|
+
"if verification fails you will get the error and another attempt. Do not commit;",
|
|
139
|
+
"leave the changes in the working tree.",
|
|
140
|
+
"",
|
|
141
|
+
"Gaps the tool should close:",
|
|
142
|
+
...findingLines(args.findings)
|
|
143
|
+
].join("\n");
|
|
144
|
+
}
|
|
145
|
+
function mcpBuildPrompt(args) {
|
|
146
|
+
return [
|
|
147
|
+
"You are building a new MCP SERVER (Model Context Protocol) that exposes",
|
|
148
|
+
"tool(s) addressing the gaps below, so any harness can mount it.",
|
|
149
|
+
"Requirements that WILL be checked by booting the server:",
|
|
150
|
+
"- it starts over stdio and answers the MCP `initialize` handshake,",
|
|
151
|
+
"- `tools/list` returns at least one tool with a valid input schema.",
|
|
152
|
+
"Newline-delimited JSON-RPC 2.0, protocol version 2024-11-05. Include a start",
|
|
153
|
+
"command (e.g. a package.json `start` script or a clear entrypoint). If the",
|
|
154
|
+
"boot-and-probe fails you will get the error and another attempt. Do not",
|
|
155
|
+
"commit; leave the changes in the working tree.",
|
|
156
|
+
"",
|
|
157
|
+
"Capabilities the server should provide:",
|
|
158
|
+
...findingLines(args.findings)
|
|
159
|
+
].join("\n");
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// src/improvement/mcp-serve-verifier.ts
|
|
163
|
+
import { spawn } from "child_process";
|
|
164
|
+
import { createInterface } from "readline";
|
|
165
|
+
var PROTOCOL_VERSION = "2024-11-05";
|
|
166
|
+
function mcpServeVerifier(spec) {
|
|
167
|
+
const timeoutMs = spec.timeoutMs ?? 3e4;
|
|
168
|
+
const minTools = spec.minTools ?? 1;
|
|
169
|
+
return (worktreePath) => new Promise((resolve, reject) => {
|
|
170
|
+
const child = spawn(spec.command, spec.args ?? [], {
|
|
171
|
+
cwd: worktreePath,
|
|
172
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
173
|
+
env: { ...process.env, ...spec.env }
|
|
174
|
+
});
|
|
175
|
+
const stderr = [];
|
|
176
|
+
let settled = false;
|
|
177
|
+
let nextId = 1;
|
|
178
|
+
const initId = nextId++;
|
|
179
|
+
let listId = -1;
|
|
180
|
+
const settle = (fn) => {
|
|
181
|
+
if (settled) return;
|
|
182
|
+
settled = true;
|
|
183
|
+
clearTimeout(timer);
|
|
184
|
+
rl.close();
|
|
185
|
+
child.kill("SIGKILL");
|
|
186
|
+
fn();
|
|
187
|
+
};
|
|
188
|
+
const withStderr = (msg) => stderr.length > 0 ? `${msg}
|
|
189
|
+
stderr:
|
|
190
|
+
${stderr.join("").slice(-2e3)}` : msg;
|
|
191
|
+
const pass = () => settle(() => resolve({ ok: true }));
|
|
192
|
+
const failCandidate = (msg) => settle(() => resolve({ ok: false, feedback: withStderr(msg) }));
|
|
193
|
+
const setupFault = (err) => settle(() => reject(err));
|
|
194
|
+
const send = (msg) => {
|
|
195
|
+
try {
|
|
196
|
+
child.stdin.write(`${JSON.stringify(msg)}
|
|
197
|
+
`);
|
|
198
|
+
return true;
|
|
199
|
+
} catch (err) {
|
|
200
|
+
failCandidate(`writing to MCP server stdin failed: ${err.message}`);
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
child.on("error", (err) => {
|
|
205
|
+
const code = err.code;
|
|
206
|
+
setupFault(
|
|
207
|
+
code === "ENOENT" ? new Error(
|
|
208
|
+
`mcpServeVerifier: '${spec.command}' not found in PATH (setup bug, not a failed candidate)`
|
|
209
|
+
) : new Error(`mcpServeVerifier: '${spec.command}' failed to spawn: ${err.message}`)
|
|
210
|
+
);
|
|
211
|
+
});
|
|
212
|
+
child.on("exit", (code, signal) => {
|
|
213
|
+
failCandidate(`MCP server exited (code ${code}, signal ${signal}) before serving`);
|
|
214
|
+
});
|
|
215
|
+
child.stderr.on("data", (d) => stderr.push(String(d)));
|
|
216
|
+
const rl = createInterface({ input: child.stdout });
|
|
217
|
+
rl.on("line", (line) => {
|
|
218
|
+
let msg;
|
|
219
|
+
try {
|
|
220
|
+
msg = JSON.parse(line);
|
|
221
|
+
} catch {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (!msg || typeof msg !== "object") return;
|
|
225
|
+
if (msg.id === initId) {
|
|
226
|
+
if (msg.error) return failCandidate(`initialize errored: ${JSON.stringify(msg.error)}`);
|
|
227
|
+
if (!send({ jsonrpc: "2.0", method: "notifications/initialized" })) return;
|
|
228
|
+
listId = nextId++;
|
|
229
|
+
send({ jsonrpc: "2.0", id: listId, method: "tools/list" });
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if (msg.id === listId) {
|
|
233
|
+
if (msg.error) return failCandidate(`tools/list errored: ${JSON.stringify(msg.error)}`);
|
|
234
|
+
const tools = msg.result?.tools;
|
|
235
|
+
if (!Array.isArray(tools)) return failCandidate("tools/list result has no tools array");
|
|
236
|
+
if (tools.length < minTools) {
|
|
237
|
+
return failCandidate(`tools/list returned ${tools.length} tool(s), need >= ${minTools}`);
|
|
238
|
+
}
|
|
239
|
+
return pass();
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
const timer = setTimeout(
|
|
243
|
+
() => failCandidate(`MCP server did not complete the handshake within ${timeoutMs}ms`),
|
|
244
|
+
timeoutMs
|
|
245
|
+
);
|
|
246
|
+
send({
|
|
247
|
+
jsonrpc: "2.0",
|
|
248
|
+
id: initId,
|
|
249
|
+
method: "initialize",
|
|
250
|
+
params: {
|
|
251
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
252
|
+
capabilities: {},
|
|
253
|
+
clientInfo: { name: "agent-runtime-mcp-verify", version: "0" }
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export {
|
|
260
|
+
agenticGenerator,
|
|
261
|
+
commandVerifier,
|
|
262
|
+
toolBuildPrompt,
|
|
263
|
+
mcpBuildPrompt,
|
|
264
|
+
mcpServeVerifier
|
|
265
|
+
};
|
|
266
|
+
//# sourceMappingURL=chunk-JPURCA2O.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/improvement/agentic-generator.ts","../src/improvement/build-prompts.ts","../src/improvement/mcp-serve-verifier.ts"],"sourcesContent":["/**\n * @experimental\n *\n * `agenticGenerator` — the full-agentic `CandidateGenerator`: the\n * `shots=N, sandbox=on` setting of the one `improvementDriver`. It runs a real\n * coding harness (claude / codex / opencode) inside the candidate worktree the\n * driver already created, letting the agent read the codebase + the research\n * report and make the change in place. The driver then commits the worktree\n * into a `CodeSurface`.\n *\n * Mechanism: identical to the proven Phase-2.8 in-process executor — spawn the\n * harness as a subprocess with `cwd` = the worktree, on the same filesystem,\n * so edits land in place (no sandbox-mount round-trip). `runLocalHarness` is\n * the verified primitive. The OUTER sandbox is the improvement loop's own\n * execution context; the generator does not nest a second sandbox per\n * candidate (which would reintroduce a host↔sandbox worktree-transport\n * problem that does not need solving here).\n *\n * `maxShots` is the DEPTH dial — a multi-shot verify-in-session loop, NOT the\n * kernel `runLoop`. Each shot runs one full harness session in the (persistent)\n * worktree; between shots the loop refines based on what the last shot produced:\n * - empty tree → \"you changed nothing, make the edits\" → retry\n * - dirty + `verify` fails → feed the verifier's failure into the next shot\n * (the worktree persists, so the harness RESUMES atop its own failing\n * edits with the error in hand — no `--resume` session plumbing needed,\n * and harness-agnostic across claude/codex/opencode)\n * - dirty + `verify` ok (or no verifier configured) → return the candidate\n * A candidate that never verifies within `maxShots` is discarded (`applied:\n * false`), never shipped — if you configured a verifier, a non-passing tree is\n * not a candidate. With no verifier the legacy behavior holds: first dirty shot\n * is the candidate.\n */\n\nimport { spawnSync } from 'node:child_process'\nimport type { AnalystFinding } from '@tangle-network/agent-eval'\nimport { type LocalHarness, runLocalHarness } from '../mcp/local-harness'\nimport type { CandidateGenerator } from './improvement-driver'\n\n/** Outcome of verifying a candidate worktree. `feedback` (compiler errors,\n * failing test output) is fed into the next shot when `ok` is false. */\nexport interface VerifyResult {\n ok: boolean\n feedback?: string\n}\n\n/** Verifies the edited worktree. Sync or async; throws only on a setup fault\n * (a candidate that fails verification returns `{ok:false}`, it does not\n * throw). */\nexport type Verifier = (worktreePath: string) => Promise<VerifyResult> | VerifyResult\n\nexport interface AgenticGeneratorOptions {\n /** Local coding harness to run in the worktree. Default `claude`. */\n harness?: LocalHarness\n /** Per-shot wall-clock timeout (ms). Default = `runLocalHarness` default (5m). */\n timeoutMs?: number\n /** Build the harness task prompt from the report + findings. Override for\n * domain phrasing; the default turns findings into a concrete coder task. */\n buildPrompt?: (args: { report: unknown; findings: AnalystFinding[] }) => string\n /** Verify the worktree after each dirtying shot. When set, a candidate that\n * fails verification is NOT returned — the failure feeds the next shot\n * (verify-in-session), up to `maxShots`; a candidate that never verifies is\n * discarded (`applied:false`), never shipped. Omitted ⇒ legacy behavior:\n * the first dirty shot is the candidate. See `commandVerifier`. */\n verify?: Verifier\n /** Test seam — inject the harness runner (defaults to `runLocalHarness`). */\n runHarness?: typeof runLocalHarness\n /** Test seam — inject the worktree-dirty check (defaults to `git status`). */\n isDirty?: (worktreePath: string) => boolean\n}\n\nexport function agenticGenerator(opts: AgenticGeneratorOptions = {}): CandidateGenerator {\n const harness = opts.harness ?? 'claude'\n const buildPrompt = opts.buildPrompt ?? defaultBuildPrompt\n const run = opts.runHarness ?? runLocalHarness\n const dirty = opts.isDirty ?? worktreeDirty\n const verify = opts.verify\n\n return {\n kind: `agentic:${harness}`,\n async generate({ worktreePath, report, findings, maxShots, signal }) {\n const basePrompt = buildPrompt({ report, findings })\n const shots = Math.max(1, maxShots)\n // Feedback appended to the base prompt for the NEXT shot — empty on shot 0.\n let attemptNote = ''\n\n for (let shot = 0; shot < shots; shot++) {\n if (signal.aborted) break\n await run({\n harness,\n cwd: worktreePath,\n taskPrompt: attemptNote ? `${basePrompt}\\n\\n${attemptNote}` : basePrompt,\n timeoutMs: opts.timeoutMs,\n signal,\n })\n\n // The worktree IS the signal: no edits ⇒ tell the next shot to act.\n if (!dirty(worktreePath)) {\n attemptNote = EMPTY_TREE_NOTE\n continue\n }\n\n // Dirty: with no verifier the diff IS the candidate (we trust the diff,\n // not the harness's stdout). With a verifier the candidate must pass it.\n if (!verify) {\n return { applied: true, summary: summarize(findings) }\n }\n const result = await verify(worktreePath)\n if (result.ok) {\n return { applied: true, summary: summarize(findings) }\n }\n // Dirty but failing — resume next shot atop these edits with the error.\n attemptNote = failureNote(result.feedback)\n }\n\n // Shots exhausted: no verified candidate (or, sans verifier, no edits).\n return { applied: false, summary: '' }\n },\n }\n}\n\n/** Turn the analyst's findings (+ optional report) into a concrete coder task. */\nfunction defaultBuildPrompt(args: { report: unknown; findings: AnalystFinding[] }): string {\n const lines: string[] = [\n 'You are improving this codebase based on an evaluation analysis.',\n 'Make the smallest set of edits that addresses the findings below, then stop.',\n 'Do not change unrelated code. Do not commit — leave changes in the working tree.',\n '',\n 'Findings:',\n ]\n for (const f of args.findings) {\n const where = f.subject ? ` [${f.subject}]` : ''\n lines.push(`- (${f.severity})${where} ${f.claim}`)\n if (f.recommended_action) lines.push(` → ${f.recommended_action}`)\n }\n return lines.join('\\n')\n}\n\nconst EMPTY_TREE_NOTE =\n 'NOTE: your previous attempt left the working tree unchanged. Make the concrete file edits now.'\n\n/** Next-shot feedback when the worktree is dirty but failed verification. The\n * edits persist on disk, so the harness resumes atop them — tell it to fix in\n * place, not start over. Verifier detail is truncated to keep the prompt bounded. */\nfunction failureNote(feedback?: string): string {\n const detail = feedback?.trim()\n return [\n 'NOTE: your edits are in the working tree but verification FAILED.',\n 'Fix the problem in place — build on your existing edits, do not revert them.',\n detail ? `Verifier output:\\n${truncate(detail, 4000)}` : 'No verifier detail was captured.',\n ].join('\\n')\n}\n\n/** A `Verifier` that runs a command in the worktree: exit 0 ⇒ ok, any other\n * exit ⇒ failed with stdout+stderr as feedback. The common case — verify by\n * `tsc --noEmit`, `pnpm build`, or a test command. A timeout is treated as a\n * FAILED candidate (a change that hangs the build is a bad change); a missing\n * binary or spawn fault throws (a setup bug, not a failed candidate — no\n * silent fallback). */\nexport function commandVerifier(\n command: string,\n args: string[] = [],\n timeoutMs = 300_000,\n): Verifier {\n return (worktreePath: string): VerifyResult => {\n const result = spawnSync(command, args, {\n cwd: worktreePath,\n encoding: 'utf-8',\n timeout: timeoutMs,\n })\n if (result.signal) {\n return {\n ok: false,\n feedback: `verifier '${command}' killed by ${result.signal} (likely timeout after ${timeoutMs}ms)`,\n }\n }\n if (result.error) {\n const code = (result.error as NodeJS.ErrnoException).code\n if (code === 'ENOENT') {\n throw new Error(\n `commandVerifier: '${command}' not found in PATH (setup bug, not a failed candidate)`,\n )\n }\n throw new Error(`commandVerifier: '${command}' failed to spawn: ${result.error.message}`)\n }\n if (result.status === 0) return { ok: true }\n const out = `${result.stdout ?? ''}${result.stderr ?? ''}`.trim()\n return { ok: false, feedback: out.length > 0 ? out : `exit ${result.status}` }\n }\n}\n\n/** A one-line summary for the commit message, derived from the findings. */\nfunction summarize(findings: AnalystFinding[]): string {\n if (findings.length === 0) return 'agentic improvement'\n if (findings.length === 1) return `agentic: ${truncate(findings[0]!.claim, 64)}`\n return `agentic: ${findings.length} findings addressed`\n}\n\nfunction truncate(s: string, n: number): string {\n return s.length <= n ? s : `${s.slice(0, n - 1)}…`\n}\n\n/** Non-empty `git status --porcelain` ⇒ the harness changed the worktree.\n * Fails loud: the worktree is a fresh checkout, so a git error here means\n * something is genuinely broken (git missing, corrupt index, killed mid-run).\n * Folding that into `false` would silently discard a candidate and mask the\n * real failure — forbidden by the no-silent-fallbacks doctrine. */\nfunction worktreeDirty(worktreePath: string): boolean {\n const result = spawnSync('git', ['status', '--porcelain'], {\n cwd: worktreePath,\n encoding: 'utf-8',\n })\n if (result.error) {\n throw new Error(\n `agenticGenerator: git status failed to spawn in ${worktreePath}: ${result.error.message}`,\n )\n }\n if (result.status !== 0) {\n throw new Error(\n `agenticGenerator: git status exited ${result.status} in ${worktreePath}: ${result.stderr.trim()}`,\n )\n }\n return result.stdout.trim().length > 0\n}\n","/**\n * Build-prompt starting points for the two buildable artifact types. There is\n * NO `toolGenerator`/`mcpGenerator` wrapper — the factory is `agenticGenerator`\n * + a verifier (docs/artifact-lifecycle-frontier.md), so a tool or an MCP\n * server is built by composing the pieces directly:\n *\n * // a tool:\n * agenticGenerator({ buildPrompt: toolBuildPrompt, verify: commandVerifier('pnpm', ['test']) })\n * // an MCP server:\n * agenticGenerator({ buildPrompt: mcpBuildPrompt, verify: mcpServeVerifier({ command: 'node', args: ['server.mjs'] }) })\n *\n * These are the only type-specific bit (the phrasing that points the agent at a\n * tool vs. an MCP); the worktree, resume-on-failure loop, and improvement-loop\n * wrapper are shared. MCP is the load-bearing target — it is how a harness\n * acquires tools; raw tools matter where we control the loader.\n */\n\nimport type { AnalystFinding } from '@tangle-network/agent-eval'\n\ntype FindingsArg = { report: unknown; findings: AnalystFinding[] }\n\nfunction findingLines(findings: AnalystFinding[]): string[] {\n return findings.map((f) => {\n const where = f.subject ? ` [${f.subject}]` : ''\n const action = f.recommended_action ? ` → ${f.recommended_action}` : ''\n return `- (${f.severity})${where} ${f.claim}${action}`\n })\n}\n\nexport function toolBuildPrompt(args: FindingsArg): string {\n return [\n 'You are building a new TOOL for this codebase to address the gaps below.',\n 'Write the tool as a small, self-contained module PLUS tests that exercise it.',\n 'The tool must compile and its tests must pass — they will be run automatically;',\n 'if verification fails you will get the error and another attempt. Do not commit;',\n 'leave the changes in the working tree.',\n '',\n 'Gaps the tool should close:',\n ...findingLines(args.findings),\n ].join('\\n')\n}\n\nexport function mcpBuildPrompt(args: FindingsArg): string {\n return [\n 'You are building a new MCP SERVER (Model Context Protocol) that exposes',\n 'tool(s) addressing the gaps below, so any harness can mount it.',\n 'Requirements that WILL be checked by booting the server:',\n '- it starts over stdio and answers the MCP `initialize` handshake,',\n '- `tools/list` returns at least one tool with a valid input schema.',\n 'Newline-delimited JSON-RPC 2.0, protocol version 2024-11-05. Include a start',\n 'command (e.g. a package.json `start` script or a clear entrypoint). If the',\n 'boot-and-probe fails you will get the error and another attempt. Do not',\n 'commit; leave the changes in the working tree.',\n '',\n 'Capabilities the server should provide:',\n ...findingLines(args.findings),\n ].join('\\n')\n}\n","/**\n * `mcpServeVerifier` — the intrinsic verifier for a built MCP server: the\n * boot-and-probe checker named in docs/artifact-lifecycle-frontier.md. A\n * generated MCP server is only a candidate if it actually *serves* — so this\n * boots it over stdio (the default local MCP transport) and runs the real\n * handshake: `initialize` → `notifications/initialized` → `tools/list`, and\n * asserts the server answers with at least `minTools` tools.\n *\n * Outcomes follow the `Verifier` contract: a server that fails to start, exits\n * early, errors the handshake, times out, or exposes no tools is a FAILED\n * candidate (`{ok:false}`, fed back into the next generation shot); a missing\n * start binary or spawn fault THROWS (a setup bug, never a silent fallback).\n *\n * Protocol matches the runtime's own stdio MCP server (src/mcp/server.ts):\n * newline-delimited JSON-RPC 2.0, protocol version 2024-11-05.\n */\n\nimport { spawn } from 'node:child_process'\nimport { createInterface } from 'node:readline'\nimport type { Verifier, VerifyResult } from './agentic-generator'\n\nconst PROTOCOL_VERSION = '2024-11-05'\n\nexport interface McpServeSpec {\n /** Command that starts the built MCP server in the worktree (stdio transport). */\n command: string\n args?: string[]\n /** Extra env for the server process (merged over `process.env`). */\n env?: Record<string, string>\n /** Handshake timeout (ms). Default 30s. */\n timeoutMs?: number\n /** Minimum tools the server must expose to pass. Default 1. */\n minTools?: number\n}\n\ninterface JsonRpcResponse {\n jsonrpc?: string\n id?: number | string | null\n result?: unknown\n error?: { code: number; message: string }\n}\n\nexport function mcpServeVerifier(spec: McpServeSpec): Verifier {\n const timeoutMs = spec.timeoutMs ?? 30_000\n const minTools = spec.minTools ?? 1\n\n return (worktreePath: string): Promise<VerifyResult> =>\n new Promise<VerifyResult>((resolve, reject) => {\n const child = spawn(spec.command, spec.args ?? [], {\n cwd: worktreePath,\n stdio: ['pipe', 'pipe', 'pipe'],\n env: { ...process.env, ...spec.env },\n })\n\n const stderr: string[] = []\n let settled = false\n let nextId = 1\n const initId = nextId++\n let listId = -1\n\n const settle = (fn: () => void) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n rl.close()\n child.kill('SIGKILL')\n fn()\n }\n const withStderr = (msg: string) =>\n stderr.length > 0 ? `${msg}\\nstderr:\\n${stderr.join('').slice(-2000)}` : msg\n const pass = () => settle(() => resolve({ ok: true }))\n const failCandidate = (msg: string) =>\n settle(() => resolve({ ok: false, feedback: withStderr(msg) }))\n const setupFault = (err: Error) => settle(() => reject(err))\n\n const send = (msg: Record<string, unknown>): boolean => {\n try {\n child.stdin.write(`${JSON.stringify(msg)}\\n`)\n return true\n } catch (err) {\n // EPIPE: the server died mid-handshake — a failed candidate, not a fault.\n failCandidate(`writing to MCP server stdin failed: ${(err as Error).message}`)\n return false\n }\n }\n\n child.on('error', (err) => {\n const code = (err as NodeJS.ErrnoException).code\n setupFault(\n code === 'ENOENT'\n ? new Error(\n `mcpServeVerifier: '${spec.command}' not found in PATH (setup bug, not a failed candidate)`,\n )\n : new Error(`mcpServeVerifier: '${spec.command}' failed to spawn: ${err.message}`),\n )\n })\n child.on('exit', (code, signal) => {\n // An exit before the handshake completes is a failed candidate (the\n // server crashed on boot); after we settle, our own SIGKILL fires here.\n failCandidate(`MCP server exited (code ${code}, signal ${signal}) before serving`)\n })\n child.stderr.on('data', (d) => stderr.push(String(d)))\n\n const rl = createInterface({ input: child.stdout })\n rl.on('line', (line) => {\n let msg: JsonRpcResponse | undefined\n try {\n msg = JSON.parse(line) as JsonRpcResponse\n } catch {\n return // servers log to stdout too; skip non-JSON lines\n }\n if (!msg || typeof msg !== 'object') return\n\n if (msg.id === initId) {\n if (msg.error) return failCandidate(`initialize errored: ${JSON.stringify(msg.error)}`)\n if (!send({ jsonrpc: '2.0', method: 'notifications/initialized' })) return\n listId = nextId++\n send({ jsonrpc: '2.0', id: listId, method: 'tools/list' })\n return\n }\n if (msg.id === listId) {\n if (msg.error) return failCandidate(`tools/list errored: ${JSON.stringify(msg.error)}`)\n const tools = (msg.result as { tools?: unknown[] } | undefined)?.tools\n if (!Array.isArray(tools)) return failCandidate('tools/list result has no tools array')\n if (tools.length < minTools) {\n return failCandidate(`tools/list returned ${tools.length} tool(s), need >= ${minTools}`)\n }\n return pass()\n }\n })\n\n const timer = setTimeout(\n () => failCandidate(`MCP server did not complete the handshake within ${timeoutMs}ms`),\n timeoutMs,\n )\n\n send({\n jsonrpc: '2.0',\n id: initId,\n method: 'initialize',\n params: {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: {},\n clientInfo: { name: 'agent-runtime-mcp-verify', version: '0' },\n },\n })\n })\n}\n"],"mappings":"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","names":[]}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
DELEGATION_STATUS_DESCRIPTION,
|
|
9
9
|
DELEGATION_STATUS_INPUT_SCHEMA,
|
|
10
10
|
DELEGATION_STATUS_TOOL_NAME
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ZKMOIEOB.js";
|
|
12
12
|
|
|
13
13
|
// src/mcp/openai-tools.ts
|
|
14
14
|
function buildTool(name, description, parameters) {
|
|
@@ -45,4 +45,4 @@ export {
|
|
|
45
45
|
mcpToolsForRuntimeMcp,
|
|
46
46
|
mcpToolsForRuntimeMcpSubset
|
|
47
47
|
};
|
|
48
|
-
//# sourceMappingURL=chunk-
|
|
48
|
+
//# sourceMappingURL=chunk-MRWXCFV5.js.map
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// src/mcp/local-harness.ts
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
var HARNESS_INVOCATIONS = {
|
|
4
|
+
claude: {
|
|
5
|
+
command: "claude",
|
|
6
|
+
buildArgs: (taskPrompt) => ["--headless", "-p", taskPrompt],
|
|
7
|
+
modelArgs: (model) => ["-m", model]
|
|
8
|
+
},
|
|
9
|
+
codex: {
|
|
10
|
+
command: "codex",
|
|
11
|
+
buildArgs: (taskPrompt) => ["run", taskPrompt],
|
|
12
|
+
modelArgs: (model) => ["-m", model]
|
|
13
|
+
},
|
|
14
|
+
opencode: {
|
|
15
|
+
command: "opencode",
|
|
16
|
+
buildArgs: (taskPrompt) => ["run", taskPrompt],
|
|
17
|
+
modelArgs: (model) => ["-m", model]
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
function harnessInvocation(harness, profile, taskPrompt) {
|
|
21
|
+
const invocation = HARNESS_INVOCATIONS[harness];
|
|
22
|
+
if (!invocation) {
|
|
23
|
+
throw new Error(`harnessInvocation: unknown harness ${String(harness)}`);
|
|
24
|
+
}
|
|
25
|
+
const systemPrompt = profile.prompt?.systemPrompt;
|
|
26
|
+
const composedPrompt = typeof systemPrompt === "string" && systemPrompt.trim().length > 0 ? `${systemPrompt}
|
|
27
|
+
|
|
28
|
+
${taskPrompt}` : taskPrompt;
|
|
29
|
+
const args = invocation.buildArgs(composedPrompt);
|
|
30
|
+
const model = profile.model?.default;
|
|
31
|
+
if (typeof model === "string" && model.length > 0) {
|
|
32
|
+
args.push(...invocation.modelArgs(model));
|
|
33
|
+
}
|
|
34
|
+
return { command: invocation.command, args };
|
|
35
|
+
}
|
|
36
|
+
var DEFAULT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
37
|
+
function runLocalHarness(options) {
|
|
38
|
+
const { harness, cwd, taskPrompt } = options;
|
|
39
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
40
|
+
const env = options.env ?? process.env;
|
|
41
|
+
const spawnImpl = options.spawn ?? spawn;
|
|
42
|
+
const invocation = HARNESS_INVOCATIONS[harness];
|
|
43
|
+
if (!invocation) {
|
|
44
|
+
return Promise.reject(new Error(`runLocalHarness: unknown harness ${String(harness)}`));
|
|
45
|
+
}
|
|
46
|
+
const startedAt = Date.now();
|
|
47
|
+
const command = options.invocation?.command ?? invocation.command;
|
|
48
|
+
const args = options.invocation ? [...options.invocation.args] : invocation.buildArgs(taskPrompt);
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
let child;
|
|
51
|
+
try {
|
|
52
|
+
child = spawnImpl(command, args, { cwd, env, stdio: "pipe" });
|
|
53
|
+
} catch (err) {
|
|
54
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
child.stdin?.end();
|
|
58
|
+
let stdout = "";
|
|
59
|
+
let stderr = "";
|
|
60
|
+
let timedOut = false;
|
|
61
|
+
let settled = false;
|
|
62
|
+
const timer = timeoutMs > 0 ? setTimeout(() => {
|
|
63
|
+
timedOut = true;
|
|
64
|
+
if (!child.killed) child.kill("SIGTERM");
|
|
65
|
+
}, timeoutMs) : null;
|
|
66
|
+
if (timer && typeof timer.unref === "function") {
|
|
67
|
+
;
|
|
68
|
+
timer.unref();
|
|
69
|
+
}
|
|
70
|
+
const onAbort = () => {
|
|
71
|
+
if (!child.killed) child.kill("SIGTERM");
|
|
72
|
+
};
|
|
73
|
+
if (options.signal) {
|
|
74
|
+
if (options.signal.aborted) onAbort();
|
|
75
|
+
else options.signal.addEventListener("abort", onAbort, { once: true });
|
|
76
|
+
}
|
|
77
|
+
child.stdout?.on("data", (chunk) => {
|
|
78
|
+
stdout += String(chunk);
|
|
79
|
+
});
|
|
80
|
+
child.stderr?.on("data", (chunk) => {
|
|
81
|
+
stderr += String(chunk);
|
|
82
|
+
});
|
|
83
|
+
const finalize = (result) => {
|
|
84
|
+
if (settled) return;
|
|
85
|
+
settled = true;
|
|
86
|
+
if (timer) clearTimeout(timer);
|
|
87
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
88
|
+
resolve(result);
|
|
89
|
+
};
|
|
90
|
+
child.on("error", (err) => {
|
|
91
|
+
if (settled) return;
|
|
92
|
+
settled = true;
|
|
93
|
+
if (timer) clearTimeout(timer);
|
|
94
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
95
|
+
reject(err);
|
|
96
|
+
});
|
|
97
|
+
child.on("close", (code, signal) => {
|
|
98
|
+
finalize({
|
|
99
|
+
exitCode: code,
|
|
100
|
+
stdout,
|
|
101
|
+
stderr,
|
|
102
|
+
killedBySignal: signal,
|
|
103
|
+
durationMs: Date.now() - startedAt,
|
|
104
|
+
timedOut
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export {
|
|
111
|
+
harnessInvocation,
|
|
112
|
+
runLocalHarness
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=chunk-O2UPHN7X.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp/local-harness.ts"],"sourcesContent":["/**\n * @experimental\n *\n * Subprocess wrappers for the local coding-harness CLIs installed in the\n * sandbox image (claude-code, codex, opencode). Used by the in-process\n * delegation executor (`createInProcessExecutor`) so a `delegate_code` call\n * spawns a real harness on a real git worktree instead of provisioning a\n * sibling sandbox.\n *\n * All harness invocations:\n * - run with `cwd` set to the worktree\n * - inherit env from the parent (the MCP server inside the sandbox has\n * the harness's auth already)\n * - capture stdout/stderr\n * - support cancellation via AbortSignal\n * - enforce a wall-clock timeout\n */\n\nimport { type ChildProcess, spawn } from 'node:child_process'\nimport type { AgentProfile } from '@tangle-network/agent-interface'\n\n/** Local coding harness available inside the sandbox. */\nexport type LocalHarness = 'claude' | 'codex' | 'opencode'\n\n/**\n * Default per-harness command + arg shape. `buildArgs` takes ONLY the task prompt and\n * emits the prompt-only invocation (no model, no system prompt) — the historical shape\n * the in-process executor's `streamPrompt` drives. `modelArgs` maps a resolved model to\n * the harness's selector flag (every supported harness takes `-m <model>`). The §1.5\n * profile-aware mapper `harnessInvocation` composes these to thread the full\n * supervisor-authored profile (systemPrompt + model) into argv.\n */\nconst HARNESS_INVOCATIONS: Record<\n LocalHarness,\n {\n command: string\n buildArgs: (taskPrompt: string) => string[]\n /** Map a resolved model to the harness's model-selector flag. */\n modelArgs: (model: string) => string[]\n }\n> = {\n claude: {\n command: 'claude',\n buildArgs: (taskPrompt) => ['--headless', '-p', taskPrompt],\n modelArgs: (model) => ['-m', model],\n },\n codex: {\n command: 'codex',\n buildArgs: (taskPrompt) => ['run', taskPrompt],\n modelArgs: (model) => ['-m', model],\n },\n opencode: {\n command: 'opencode',\n buildArgs: (taskPrompt) => ['run', taskPrompt],\n modelArgs: (model) => ['-m', model],\n },\n}\n\n/** Result of mapping an `AgentProfile` + task prompt onto a harness invocation. */\nexport interface HarnessInvocation {\n command: string\n args: string[]\n}\n\n/**\n * Map a supervisor-authored `AgentProfile` + the per-task prompt onto a concrete harness\n * `command` + `args` (the §1.5 fix). UNLIKE the prompt-only `HARNESS_INVOCATIONS.buildArgs`\n * — which drops both the authored model and the system prompt — this threads the FULL\n * profile payload into argv:\n *\n * - `profile.prompt.systemPrompt` → the PROMPT channel: a portable, harness-agnostic\n * default that prepends the system prompt above the task prompt (`<system>\\n\\n<task>`),\n * so the authored standing instructions reach EVERY harness (none of the three CLIs\n * expose a portable replace-system-prompt flag for a one-shot non-interactive run).\n * - `profile.model.default` → the harness's `-m <model>` selector.\n *\n * The task prompt alone is the floor; an empty/absent profile yields exactly the legacy\n * `buildArgs(taskPrompt)` shape so existing callers are byte-identical.\n */\nexport function harnessInvocation(\n harness: LocalHarness,\n profile: AgentProfile,\n taskPrompt: string,\n): HarnessInvocation {\n const invocation = HARNESS_INVOCATIONS[harness]\n if (!invocation) {\n throw new Error(`harnessInvocation: unknown harness ${String(harness)}`)\n }\n\n const systemPrompt = profile.prompt?.systemPrompt\n const composedPrompt =\n typeof systemPrompt === 'string' && systemPrompt.trim().length > 0\n ? `${systemPrompt}\\n\\n${taskPrompt}`\n : taskPrompt\n\n const args = invocation.buildArgs(composedPrompt)\n\n const model = profile.model?.default\n if (typeof model === 'string' && model.length > 0) {\n args.push(...invocation.modelArgs(model))\n }\n\n return { command: invocation.command, args }\n}\n\n/** @experimental */\nexport interface RunLocalHarnessOptions {\n harness: LocalHarness\n /** Working directory for the subprocess (typically a worktree path). */\n cwd: string\n /** Prompt forwarded as the harness CLI's task argument. */\n taskPrompt: string\n /**\n * Pre-built command + args (e.g. from `harnessInvocation` so the full authored\n * `AgentProfile` — systemPrompt + model — reaches the harness). When set it OVERRIDES the\n * default prompt-only `buildArgs(taskPrompt)` path; `command` defaults to the harness's\n * default binary when only `args` is supplied. When absent the legacy prompt-only shape\n * is used unchanged.\n */\n invocation?: { command?: string; args: ReadonlyArray<string> }\n /** Wall-clock kill deadline (ms). Default 5 min. Subprocess SIGTERMed on expiry. */\n timeoutMs?: number\n /** Caller cancellation. SIGTERM is sent on abort. */\n signal?: AbortSignal\n /** Override env (defaults to inheriting from the parent). */\n env?: NodeJS.ProcessEnv\n /**\n * Test seam — inject a custom spawner so unit tests can mock the\n * subprocess without touching the OS. Defaults to node's `child_process.spawn`.\n */\n spawn?: (\n command: string,\n args: ReadonlyArray<string>,\n opts: {\n cwd: string\n env: NodeJS.ProcessEnv\n stdio: 'pipe'\n },\n ) => ChildProcess\n}\n\n/** @experimental */\nexport interface LocalHarnessResult {\n /** OS exit code. `null` when killed before exit. */\n exitCode: number | null\n /** Concatenated stdout. */\n stdout: string\n /** Concatenated stderr. */\n stderr: string\n /** Set when the process exited via signal (timeout / abort). */\n killedBySignal: NodeJS.Signals | null\n /** Wall-clock duration ms (spawn → exit). */\n durationMs: number\n /** Set when timeoutMs elapsed before exit. */\n timedOut: boolean\n}\n\nconst DEFAULT_TIMEOUT_MS = 5 * 60 * 1000\n\n/**\n * Spawn a local coding harness CLI as a subprocess + collect its output.\n *\n * NOT responsible for parsing the harness's output or extracting a diff —\n * the in-process executor's `streamPrompt` orchestrates `git diff` against\n * the worktree after this resolves. This function is intentionally narrow:\n * spawn, wait, capture, return.\n *\n * Fails loud — throws when:\n * - `cwd` doesn't exist (subprocess emits ENOENT; surfaced as Error)\n * - the harness binary is not on PATH (ENOENT)\n *\n * Does NOT throw when:\n * - the subprocess exits non-zero (`result.exitCode` carries the code)\n * - the subprocess is aborted / timed out (`result.killedBySignal` /\n * `result.timedOut` carries the reason)\n *\n * @experimental\n */\nexport function runLocalHarness(options: RunLocalHarnessOptions): Promise<LocalHarnessResult> {\n const { harness, cwd, taskPrompt } = options\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS\n const env = options.env ?? process.env\n const spawnImpl = options.spawn ?? spawn\n\n const invocation = HARNESS_INVOCATIONS[harness]\n if (!invocation) {\n return Promise.reject(new Error(`runLocalHarness: unknown harness ${String(harness)}`))\n }\n\n const startedAt = Date.now()\n const command = options.invocation?.command ?? invocation.command\n const args = options.invocation ? [...options.invocation.args] : invocation.buildArgs(taskPrompt)\n\n return new Promise<LocalHarnessResult>((resolve, reject) => {\n let child: ChildProcess\n try {\n child = spawnImpl(command, args, { cwd, env, stdio: 'pipe' })\n } catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)))\n return\n }\n\n // The harness takes its task as an argv arg, not on stdin. Leaving stdin\n // OPEN makes a non-TTY `opencode run` (and likely the other harnesses)\n // BLOCK forever waiting on input — zero output, SIGTERM at the wall cap,\n // empty patch -> \"no candidate passed validation\". Close stdin so the\n // subprocess sees EOF and proceeds (the `cliExecutor` leaf does the same).\n child.stdin?.end()\n\n let stdout = ''\n let stderr = ''\n let timedOut = false\n let settled = false\n\n const timer =\n timeoutMs > 0\n ? setTimeout(() => {\n timedOut = true\n if (!child.killed) child.kill('SIGTERM')\n }, timeoutMs)\n : null\n if (timer && typeof (timer as { unref?: () => void }).unref === 'function') {\n ;(timer as { unref: () => void }).unref()\n }\n\n const onAbort = () => {\n if (!child.killed) child.kill('SIGTERM')\n }\n if (options.signal) {\n if (options.signal.aborted) onAbort()\n else options.signal.addEventListener('abort', onAbort, { once: true })\n }\n\n child.stdout?.on('data', (chunk) => {\n stdout += String(chunk)\n })\n child.stderr?.on('data', (chunk) => {\n stderr += String(chunk)\n })\n\n const finalize = (result: LocalHarnessResult) => {\n if (settled) return\n settled = true\n if (timer) clearTimeout(timer)\n options.signal?.removeEventListener('abort', onAbort)\n resolve(result)\n }\n\n child.on('error', (err) => {\n if (settled) return\n settled = true\n if (timer) clearTimeout(timer)\n options.signal?.removeEventListener('abort', onAbort)\n reject(err)\n })\n\n child.on('close', (code, signal) => {\n finalize({\n exitCode: code,\n stdout,\n stderr,\n killedBySignal: signal,\n durationMs: Date.now() - startedAt,\n timedOut,\n })\n })\n })\n}\n"],"mappings":"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","names":[]}
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
definePersona,
|
|
6
6
|
runPersonified,
|
|
7
7
|
worktreeFanout
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-SA5GCF2X.js";
|
|
9
9
|
import {
|
|
10
10
|
createExecutorRegistry
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ZKMOIEOB.js";
|
|
12
12
|
import {
|
|
13
13
|
runAnalystLoop
|
|
14
14
|
} from "./chunk-IODKUOBA.js";
|
|
@@ -196,4 +196,4 @@ export {
|
|
|
196
196
|
runLoopRunnerCli,
|
|
197
197
|
parseLoopRunnerArgv
|
|
198
198
|
};
|
|
199
|
-
//# sourceMappingURL=chunk-
|
|
199
|
+
//# sourceMappingURL=chunk-QKNBYHMK.js.map
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
stringifySafe,
|
|
20
20
|
withDriverExecutor,
|
|
21
21
|
zeroTokenUsage
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-ZKMOIEOB.js";
|
|
23
23
|
import {
|
|
24
24
|
AnalystError,
|
|
25
25
|
PlannerError,
|
|
@@ -4036,4 +4036,4 @@ export {
|
|
|
4036
4036
|
computeFindingId,
|
|
4037
4037
|
makeFinding2 as makeFinding
|
|
4038
4038
|
};
|
|
4039
|
-
//# sourceMappingURL=chunk-
|
|
4039
|
+
//# sourceMappingURL=chunk-SA5GCF2X.js.map
|