@tangle-network/agent-runtime 0.68.0 → 0.70.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 +81 -13
- package/dist/agent.d.ts +4 -5
- package/dist/agent.js +3 -6
- package/dist/agent.js.map +1 -1
- package/dist/chunk-BYZCXQHF.js +474 -0
- package/dist/chunk-BYZCXQHF.js.map +1 -0
- package/dist/{chunk-OYU5LR4T.js → chunk-EDCVUZZC.js} +2 -2
- package/dist/{chunk-QNUEFNU7.js → chunk-L5ZFBVT6.js} +6 -6
- package/dist/chunk-L5ZFBVT6.js.map +1 -0
- package/dist/{chunk-VKUHUFX7.js → chunk-QXWGSDAQ.js} +914 -590
- package/dist/chunk-QXWGSDAQ.js.map +1 -0
- package/dist/{chunk-LTEF2LYD.js → chunk-ZNQVMMR5.js} +3 -3
- package/dist/{coordination-Curpzeyc.d.ts → coordination-C7WxwHXq.d.ts} +8 -1
- package/dist/{delegates-CLFNAKyi.d.ts → delegates-DqAgo32T.d.ts} +105 -10
- package/dist/{improvement-adapter-BC4HhuAR.d.ts → improvement-adapter-BVuMragr.d.ts} +1 -1
- package/dist/index.d.ts +439 -100
- package/dist/index.js +583 -125
- package/dist/index.js.map +1 -1
- package/dist/intelligence.d.ts +2 -3
- package/dist/{loop-runner-bin-B6dzNZC8.d.ts → loop-runner-bin-B0NeLTRd.d.ts} +4 -4
- package/dist/loop-runner-bin.d.ts +7 -10
- package/dist/loop-runner-bin.js +4 -7
- package/dist/loops.d.ts +3149 -16
- package/dist/loops.js +34 -63
- package/dist/mcp/bin.js +14 -16
- package/dist/mcp/bin.js.map +1 -1
- package/dist/mcp/index.d.ts +8 -12
- package/dist/mcp/index.js +16 -19
- package/dist/mcp/index.js.map +1 -1
- package/dist/{openai-tools-CA2N3-Ak.d.ts → openai-tools-DPx9Gzvn.d.ts} +1 -1
- package/dist/profiles.d.ts +94 -6
- package/dist/profiles.js +320 -9
- package/dist/profiles.js.map +1 -1
- package/dist/{router-client-30Y_pca8.d.ts → router-client-C7kp_ECN.d.ts} +37 -1
- package/dist/{substrate-CUgk7F7s.d.ts → substrate-BoRXgvka.d.ts} +52 -1
- package/dist/{types-Crxftafi.d.ts → types-BYa2ZOAx.d.ts} +83 -2
- package/dist/{types-p8dWBIXL.d.ts → types-DJu6TBGp.d.ts} +2 -16
- package/dist/{worktree-fanout-DUiKPApb.d.ts → worktree-fanout-gNfl0Byj.d.ts} +9 -37
- package/package.json +9 -39
- package/dist/analyst-loop.d.ts +0 -52
- package/dist/analyst-loop.js +0 -11
- package/dist/analyst-loop.js.map +0 -1
- package/dist/audit.d.ts +0 -93
- package/dist/audit.js +0 -312
- package/dist/audit.js.map +0 -1
- package/dist/chunk-4B6U4CVQ.js +0 -15
- package/dist/chunk-4B6U4CVQ.js.map +0 -1
- package/dist/chunk-FCIPUALH.js +0 -214
- package/dist/chunk-FCIPUALH.js.map +0 -1
- package/dist/chunk-O2UPHN7X.js +0 -114
- package/dist/chunk-O2UPHN7X.js.map +0 -1
- package/dist/chunk-P5OKDSLB.js +0 -580
- package/dist/chunk-P5OKDSLB.js.map +0 -1
- package/dist/chunk-QNUEFNU7.js.map +0 -1
- package/dist/chunk-VKUHUFX7.js.map +0 -1
- package/dist/chunk-VLF5RHEQ.js +0 -143
- package/dist/chunk-VLF5RHEQ.js.map +0 -1
- package/dist/coder-2leJPOvC.d.ts +0 -52
- package/dist/improvement.d.ts +0 -208
- package/dist/improvement.js +0 -343
- package/dist/improvement.js.map +0 -1
- package/dist/local-harness-BE_h8szs.d.ts +0 -93
- package/dist/platform.d.ts +0 -255
- package/dist/platform.js +0 -229
- package/dist/platform.js.map +0 -1
- package/dist/run-loop-D3PwlG7J.d.ts +0 -112
- package/dist/runtime-hooks-C7JwKb9E.d.ts +0 -70
- package/dist/runtime.d.ts +0 -3108
- package/dist/runtime.js +0 -263
- package/dist/runtime.js.map +0 -1
- package/dist/topology.d.ts +0 -126
- package/dist/topology.js +0 -333
- package/dist/topology.js.map +0 -1
- package/dist/workflow.d.ts +0 -551
- package/dist/workflow.js +0 -1781
- package/dist/workflow.js.map +0 -1
- /package/dist/{chunk-OYU5LR4T.js.map → chunk-EDCVUZZC.js.map} +0 -0
- /package/dist/{chunk-LTEF2LYD.js.map → chunk-ZNQVMMR5.js.map} +0 -0
|
@@ -1,22 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
UI_LENSES
|
|
3
|
-
} from "./chunk-WIR4HOOJ.js";
|
|
4
|
-
import {
|
|
5
|
-
AgentEvalError,
|
|
6
|
-
AnalystError,
|
|
7
|
-
NotFoundError,
|
|
8
|
-
PlannerError,
|
|
9
|
-
RuntimeRunStateError,
|
|
10
|
-
ValidationError,
|
|
11
|
-
extractLlmCallEvent
|
|
12
|
-
} from "./chunk-VLF5RHEQ.js";
|
|
13
|
-
import {
|
|
14
|
-
harnessInvocation,
|
|
15
|
-
runLocalHarness
|
|
16
|
-
} from "./chunk-O2UPHN7X.js";
|
|
17
1
|
import {
|
|
18
2
|
buildLoopSpanNodes
|
|
19
3
|
} from "./chunk-G3RGMA7C.js";
|
|
4
|
+
import {
|
|
5
|
+
UI_LENSES
|
|
6
|
+
} from "./chunk-WIR4HOOJ.js";
|
|
7
|
+
|
|
8
|
+
// src/runtime/index.ts
|
|
9
|
+
import { computeFindingId as computeFindingId2, makeFinding as makeFinding3 } from "@tangle-network/agent-eval";
|
|
20
10
|
|
|
21
11
|
// src/durable/spawn-journal.ts
|
|
22
12
|
import { createHash } from "crypto";
|
|
@@ -149,38 +139,6 @@ var InMemoryResultBlobStore = class {
|
|
|
149
139
|
return this.blobs.has(outRef) ? this.blobs.get(outRef) : void 0;
|
|
150
140
|
}
|
|
151
141
|
};
|
|
152
|
-
var FileResultBlobStore = class {
|
|
153
|
-
constructor(dir) {
|
|
154
|
-
this.dir = dir;
|
|
155
|
-
}
|
|
156
|
-
dir;
|
|
157
|
-
async put(outRef, artifact) {
|
|
158
|
-
assertContentAddress(outRef, artifact);
|
|
159
|
-
const fs = await import("fs/promises");
|
|
160
|
-
await fs.mkdir(this.dir, { recursive: true });
|
|
161
|
-
const fh = await fs.open(this.blobPath(outRef), "w");
|
|
162
|
-
try {
|
|
163
|
-
await fh.write(JSON.stringify(artifact));
|
|
164
|
-
await fh.sync();
|
|
165
|
-
} finally {
|
|
166
|
-
await fh.close();
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
async get(outRef) {
|
|
170
|
-
const fs = await import("fs/promises");
|
|
171
|
-
let text;
|
|
172
|
-
try {
|
|
173
|
-
text = await fs.readFile(this.blobPath(outRef), "utf8");
|
|
174
|
-
} catch (err) {
|
|
175
|
-
if (isNoEntError(err)) return void 0;
|
|
176
|
-
throw err;
|
|
177
|
-
}
|
|
178
|
-
return JSON.parse(text);
|
|
179
|
-
}
|
|
180
|
-
blobPath(outRef) {
|
|
181
|
-
return `${this.dir}/${outRef.replace(/:/g, "-")}.json`;
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
142
|
function assertContentAddress(outRef, artifact) {
|
|
185
143
|
const expected = contentAddress(artifact);
|
|
186
144
|
if (outRef !== expected) {
|
|
@@ -217,90 +175,6 @@ var InMemorySpawnJournal = class {
|
|
|
217
175
|
tree.events.push({ ...ev });
|
|
218
176
|
}
|
|
219
177
|
};
|
|
220
|
-
var FileSpawnJournal = class {
|
|
221
|
-
constructor(path2) {
|
|
222
|
-
this.path = path2;
|
|
223
|
-
}
|
|
224
|
-
path;
|
|
225
|
-
async loadTree(root) {
|
|
226
|
-
const fs = await import("fs/promises");
|
|
227
|
-
let text;
|
|
228
|
-
try {
|
|
229
|
-
text = await fs.readFile(this.path, "utf8");
|
|
230
|
-
} catch (err) {
|
|
231
|
-
if (isNoEntError(err)) return void 0;
|
|
232
|
-
throw err;
|
|
233
|
-
}
|
|
234
|
-
const lines = text.split("\n").filter((line) => line.length > 0);
|
|
235
|
-
let begun = false;
|
|
236
|
-
const events = [];
|
|
237
|
-
for (const line of lines) {
|
|
238
|
-
const record = JSON.parse(line);
|
|
239
|
-
if (record.root !== root) continue;
|
|
240
|
-
if (record.kind === "begin") {
|
|
241
|
-
begun = true;
|
|
242
|
-
} else {
|
|
243
|
-
if (!begun) {
|
|
244
|
-
throw new Error(
|
|
245
|
-
`spawn journal corrupted: event for tree '${root}' precedes its begin record`
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
assertSeqUnique(root, events, record.event);
|
|
249
|
-
events.push(record.event);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
return begun ? events : void 0;
|
|
253
|
-
}
|
|
254
|
-
async beginTree(root, at) {
|
|
255
|
-
const existing = await this.loadTreeBegin(root);
|
|
256
|
-
if (existing) {
|
|
257
|
-
if (existing !== at) {
|
|
258
|
-
throw new Error(
|
|
259
|
-
`spawn tree '${root}' already begun in ${this.path} at ${existing}; refusing to overwrite with ${at}`
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
await this.appendRecord({ kind: "begin", root, at });
|
|
265
|
-
}
|
|
266
|
-
async appendEvent(root, ev) {
|
|
267
|
-
const events = await this.loadTree(root);
|
|
268
|
-
if (events === void 0) {
|
|
269
|
-
throw new Error(`appendEvent called for unknown spawn tree '${root}'; call beginTree first`);
|
|
270
|
-
}
|
|
271
|
-
assertSeqUnique(root, events, ev);
|
|
272
|
-
await this.appendRecord({ kind: "event", root, event: ev });
|
|
273
|
-
}
|
|
274
|
-
async loadTreeBegin(root) {
|
|
275
|
-
const fs = await import("fs/promises");
|
|
276
|
-
let text;
|
|
277
|
-
try {
|
|
278
|
-
text = await fs.readFile(this.path, "utf8");
|
|
279
|
-
} catch (err) {
|
|
280
|
-
if (isNoEntError(err)) return void 0;
|
|
281
|
-
throw err;
|
|
282
|
-
}
|
|
283
|
-
const lines = text.split("\n").filter((line) => line.length > 0);
|
|
284
|
-
for (const line of lines) {
|
|
285
|
-
const record = JSON.parse(line);
|
|
286
|
-
if (record.root === root && record.kind === "begin") return record.at;
|
|
287
|
-
}
|
|
288
|
-
return void 0;
|
|
289
|
-
}
|
|
290
|
-
async appendRecord(record) {
|
|
291
|
-
const fs = await import("fs/promises");
|
|
292
|
-
const path2 = await import("path");
|
|
293
|
-
await fs.mkdir(path2.dirname(this.path), { recursive: true });
|
|
294
|
-
const fh = await fs.open(this.path, "a");
|
|
295
|
-
try {
|
|
296
|
-
await fh.write(`${JSON.stringify(record)}
|
|
297
|
-
`);
|
|
298
|
-
await fh.sync();
|
|
299
|
-
} finally {
|
|
300
|
-
await fh.close();
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
};
|
|
304
178
|
function assertSeqUnique(root, events, ev) {
|
|
305
179
|
if (ev.kind === "spawned" || ev.kind === "metered") return;
|
|
306
180
|
if (events.some((e) => e.kind !== "spawned" && e.kind !== "metered" && e.seq === ev.seq)) {
|
|
@@ -309,148 +183,6 @@ function assertSeqUnique(root, events, ev) {
|
|
|
309
183
|
);
|
|
310
184
|
}
|
|
311
185
|
}
|
|
312
|
-
async function replaySpawnTree(journal, blobs, root) {
|
|
313
|
-
const events = await journal.loadTree(root);
|
|
314
|
-
if (events === void 0) {
|
|
315
|
-
throw new Error(`replaySpawnTree: no journaled tree for root '${root}'`);
|
|
316
|
-
}
|
|
317
|
-
const ordered = [...events].sort((a, b) => a.seq - b.seq);
|
|
318
|
-
const labels = /* @__PURE__ */ new Map();
|
|
319
|
-
for (const ev of ordered) {
|
|
320
|
-
if (ev.kind === "spawned") labels.set(ev.id, ev.label);
|
|
321
|
-
}
|
|
322
|
-
const settled = [];
|
|
323
|
-
for (const ev of ordered) {
|
|
324
|
-
if (ev.kind === "spawned") continue;
|
|
325
|
-
if (ev.kind === "metered") continue;
|
|
326
|
-
if (ev.kind === "cancelled") {
|
|
327
|
-
settled.push({
|
|
328
|
-
kind: "down",
|
|
329
|
-
handle: replayHandle(ev.id, labels.get(ev.id) ?? ev.id, "cancelled"),
|
|
330
|
-
reason: ev.reason,
|
|
331
|
-
infra: false,
|
|
332
|
-
restartCount: 0,
|
|
333
|
-
seq: ev.seq
|
|
334
|
-
});
|
|
335
|
-
continue;
|
|
336
|
-
}
|
|
337
|
-
if (ev.status === "down") {
|
|
338
|
-
settled.push({
|
|
339
|
-
kind: "down",
|
|
340
|
-
handle: replayHandle(ev.id, labels.get(ev.id) ?? ev.id, "failed"),
|
|
341
|
-
reason: ev.verdict?.notes ?? "child down",
|
|
342
|
-
infra: ev.infra === true,
|
|
343
|
-
restartCount: 0,
|
|
344
|
-
seq: ev.seq
|
|
345
|
-
});
|
|
346
|
-
continue;
|
|
347
|
-
}
|
|
348
|
-
if (ev.outRef === void 0) {
|
|
349
|
-
throw new Error(
|
|
350
|
-
`replaySpawnTree: settled-done event for '${ev.id}' (seq ${ev.seq}) has no outRef; cannot rehydrate the result the driver branched on`
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
const out = await blobs.get(ev.outRef);
|
|
354
|
-
if (out === void 0) {
|
|
355
|
-
throw new Error(
|
|
356
|
-
`replaySpawnTree: blob store has no artifact for outRef '${ev.outRef}' (node '${ev.id}', seq ${ev.seq})`
|
|
357
|
-
);
|
|
358
|
-
}
|
|
359
|
-
settled.push({
|
|
360
|
-
kind: "done",
|
|
361
|
-
handle: replayHandle(ev.id, labels.get(ev.id) ?? ev.id, "done"),
|
|
362
|
-
out,
|
|
363
|
-
outRef: ev.outRef,
|
|
364
|
-
verdict: ev.verdict,
|
|
365
|
-
spent: ev.spent,
|
|
366
|
-
seq: ev.seq
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
return settled;
|
|
370
|
-
}
|
|
371
|
-
function replayHandle(id, label, status) {
|
|
372
|
-
return {
|
|
373
|
-
id,
|
|
374
|
-
label,
|
|
375
|
-
status,
|
|
376
|
-
abort() {
|
|
377
|
-
throw new Error(`cannot abort node '${id}': replayed handles are terminal, not live`);
|
|
378
|
-
}
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
function materializeTreeView(events) {
|
|
382
|
-
const nodes = /* @__PURE__ */ new Map();
|
|
383
|
-
let root;
|
|
384
|
-
const spawns = events.filter((ev) => ev.kind === "spawned").sort((a, b) => a.seq - b.seq);
|
|
385
|
-
const settlements = events.filter((ev) => ev.kind !== "spawned" && ev.kind !== "metered").sort((a, b) => a.seq - b.seq);
|
|
386
|
-
for (const ev of spawns) {
|
|
387
|
-
if (ev.parent === void 0 && root === void 0) root = ev.id;
|
|
388
|
-
nodes.set(ev.id, {
|
|
389
|
-
id: ev.id,
|
|
390
|
-
parent: ev.parent,
|
|
391
|
-
label: ev.label,
|
|
392
|
-
status: "pending",
|
|
393
|
-
runtime: ev.runtime,
|
|
394
|
-
budget: ev.budget,
|
|
395
|
-
spent: zeroSpend()
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
for (const ev of settlements) {
|
|
399
|
-
if (ev.kind === "settled") {
|
|
400
|
-
const node = requireNode(nodes, ev.id);
|
|
401
|
-
node.status = ev.status === "done" ? "done" : "failed";
|
|
402
|
-
node.spent = ev.spent;
|
|
403
|
-
node.outRef = ev.outRef;
|
|
404
|
-
} else {
|
|
405
|
-
const node = requireNode(nodes, ev.id);
|
|
406
|
-
node.status = "cancelled";
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
for (const ev of events) {
|
|
410
|
-
if (ev.kind !== "metered") continue;
|
|
411
|
-
const node = requireNode(nodes, ev.id);
|
|
412
|
-
node.spent = addJournalSpend(node.spent, ev.spend);
|
|
413
|
-
}
|
|
414
|
-
const snapshots = [...nodes.values()].map(freezeSnapshot);
|
|
415
|
-
return {
|
|
416
|
-
root: root ?? snapshots[0]?.id ?? "",
|
|
417
|
-
nodes: snapshots,
|
|
418
|
-
inFlight: snapshots.filter((n) => n.status === "running" || n.status === "acquiring").length
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
function zeroSpend() {
|
|
422
|
-
return { iterations: 0, tokens: zeroTokenUsage(), usd: 0, ms: 0 };
|
|
423
|
-
}
|
|
424
|
-
function addJournalSpend(a, b) {
|
|
425
|
-
return {
|
|
426
|
-
iterations: a.iterations + b.iterations,
|
|
427
|
-
tokens: { input: a.tokens.input + b.tokens.input, output: a.tokens.output + b.tokens.output },
|
|
428
|
-
usd: a.usd + b.usd,
|
|
429
|
-
ms: a.ms + b.ms
|
|
430
|
-
};
|
|
431
|
-
}
|
|
432
|
-
function requireNode(nodes, id) {
|
|
433
|
-
const node = nodes.get(id);
|
|
434
|
-
if (!node) {
|
|
435
|
-
throw new Error(`spawn journal corrupted: settle/cancel for node '${id}' with no prior spawn`);
|
|
436
|
-
}
|
|
437
|
-
return node;
|
|
438
|
-
}
|
|
439
|
-
function freezeSnapshot(node) {
|
|
440
|
-
return {
|
|
441
|
-
id: node.id,
|
|
442
|
-
parent: node.parent,
|
|
443
|
-
label: node.label,
|
|
444
|
-
status: node.status,
|
|
445
|
-
runtime: node.runtime,
|
|
446
|
-
budget: node.budget,
|
|
447
|
-
spent: node.spent,
|
|
448
|
-
outRef: node.outRef
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
function isNoEntError(err) {
|
|
452
|
-
return typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT";
|
|
453
|
-
}
|
|
454
186
|
|
|
455
187
|
// src/runtime/anytime.ts
|
|
456
188
|
var median = (xs) => {
|
|
@@ -947,6 +679,61 @@ function reportLoopUsage(cost, result, source = "loop") {
|
|
|
947
679
|
cost.observeTokens(result.tokenUsage);
|
|
948
680
|
}
|
|
949
681
|
|
|
682
|
+
// src/errors.ts
|
|
683
|
+
import { AgentEvalError } from "@tangle-network/agent-eval";
|
|
684
|
+
import {
|
|
685
|
+
AgentEvalError as AgentEvalError2,
|
|
686
|
+
ConfigError,
|
|
687
|
+
JudgeError,
|
|
688
|
+
NotFoundError,
|
|
689
|
+
ValidationError
|
|
690
|
+
} from "@tangle-network/agent-eval";
|
|
691
|
+
var SessionMismatchError = class extends AgentEvalError {
|
|
692
|
+
sessionBackend;
|
|
693
|
+
requestedBackend;
|
|
694
|
+
constructor(sessionBackend, requestedBackend, options) {
|
|
695
|
+
super(
|
|
696
|
+
"validation",
|
|
697
|
+
`Cannot resume ${sessionBackend} session with ${requestedBackend} backend`,
|
|
698
|
+
options
|
|
699
|
+
);
|
|
700
|
+
this.sessionBackend = sessionBackend;
|
|
701
|
+
this.requestedBackend = requestedBackend;
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
var BackendTransportError = class extends AgentEvalError {
|
|
705
|
+
backend;
|
|
706
|
+
status;
|
|
707
|
+
/**
|
|
708
|
+
* Truncated upstream response body (≤2 KiB) when available. Diagnostic
|
|
709
|
+
* only — surfaces in `backend_error.error.body` and `final.error.body`
|
|
710
|
+
* so operators can see "free_tier_limit", "invalid_api_key", etc. without
|
|
711
|
+
* cracking the log line open.
|
|
712
|
+
*/
|
|
713
|
+
body;
|
|
714
|
+
constructor(backend, message, options) {
|
|
715
|
+
super("config", message, options);
|
|
716
|
+
this.backend = backend;
|
|
717
|
+
this.status = options?.status;
|
|
718
|
+
this.body = options?.body;
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
var RuntimeRunStateError = class extends AgentEvalError {
|
|
722
|
+
constructor(message, options) {
|
|
723
|
+
super("validation", message, options);
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
var PlannerError = class extends AgentEvalError {
|
|
727
|
+
constructor(message, options) {
|
|
728
|
+
super("validation", message, options);
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
var AnalystError = class extends AgentEvalError {
|
|
732
|
+
constructor(message, options) {
|
|
733
|
+
super("validation", message, options);
|
|
734
|
+
}
|
|
735
|
+
};
|
|
736
|
+
|
|
950
737
|
// src/runtime-hooks.ts
|
|
951
738
|
function defineRuntimeHooks(hooks) {
|
|
952
739
|
return hooks;
|
|
@@ -1175,6 +962,79 @@ async function resolveCapabilities(client) {
|
|
|
1175
962
|
}
|
|
1176
963
|
}
|
|
1177
964
|
|
|
965
|
+
// src/runtime/sandbox-events.ts
|
|
966
|
+
function extractLlmCallEvent(event, agentRunName) {
|
|
967
|
+
if (!event || typeof event !== "object") return void 0;
|
|
968
|
+
const type = String(event.type ?? "");
|
|
969
|
+
const data = event.data && typeof event.data === "object" ? event.data : {};
|
|
970
|
+
if (type === "llm_call" || type === "cost.usage" || type === "usage") {
|
|
971
|
+
return buildLlmCall(data, agentRunName);
|
|
972
|
+
}
|
|
973
|
+
if (type === "message.completed" || type === "result" || type === "final") {
|
|
974
|
+
const usage = data.usage;
|
|
975
|
+
if (!usage || typeof usage !== "object") return void 0;
|
|
976
|
+
return buildLlmCall({ ...usage, model: data.model ?? usage.model }, agentRunName);
|
|
977
|
+
}
|
|
978
|
+
if (type === "done") {
|
|
979
|
+
const usage = data.tokenUsage;
|
|
980
|
+
if (!usage || typeof usage !== "object") return void 0;
|
|
981
|
+
const out = pickFiniteNumber(usage, ["outputTokens", "completion_tokens", "tokensOut"]);
|
|
982
|
+
const reasoning = pickFiniteNumber(usage, ["reasoningTokens"]);
|
|
983
|
+
const mergedOut = out !== void 0 || reasoning !== void 0 ? (out ?? 0) + (reasoning ?? 0) : void 0;
|
|
984
|
+
return buildLlmCall(
|
|
985
|
+
{
|
|
986
|
+
inputTokens: usage.inputTokens,
|
|
987
|
+
outputTokens: mergedOut,
|
|
988
|
+
totalCostUsd: data.totalCostUsd,
|
|
989
|
+
model: data.model ?? usage.model
|
|
990
|
+
},
|
|
991
|
+
agentRunName
|
|
992
|
+
);
|
|
993
|
+
}
|
|
994
|
+
return void 0;
|
|
995
|
+
}
|
|
996
|
+
function buildLlmCall(data, agentRunName) {
|
|
997
|
+
const tokensIn = pickFiniteNumber(data, ["tokensIn", "inputTokens", "prompt_tokens"]);
|
|
998
|
+
const tokensOut = pickFiniteNumber(data, ["tokensOut", "outputTokens", "completion_tokens"]);
|
|
999
|
+
const costUsd = pickFiniteNumber(data, ["costUsd", "totalCostUsd", "cost_usd", "cost"]);
|
|
1000
|
+
if (tokensIn === void 0 && tokensOut === void 0 && costUsd === void 0) {
|
|
1001
|
+
return void 0;
|
|
1002
|
+
}
|
|
1003
|
+
const model = typeof data.model === "string" && data.model.length > 0 ? data.model : agentRunName;
|
|
1004
|
+
const event = {
|
|
1005
|
+
type: "llm_call",
|
|
1006
|
+
model
|
|
1007
|
+
};
|
|
1008
|
+
if (tokensIn !== void 0) event.tokensIn = tokensIn;
|
|
1009
|
+
if (tokensOut !== void 0) event.tokensOut = tokensOut;
|
|
1010
|
+
if (costUsd !== void 0) event.costUsd = costUsd;
|
|
1011
|
+
return event;
|
|
1012
|
+
}
|
|
1013
|
+
function pickFiniteNumber(data, keys) {
|
|
1014
|
+
for (const key of keys) {
|
|
1015
|
+
const value = data[key];
|
|
1016
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
1017
|
+
}
|
|
1018
|
+
return void 0;
|
|
1019
|
+
}
|
|
1020
|
+
function mapSandboxEvent(event, opts = {}) {
|
|
1021
|
+
if (!event || typeof event !== "object") return void 0;
|
|
1022
|
+
const type = String(event.type ?? "");
|
|
1023
|
+
const data = event.data && typeof event.data === "object" ? event.data : {};
|
|
1024
|
+
if (type === "message.part.updated") {
|
|
1025
|
+
const part = data.part && typeof data.part === "object" ? data.part : {};
|
|
1026
|
+
const partType = String(part.type ?? "");
|
|
1027
|
+
const delta = typeof data.delta === "string" ? data.delta : void 0;
|
|
1028
|
+
const text = delta ?? (typeof part.text === "string" ? part.text : void 0);
|
|
1029
|
+
if (text === void 0) return void 0;
|
|
1030
|
+
if (partType === "text") return { type: "text_delta", text };
|
|
1031
|
+
if (partType === "reasoning" || partType === "thinking")
|
|
1032
|
+
return { type: "reasoning_delta", text };
|
|
1033
|
+
return void 0;
|
|
1034
|
+
}
|
|
1035
|
+
return extractLlmCallEvent(event, opts.agentRunName ?? "agent");
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1178
1038
|
// src/runtime/sandbox-lineage.ts
|
|
1179
1039
|
var TEARDOWN_TIMEOUT_MS = 15e3;
|
|
1180
1040
|
var DEFAULT_FORK_CONCURRENCY = 4;
|
|
@@ -2143,7 +2003,7 @@ function createScope(args) {
|
|
|
2143
2003
|
let cursorSeq = 0;
|
|
2144
2004
|
let meterSeq = 0;
|
|
2145
2005
|
const now = args.now ?? Date.now;
|
|
2146
|
-
function
|
|
2006
|
+
function spawn5(agent, task, opts) {
|
|
2147
2007
|
if (args.maxDepth !== void 0 && args.depth >= args.maxDepth) {
|
|
2148
2008
|
return { ok: false, reason: "depth-exceeded" };
|
|
2149
2009
|
}
|
|
@@ -2185,7 +2045,7 @@ function createScope(args) {
|
|
|
2185
2045
|
runtime: executor.runtime,
|
|
2186
2046
|
budget: opts.budget,
|
|
2187
2047
|
label: opts.label,
|
|
2188
|
-
spent:
|
|
2048
|
+
spent: zeroSpend(),
|
|
2189
2049
|
settled: void 0,
|
|
2190
2050
|
delivered: false,
|
|
2191
2051
|
...executor.deliver ? { deliver: executor.deliver.bind(executor) } : {}
|
|
@@ -2239,7 +2099,7 @@ function createScope(args) {
|
|
|
2239
2099
|
live.settled = settled;
|
|
2240
2100
|
return { ok: true, handle };
|
|
2241
2101
|
} catch (err) {
|
|
2242
|
-
args.pool.reconcile(reservation.ticket,
|
|
2102
|
+
args.pool.reconcile(reservation.ticket, zeroSpend());
|
|
2243
2103
|
throw err;
|
|
2244
2104
|
}
|
|
2245
2105
|
}
|
|
@@ -2294,7 +2154,7 @@ function createScope(args) {
|
|
|
2294
2154
|
);
|
|
2295
2155
|
}
|
|
2296
2156
|
return {
|
|
2297
|
-
spawn:
|
|
2157
|
+
spawn: spawn5,
|
|
2298
2158
|
next,
|
|
2299
2159
|
send,
|
|
2300
2160
|
signal: args.signal,
|
|
@@ -2546,7 +2406,7 @@ async function teardownSafe(executor, grace) {
|
|
|
2546
2406
|
function downRecord(reason, infra, metered) {
|
|
2547
2407
|
return { kind: "down", reason, infra, restartCount: 0, ...metered ? { metered } : {} };
|
|
2548
2408
|
}
|
|
2549
|
-
function
|
|
2409
|
+
function zeroSpend() {
|
|
2550
2410
|
return { iterations: 0, tokens: { input: 0, output: 0 }, usd: 0, ms: 0 };
|
|
2551
2411
|
}
|
|
2552
2412
|
function isAsyncIterable2(value) {
|
|
@@ -3042,7 +2902,7 @@ var FileCorpus = class {
|
|
|
3042
2902
|
try {
|
|
3043
2903
|
text = await fs.readFile(this.path, "utf8");
|
|
3044
2904
|
} catch (err) {
|
|
3045
|
-
if (
|
|
2905
|
+
if (isNoEntError(err)) return /* @__PURE__ */ new Map();
|
|
3046
2906
|
throw err;
|
|
3047
2907
|
}
|
|
3048
2908
|
const lines = text.split("\n").filter((line) => line.length > 0);
|
|
@@ -3116,30 +2976,13 @@ function renderLine(record) {
|
|
|
3116
2976
|
function freeze(record) {
|
|
3117
2977
|
return Object.freeze({ ...record });
|
|
3118
2978
|
}
|
|
3119
|
-
function
|
|
2979
|
+
function isNoEntError(err) {
|
|
3120
2980
|
return typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT";
|
|
3121
2981
|
}
|
|
3122
2982
|
|
|
3123
2983
|
// src/runtime/supervise/driver-executor.ts
|
|
3124
2984
|
var driverRuntime = "driver";
|
|
3125
2985
|
var driverRole = "driver";
|
|
3126
|
-
function driverChild(name, driver, journal) {
|
|
3127
|
-
const spec = {
|
|
3128
|
-
profile: { name, metadata: { role: driverRole } },
|
|
3129
|
-
harness: null,
|
|
3130
|
-
driver,
|
|
3131
|
-
journal
|
|
3132
|
-
};
|
|
3133
|
-
return {
|
|
3134
|
-
name,
|
|
3135
|
-
executorSpec: spec,
|
|
3136
|
-
act() {
|
|
3137
|
-
throw new ValidationError(
|
|
3138
|
-
`driverChild: "${name}" was run directly; a driver child runs through its nested-scope executor`
|
|
3139
|
-
);
|
|
3140
|
-
}
|
|
3141
|
-
};
|
|
3142
|
-
}
|
|
3143
2986
|
function isDriverSpec(spec) {
|
|
3144
2987
|
const role = spec.profile.metadata?.role;
|
|
3145
2988
|
if (role !== driverRole) return false;
|
|
@@ -3311,11 +3154,64 @@ function isAgent(value) {
|
|
|
3311
3154
|
}
|
|
3312
3155
|
|
|
3313
3156
|
// src/runtime/supervise/runtime.ts
|
|
3314
|
-
import { spawn as
|
|
3157
|
+
import { spawn as spawn4 } from "child_process";
|
|
3158
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
3315
3159
|
import { estimateCost as estimateCost2, isModelPriced as isModelPriced2 } from "@tangle-network/agent-eval";
|
|
3316
3160
|
|
|
3317
3161
|
// src/runtime/router-client.ts
|
|
3318
3162
|
import { estimateCost, isModelPriced } from "@tangle-network/agent-eval";
|
|
3163
|
+
|
|
3164
|
+
// src/runtime/tool-loop.ts
|
|
3165
|
+
async function runBrainLoop(opts) {
|
|
3166
|
+
const maxTurns = opts.maxTurns ?? 4;
|
|
3167
|
+
const messages = [...opts.initialMessages];
|
|
3168
|
+
let toolCalls = 0;
|
|
3169
|
+
let lastText = "";
|
|
3170
|
+
const usage = { input: 0, output: 0 };
|
|
3171
|
+
const toolTrace = [];
|
|
3172
|
+
for (let turn = 1; turn <= maxTurns; turn += 1) {
|
|
3173
|
+
if (opts.hooks?.stopBefore?.(turn)) break;
|
|
3174
|
+
await opts.hooks?.beforeTurn?.(turn, messages);
|
|
3175
|
+
const r = await opts.chat(messages, opts.tools);
|
|
3176
|
+
if (r.usage) {
|
|
3177
|
+
usage.input += r.usage.input;
|
|
3178
|
+
usage.output += r.usage.output;
|
|
3179
|
+
opts.hooks?.onUsage?.(r.usage);
|
|
3180
|
+
}
|
|
3181
|
+
if (r.content) lastText = r.content;
|
|
3182
|
+
if (r.toolCalls.length === 0)
|
|
3183
|
+
return { final: lastText, turns: turn, toolCalls, toolTrace, usage, messages };
|
|
3184
|
+
messages.push({
|
|
3185
|
+
role: "assistant",
|
|
3186
|
+
content: r.content ?? "",
|
|
3187
|
+
tool_calls: r.toolCalls.map((tc) => ({
|
|
3188
|
+
id: tc.id,
|
|
3189
|
+
type: "function",
|
|
3190
|
+
function: { name: tc.name, arguments: tc.arguments }
|
|
3191
|
+
}))
|
|
3192
|
+
});
|
|
3193
|
+
for (const tc of r.toolCalls) {
|
|
3194
|
+
toolCalls += 1;
|
|
3195
|
+
let args = {};
|
|
3196
|
+
try {
|
|
3197
|
+
args = JSON.parse(tc.arguments);
|
|
3198
|
+
} catch {
|
|
3199
|
+
messages.push({
|
|
3200
|
+
role: "tool",
|
|
3201
|
+
tool_call_id: tc.id,
|
|
3202
|
+
content: `error: arguments were not valid JSON: ${tc.arguments.slice(0, 200)}`
|
|
3203
|
+
});
|
|
3204
|
+
continue;
|
|
3205
|
+
}
|
|
3206
|
+
const out = await opts.execute(tc.name, args);
|
|
3207
|
+
messages.push({ role: "tool", tool_call_id: tc.id, content: out });
|
|
3208
|
+
toolTrace.push({ name: tc.name, args: tc.arguments, result: out });
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
return { final: lastText, turns: maxTurns, toolCalls, toolTrace, usage, messages };
|
|
3212
|
+
}
|
|
3213
|
+
|
|
3214
|
+
// src/runtime/router-client.ts
|
|
3319
3215
|
async function routerChatWithUsage(cfg, messages, opts) {
|
|
3320
3216
|
const url = `${cfg.routerBaseUrl.replace(/\/$/, "")}/chat/completions`;
|
|
3321
3217
|
const headers = { "content-type": "application/json", authorization: `Bearer ${cfg.routerKey}` };
|
|
@@ -3387,62 +3283,31 @@ async function routerChatWithTools(cfg, messages, tools, opts) {
|
|
|
3387
3283
|
const costUsd = usage && isModelPriced(cfg.model) ? estimateCost(usage.input, usage.output, cfg.model) : void 0;
|
|
3388
3284
|
return {
|
|
3389
3285
|
content: msg?.content ?? null,
|
|
3390
|
-
toolCalls,
|
|
3391
|
-
...usage ? { usage } : {},
|
|
3392
|
-
...costUsd !== void 0 ? { costUsd } : {}
|
|
3393
|
-
};
|
|
3394
|
-
}
|
|
3395
|
-
async function routerToolLoop(cfg, system, user, tools, execute, opts) {
|
|
3396
|
-
const
|
|
3397
|
-
|
|
3398
|
-
{ role: "
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
if (r.content) lastText = r.content;
|
|
3416
|
-
if (r.toolCalls.length === 0)
|
|
3417
|
-
return { final: lastText, turns: turn, toolCalls, toolTrace, usage, messages };
|
|
3418
|
-
messages.push({
|
|
3419
|
-
role: "assistant",
|
|
3420
|
-
content: r.content ?? "",
|
|
3421
|
-
tool_calls: r.toolCalls.map((tc) => ({
|
|
3422
|
-
id: tc.id,
|
|
3423
|
-
type: "function",
|
|
3424
|
-
function: { name: tc.name, arguments: tc.arguments }
|
|
3425
|
-
}))
|
|
3426
|
-
});
|
|
3427
|
-
for (const tc of r.toolCalls) {
|
|
3428
|
-
toolCalls += 1;
|
|
3429
|
-
let args = {};
|
|
3430
|
-
try {
|
|
3431
|
-
args = JSON.parse(tc.arguments);
|
|
3432
|
-
} catch {
|
|
3433
|
-
messages.push({
|
|
3434
|
-
role: "tool",
|
|
3435
|
-
tool_call_id: tc.id,
|
|
3436
|
-
content: `error: arguments were not valid JSON: ${tc.arguments.slice(0, 200)}`
|
|
3437
|
-
});
|
|
3438
|
-
continue;
|
|
3439
|
-
}
|
|
3440
|
-
const out = await execute(tc.name, args);
|
|
3441
|
-
messages.push({ role: "tool", tool_call_id: tc.id, content: out });
|
|
3442
|
-
toolTrace.push({ name: tc.name, args: tc.arguments, result: out });
|
|
3443
|
-
}
|
|
3444
|
-
}
|
|
3445
|
-
return { final: lastText, turns: maxTurns, toolCalls, toolTrace, usage, messages };
|
|
3286
|
+
toolCalls,
|
|
3287
|
+
...usage ? { usage } : {},
|
|
3288
|
+
...costUsd !== void 0 ? { costUsd } : {}
|
|
3289
|
+
};
|
|
3290
|
+
}
|
|
3291
|
+
async function routerToolLoop(cfg, system, user, tools, execute, opts) {
|
|
3292
|
+
const initialMessages = opts?.initialMessages ?? [
|
|
3293
|
+
{ role: "system", content: system },
|
|
3294
|
+
{ role: "user", content: user }
|
|
3295
|
+
];
|
|
3296
|
+
return runBrainLoop({
|
|
3297
|
+
chat: (messages, toolSpecs) => routerChatWithTools(cfg, messages, toolSpecs, {
|
|
3298
|
+
...opts?.temperature !== void 0 ? { temperature: opts.temperature } : {},
|
|
3299
|
+
...opts?.maxTokens ? { maxTokens: opts.maxTokens } : {},
|
|
3300
|
+
...opts?.signal ? { signal: opts.signal } : {}
|
|
3301
|
+
}),
|
|
3302
|
+
tools,
|
|
3303
|
+
execute,
|
|
3304
|
+
initialMessages,
|
|
3305
|
+
maxTurns: opts?.maxTurns ?? 4
|
|
3306
|
+
});
|
|
3307
|
+
}
|
|
3308
|
+
function routerBrain(cfg, opts = {}) {
|
|
3309
|
+
const temperature = opts.temperature ?? 0.4;
|
|
3310
|
+
return (messages, tools) => routerChatWithTools(cfg, messages, tools, { temperature, toolChoice: "auto" });
|
|
3446
3311
|
}
|
|
3447
3312
|
|
|
3448
3313
|
// src/runtime/supervise/inbox.ts
|
|
@@ -3494,14 +3359,123 @@ ${lines.join("\n")}`;
|
|
|
3494
3359
|
import { randomUUID } from "crypto";
|
|
3495
3360
|
|
|
3496
3361
|
// src/mcp/worktree-harness.ts
|
|
3497
|
-
import { spawn as
|
|
3362
|
+
import { spawn as spawn3 } from "child_process";
|
|
3498
3363
|
|
|
3499
|
-
// src/mcp/
|
|
3364
|
+
// src/mcp/local-harness.ts
|
|
3500
3365
|
import { spawn } from "child_process";
|
|
3366
|
+
var HARNESS_INVOCATIONS = {
|
|
3367
|
+
claude: {
|
|
3368
|
+
command: "claude",
|
|
3369
|
+
buildArgs: (taskPrompt) => ["--headless", "-p", taskPrompt],
|
|
3370
|
+
modelArgs: (model) => ["-m", model]
|
|
3371
|
+
},
|
|
3372
|
+
codex: {
|
|
3373
|
+
command: "codex",
|
|
3374
|
+
buildArgs: (taskPrompt) => ["run", taskPrompt],
|
|
3375
|
+
modelArgs: (model) => ["-m", model]
|
|
3376
|
+
},
|
|
3377
|
+
opencode: {
|
|
3378
|
+
command: "opencode",
|
|
3379
|
+
buildArgs: (taskPrompt) => ["run", taskPrompt],
|
|
3380
|
+
modelArgs: (model) => ["-m", model]
|
|
3381
|
+
}
|
|
3382
|
+
};
|
|
3383
|
+
function harnessInvocation(harness, profile, taskPrompt) {
|
|
3384
|
+
const invocation = HARNESS_INVOCATIONS[harness];
|
|
3385
|
+
if (!invocation) {
|
|
3386
|
+
throw new Error(`harnessInvocation: unknown harness ${String(harness)}`);
|
|
3387
|
+
}
|
|
3388
|
+
const systemPrompt = profile.prompt?.systemPrompt;
|
|
3389
|
+
const composedPrompt = typeof systemPrompt === "string" && systemPrompt.trim().length > 0 ? `${systemPrompt}
|
|
3390
|
+
|
|
3391
|
+
${taskPrompt}` : taskPrompt;
|
|
3392
|
+
const args = invocation.buildArgs(composedPrompt);
|
|
3393
|
+
const model = profile.model?.default;
|
|
3394
|
+
if (typeof model === "string" && model.length > 0) {
|
|
3395
|
+
args.push(...invocation.modelArgs(model));
|
|
3396
|
+
}
|
|
3397
|
+
return { command: invocation.command, args };
|
|
3398
|
+
}
|
|
3399
|
+
var DEFAULT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
3400
|
+
function runLocalHarness(options) {
|
|
3401
|
+
const { harness, cwd, taskPrompt } = options;
|
|
3402
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
3403
|
+
const env = options.env ?? process.env;
|
|
3404
|
+
const spawnImpl = options.spawn ?? spawn;
|
|
3405
|
+
const invocation = HARNESS_INVOCATIONS[harness];
|
|
3406
|
+
if (!invocation) {
|
|
3407
|
+
return Promise.reject(new Error(`runLocalHarness: unknown harness ${String(harness)}`));
|
|
3408
|
+
}
|
|
3409
|
+
const startedAt = Date.now();
|
|
3410
|
+
const command = options.invocation?.command ?? invocation.command;
|
|
3411
|
+
const args = options.invocation ? [...options.invocation.args] : invocation.buildArgs(taskPrompt);
|
|
3412
|
+
return new Promise((resolve, reject) => {
|
|
3413
|
+
let child;
|
|
3414
|
+
try {
|
|
3415
|
+
child = spawnImpl(command, args, { cwd, env, stdio: "pipe" });
|
|
3416
|
+
} catch (err) {
|
|
3417
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
3418
|
+
return;
|
|
3419
|
+
}
|
|
3420
|
+
child.stdin?.end();
|
|
3421
|
+
let stdout = "";
|
|
3422
|
+
let stderr = "";
|
|
3423
|
+
let timedOut = false;
|
|
3424
|
+
let settled = false;
|
|
3425
|
+
const timer = timeoutMs > 0 ? setTimeout(() => {
|
|
3426
|
+
timedOut = true;
|
|
3427
|
+
if (!child.killed) child.kill("SIGTERM");
|
|
3428
|
+
}, timeoutMs) : null;
|
|
3429
|
+
if (timer && typeof timer.unref === "function") {
|
|
3430
|
+
;
|
|
3431
|
+
timer.unref();
|
|
3432
|
+
}
|
|
3433
|
+
const onAbort = () => {
|
|
3434
|
+
if (!child.killed) child.kill("SIGTERM");
|
|
3435
|
+
};
|
|
3436
|
+
if (options.signal) {
|
|
3437
|
+
if (options.signal.aborted) onAbort();
|
|
3438
|
+
else options.signal.addEventListener("abort", onAbort, { once: true });
|
|
3439
|
+
}
|
|
3440
|
+
child.stdout?.on("data", (chunk) => {
|
|
3441
|
+
stdout += String(chunk);
|
|
3442
|
+
});
|
|
3443
|
+
child.stderr?.on("data", (chunk) => {
|
|
3444
|
+
stderr += String(chunk);
|
|
3445
|
+
});
|
|
3446
|
+
const finalize3 = (result) => {
|
|
3447
|
+
if (settled) return;
|
|
3448
|
+
settled = true;
|
|
3449
|
+
if (timer) clearTimeout(timer);
|
|
3450
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
3451
|
+
resolve(result);
|
|
3452
|
+
};
|
|
3453
|
+
child.on("error", (err) => {
|
|
3454
|
+
if (settled) return;
|
|
3455
|
+
settled = true;
|
|
3456
|
+
if (timer) clearTimeout(timer);
|
|
3457
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
3458
|
+
reject(err);
|
|
3459
|
+
});
|
|
3460
|
+
child.on("close", (code, signal) => {
|
|
3461
|
+
finalize3({
|
|
3462
|
+
exitCode: code,
|
|
3463
|
+
stdout,
|
|
3464
|
+
stderr,
|
|
3465
|
+
killedBySignal: signal,
|
|
3466
|
+
durationMs: Date.now() - startedAt,
|
|
3467
|
+
timedOut
|
|
3468
|
+
});
|
|
3469
|
+
});
|
|
3470
|
+
});
|
|
3471
|
+
}
|
|
3472
|
+
|
|
3473
|
+
// src/mcp/worktree.ts
|
|
3474
|
+
import { spawn as spawn2 } from "child_process";
|
|
3501
3475
|
async function runGitAsync(args, cwd, runner) {
|
|
3502
3476
|
if (runner) return runner(args, { cwd });
|
|
3503
3477
|
return new Promise((resolve, reject) => {
|
|
3504
|
-
const proc =
|
|
3478
|
+
const proc = spawn2("git", args, { cwd, stdio: "pipe" });
|
|
3505
3479
|
let stdout = "";
|
|
3506
3480
|
let stderr = "";
|
|
3507
3481
|
proc.stdout?.on("data", (c) => {
|
|
@@ -3667,7 +3641,7 @@ async function runChecks(opts) {
|
|
|
3667
3641
|
}
|
|
3668
3642
|
function defaultRunCommand(opts) {
|
|
3669
3643
|
return new Promise((resolve, reject) => {
|
|
3670
|
-
const child =
|
|
3644
|
+
const child = spawn3("/bin/sh", ["-c", opts.command], {
|
|
3671
3645
|
cwd: opts.cwd,
|
|
3672
3646
|
stdio: ["ignore", "pipe", "pipe"]
|
|
3673
3647
|
});
|
|
@@ -3790,7 +3764,7 @@ function contentRef(prefix, value) {
|
|
|
3790
3764
|
}
|
|
3791
3765
|
return `${prefix}:${(h >>> 0).toString(16).padStart(8, "0")}`;
|
|
3792
3766
|
}
|
|
3793
|
-
function
|
|
3767
|
+
function zeroSpend2() {
|
|
3794
3768
|
return { iterations: 0, tokens: zeroTokenUsage(), usd: 0, ms: 0 };
|
|
3795
3769
|
}
|
|
3796
3770
|
var routerInlineExecutor = (spec, ctx) => {
|
|
@@ -3962,15 +3936,24 @@ var routerToolsInlineExecutor = (spec, ctx) => {
|
|
|
3962
3936
|
const toolName = tc?.function?.name ?? "";
|
|
3963
3937
|
let result;
|
|
3964
3938
|
let status = "ok";
|
|
3939
|
+
const toolStartedAt = Date.now();
|
|
3965
3940
|
try {
|
|
3966
3941
|
result = await seam.executeToolCall(toolName, args, task);
|
|
3967
3942
|
} catch (e) {
|
|
3968
3943
|
status = "error";
|
|
3969
3944
|
result = `error: ${e instanceof Error ? e.message : String(e)}`;
|
|
3970
3945
|
}
|
|
3946
|
+
const toolEndedAt = Date.now();
|
|
3971
3947
|
messages.push({ role: "tool", tool_call_id: id, content: result });
|
|
3972
3948
|
try {
|
|
3973
|
-
seam.onToolStep?.({
|
|
3949
|
+
seam.onToolStep?.({
|
|
3950
|
+
toolName,
|
|
3951
|
+
args,
|
|
3952
|
+
status,
|
|
3953
|
+
startedAt: toolStartedAt,
|
|
3954
|
+
endedAt: toolEndedAt,
|
|
3955
|
+
durationMs: toolEndedAt - toolStartedAt
|
|
3956
|
+
});
|
|
3974
3957
|
} catch {
|
|
3975
3958
|
}
|
|
3976
3959
|
}
|
|
@@ -4150,7 +4133,7 @@ var cliExecutor = (_spec, ctx) => {
|
|
|
4150
4133
|
};
|
|
4151
4134
|
async function* streamCliLeaf(args) {
|
|
4152
4135
|
const prompt = taskToPrompt(args.task);
|
|
4153
|
-
const proc =
|
|
4136
|
+
const proc = spawn4(args.seam.bin, args.seam.args ?? [], {
|
|
4154
4137
|
...args.seam.cwd ? { cwd: args.seam.cwd } : {},
|
|
4155
4138
|
env: { ...process.env, ...args.seam.env ?? {} },
|
|
4156
4139
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4187,7 +4170,7 @@ async function* streamCliLeaf(args) {
|
|
|
4187
4170
|
);
|
|
4188
4171
|
}
|
|
4189
4172
|
const out = { content: chunks.join("") };
|
|
4190
|
-
args.onArtifact({ outRef: contentRef("cli", out), out, spent:
|
|
4173
|
+
args.onArtifact({ outRef: contentRef("cli", out), out, spent: zeroSpend2() });
|
|
4191
4174
|
yield { kind: "iteration" };
|
|
4192
4175
|
}
|
|
4193
4176
|
function killWithGrace(proc, grace) {
|
|
@@ -4216,58 +4199,33 @@ var bridgeExecutor = (spec, ctx) => {
|
|
|
4216
4199
|
"bridgeExecutor: BridgeSeam.bridgeUrl + bridgeBearer + model required"
|
|
4217
4200
|
);
|
|
4218
4201
|
}
|
|
4202
|
+
const maxTurns = seam.maxTurns ?? 200;
|
|
4203
|
+
const sessionId = seam.sessionId ?? `bridge-${spec.profile.name ?? "worker"}-${randomUUID2()}`;
|
|
4219
4204
|
const controller = new AbortController();
|
|
4220
4205
|
const abortIfSignalled = () => {
|
|
4221
4206
|
if (ctx.signal.aborted) controller.abort();
|
|
4222
4207
|
};
|
|
4223
4208
|
abortIfSignalled();
|
|
4224
4209
|
if (!ctx.signal.aborted) ctx.signal.addEventListener("abort", abortIfSignalled, { once: true });
|
|
4210
|
+
const inbox = createInbox();
|
|
4225
4211
|
let artifact;
|
|
4226
4212
|
return {
|
|
4227
4213
|
runtime: "cli",
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
model: seam.model,
|
|
4242
|
-
stream: false,
|
|
4243
|
-
...seam.agentProfile ? { agent_profile: seam.agentProfile } : {},
|
|
4244
|
-
messages
|
|
4245
|
-
}),
|
|
4246
|
-
...linked ? { signal: linked } : {}
|
|
4247
|
-
});
|
|
4248
|
-
if (!res.ok) {
|
|
4249
|
-
throw new ValidationError(
|
|
4250
|
-
`bridgeExecutor: bridge ${res.status}: ${(await res.text()).slice(0, 300)}`
|
|
4251
|
-
);
|
|
4214
|
+
deliver: (m) => inbox.deliver(m),
|
|
4215
|
+
execute(task, signal) {
|
|
4216
|
+
return streamBridgeSession({
|
|
4217
|
+
task,
|
|
4218
|
+
signal,
|
|
4219
|
+
spec,
|
|
4220
|
+
seam,
|
|
4221
|
+
sessionId,
|
|
4222
|
+
maxTurns,
|
|
4223
|
+
inbox,
|
|
4224
|
+
controller,
|
|
4225
|
+
onArtifact: (a) => {
|
|
4226
|
+
artifact = a;
|
|
4252
4227
|
}
|
|
4253
|
-
|
|
4254
|
-
const u = data.usage;
|
|
4255
|
-
const usage = u && typeof u.prompt_tokens === "number" && typeof u.completion_tokens === "number" ? { input: u.prompt_tokens, output: u.completion_tokens } : void 0;
|
|
4256
|
-
const msg = data.choices?.[0]?.message;
|
|
4257
|
-
const content = msg?.content ?? "";
|
|
4258
|
-
const toolCalls = (msg?.tool_calls ?? []).map((t) => t.function?.name ?? "unknown");
|
|
4259
|
-
const spent = {
|
|
4260
|
-
iterations: 1,
|
|
4261
|
-
tokens: usage ? { input: usage.input, output: usage.output } : zeroTokenUsage(),
|
|
4262
|
-
usd: typeof u?.cost === "number" ? u.cost : 0,
|
|
4263
|
-
ms: Date.now() - started
|
|
4264
|
-
};
|
|
4265
|
-
const out = { content, toolCalls };
|
|
4266
|
-
artifact = { outRef: contentRef("bridge", { model: seam.model, content }), out, spent };
|
|
4267
|
-
return artifact;
|
|
4268
|
-
} finally {
|
|
4269
|
-
if (timer) clearTimeout(timer);
|
|
4270
|
-
}
|
|
4228
|
+
});
|
|
4271
4229
|
},
|
|
4272
4230
|
teardown(_grace) {
|
|
4273
4231
|
controller.abort();
|
|
@@ -4275,12 +4233,179 @@ var bridgeExecutor = (spec, ctx) => {
|
|
|
4275
4233
|
},
|
|
4276
4234
|
resultArtifact() {
|
|
4277
4235
|
if (!artifact) {
|
|
4278
|
-
throw new ValidationError("bridgeExecutor: resultArtifact() read before
|
|
4236
|
+
throw new ValidationError("bridgeExecutor: resultArtifact() read before stream drained");
|
|
4279
4237
|
}
|
|
4280
4238
|
return { ...artifact, spent: artifact.spent };
|
|
4281
4239
|
}
|
|
4282
4240
|
};
|
|
4283
4241
|
};
|
|
4242
|
+
async function* streamBridgeSession(args) {
|
|
4243
|
+
const { seam, inbox } = args;
|
|
4244
|
+
const started = Date.now();
|
|
4245
|
+
const url = `${seam.bridgeUrl.replace(/\/$/, "")}/v1/chat/completions`;
|
|
4246
|
+
const external = mergeAbortSignals(args.signal, args.controller.signal);
|
|
4247
|
+
const tokens = zeroTokenUsage();
|
|
4248
|
+
let usd = 0;
|
|
4249
|
+
let turns = 0;
|
|
4250
|
+
let lastText = "";
|
|
4251
|
+
const toolCalls = [];
|
|
4252
|
+
let nextPrompt = taskToPrompt(args.task);
|
|
4253
|
+
const system = args.spec.profile.prompt?.systemPrompt;
|
|
4254
|
+
for (let t = 0; t < args.maxTurns; t += 1) {
|
|
4255
|
+
const pending = inbox.drain();
|
|
4256
|
+
if (pending.length) {
|
|
4257
|
+
const folded = inbox.fold(pending);
|
|
4258
|
+
nextPrompt = t === 0 && nextPrompt ? `${nextPrompt}
|
|
4259
|
+
|
|
4260
|
+
${folded}` : folded;
|
|
4261
|
+
}
|
|
4262
|
+
if (nextPrompt === void 0) break;
|
|
4263
|
+
const messages = [];
|
|
4264
|
+
if (t === 0 && typeof system === "string" && system.length > 0) {
|
|
4265
|
+
messages.push({ role: "system", content: system });
|
|
4266
|
+
}
|
|
4267
|
+
messages.push({ role: "user", content: nextPrompt });
|
|
4268
|
+
nextPrompt = void 0;
|
|
4269
|
+
const interruptSig = inbox.freshInterrupt();
|
|
4270
|
+
const turnController = new AbortController();
|
|
4271
|
+
const abortTurn = () => turnController.abort();
|
|
4272
|
+
if (external.aborted) turnController.abort();
|
|
4273
|
+
else external.addEventListener("abort", abortTurn);
|
|
4274
|
+
interruptSig.addEventListener("abort", abortTurn, { once: true });
|
|
4275
|
+
const timer = seam.timeoutMs ? setTimeout(abortTurn, seam.timeoutMs) : void 0;
|
|
4276
|
+
const cleanup = () => {
|
|
4277
|
+
external.removeEventListener("abort", abortTurn);
|
|
4278
|
+
if (timer) clearTimeout(timer);
|
|
4279
|
+
};
|
|
4280
|
+
let res;
|
|
4281
|
+
try {
|
|
4282
|
+
res = await fetch(url, {
|
|
4283
|
+
method: "POST",
|
|
4284
|
+
headers: {
|
|
4285
|
+
"content-type": "application/json",
|
|
4286
|
+
authorization: `Bearer ${seam.bridgeBearer}`,
|
|
4287
|
+
"x-session-id": args.sessionId
|
|
4288
|
+
},
|
|
4289
|
+
body: JSON.stringify({
|
|
4290
|
+
model: seam.model,
|
|
4291
|
+
stream: true,
|
|
4292
|
+
session_id: args.sessionId,
|
|
4293
|
+
...seam.agentProfile ? { agent_profile: seam.agentProfile } : {},
|
|
4294
|
+
messages
|
|
4295
|
+
}),
|
|
4296
|
+
signal: turnController.signal
|
|
4297
|
+
});
|
|
4298
|
+
} catch (e) {
|
|
4299
|
+
cleanup();
|
|
4300
|
+
const interruptAbort = e instanceof DOMException && e.name === "AbortError" && interruptSig.aborted && !args.signal.aborted && !args.controller.signal.aborted;
|
|
4301
|
+
if (interruptAbort) continue;
|
|
4302
|
+
throw e;
|
|
4303
|
+
}
|
|
4304
|
+
if (!res.ok) {
|
|
4305
|
+
cleanup();
|
|
4306
|
+
throw new ValidationError(
|
|
4307
|
+
`bridgeExecutor: bridge ${res.status}: ${(await res.text()).slice(0, 300)}`
|
|
4308
|
+
);
|
|
4309
|
+
}
|
|
4310
|
+
if (!res.body) {
|
|
4311
|
+
cleanup();
|
|
4312
|
+
throw new ValidationError("bridgeExecutor: bridge response had no body to stream");
|
|
4313
|
+
}
|
|
4314
|
+
let turnText = "";
|
|
4315
|
+
try {
|
|
4316
|
+
for await (const chunk of parseSseChatStream(res.body)) {
|
|
4317
|
+
if (chunk.content) {
|
|
4318
|
+
turnText += chunk.content;
|
|
4319
|
+
yield { kind: "iteration" };
|
|
4320
|
+
}
|
|
4321
|
+
if (chunk.toolCall) toolCalls.push(chunk.toolCall);
|
|
4322
|
+
if (chunk.usage) {
|
|
4323
|
+
tokens.input += chunk.usage.input;
|
|
4324
|
+
tokens.output += chunk.usage.output;
|
|
4325
|
+
yield { kind: "tokens", input: chunk.usage.input, output: chunk.usage.output };
|
|
4326
|
+
}
|
|
4327
|
+
if (typeof chunk.cost === "number" && chunk.cost > 0) {
|
|
4328
|
+
usd += chunk.cost;
|
|
4329
|
+
yield { kind: "cost", usd: chunk.cost };
|
|
4330
|
+
}
|
|
4331
|
+
}
|
|
4332
|
+
} finally {
|
|
4333
|
+
cleanup();
|
|
4334
|
+
}
|
|
4335
|
+
turns += 1;
|
|
4336
|
+
if (turnText) lastText = turnText;
|
|
4337
|
+
if (inbox.pending() === 0) break;
|
|
4338
|
+
}
|
|
4339
|
+
const spent = {
|
|
4340
|
+
iterations: turns,
|
|
4341
|
+
tokens,
|
|
4342
|
+
usd,
|
|
4343
|
+
ms: Date.now() - started
|
|
4344
|
+
};
|
|
4345
|
+
const out = { content: lastText, toolCalls };
|
|
4346
|
+
args.onArtifact({
|
|
4347
|
+
outRef: contentRef("bridge", { model: seam.model, session: args.sessionId, content: lastText }),
|
|
4348
|
+
out,
|
|
4349
|
+
spent
|
|
4350
|
+
});
|
|
4351
|
+
}
|
|
4352
|
+
async function* parseSseChatStream(body) {
|
|
4353
|
+
const reader = body.getReader();
|
|
4354
|
+
const decoder = new TextDecoder();
|
|
4355
|
+
let buf = "";
|
|
4356
|
+
try {
|
|
4357
|
+
for (; ; ) {
|
|
4358
|
+
const { done, value } = await reader.read();
|
|
4359
|
+
if (done) break;
|
|
4360
|
+
buf += decoder.decode(value, { stream: true });
|
|
4361
|
+
let sep = buf.indexOf("\n\n");
|
|
4362
|
+
while (sep !== -1) {
|
|
4363
|
+
const frame = buf.slice(0, sep);
|
|
4364
|
+
buf = buf.slice(sep + 2);
|
|
4365
|
+
const chunk = parseSseFrame(frame);
|
|
4366
|
+
if (chunk === "done") return;
|
|
4367
|
+
if (chunk) yield chunk;
|
|
4368
|
+
sep = buf.indexOf("\n\n");
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
} finally {
|
|
4372
|
+
reader.releaseLock();
|
|
4373
|
+
}
|
|
4374
|
+
}
|
|
4375
|
+
function parseSseFrame(frame) {
|
|
4376
|
+
const dataLines = [];
|
|
4377
|
+
for (const rawLine of frame.split("\n")) {
|
|
4378
|
+
const line = rawLine.replace(/\r$/, "");
|
|
4379
|
+
if (!line || line.startsWith(":")) continue;
|
|
4380
|
+
if (line.startsWith("data:")) dataLines.push(line.slice("data:".length).trimStart());
|
|
4381
|
+
}
|
|
4382
|
+
if (dataLines.length === 0) return void 0;
|
|
4383
|
+
const data = dataLines.join("\n");
|
|
4384
|
+
if (data === "[DONE]") return "done";
|
|
4385
|
+
let parsed;
|
|
4386
|
+
try {
|
|
4387
|
+
parsed = JSON.parse(data);
|
|
4388
|
+
} catch {
|
|
4389
|
+
return void 0;
|
|
4390
|
+
}
|
|
4391
|
+
if (parsed.error) {
|
|
4392
|
+
throw new ValidationError(
|
|
4393
|
+
`bridgeExecutor: bridge stream error: ${parsed.error.message ?? "unknown"}`
|
|
4394
|
+
);
|
|
4395
|
+
}
|
|
4396
|
+
const out = {};
|
|
4397
|
+
const choice = parsed.choices?.[0];
|
|
4398
|
+
const content = choice?.delta?.content ?? choice?.message?.content;
|
|
4399
|
+
if (typeof content === "string" && content.length > 0) out.content = content;
|
|
4400
|
+
const toolName = choice?.delta?.tool_calls?.[0]?.function?.name;
|
|
4401
|
+
if (typeof toolName === "string" && toolName.length > 0) out.toolCall = toolName;
|
|
4402
|
+
const u = parsed.usage;
|
|
4403
|
+
if (u && (typeof u.prompt_tokens === "number" || typeof u.completion_tokens === "number")) {
|
|
4404
|
+
out.usage = { input: u.prompt_tokens ?? 0, output: u.completion_tokens ?? 0 };
|
|
4405
|
+
}
|
|
4406
|
+
if (typeof u?.cost === "number") out.cost = u.cost;
|
|
4407
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
4408
|
+
}
|
|
4284
4409
|
var cliWorktreeExecutor = (spec, ctx) => {
|
|
4285
4410
|
const seam = readSeam(ctx, cliWorktreeSeamKey, "cli-worktree");
|
|
4286
4411
|
if (!seam.repoRoot || !seam.harness || !seam.taskPrompt) {
|
|
@@ -4660,40 +4785,6 @@ function createSupervisor() {
|
|
|
4660
4785
|
return { run, attach };
|
|
4661
4786
|
}
|
|
4662
4787
|
var rootControls = /* @__PURE__ */ new WeakMap();
|
|
4663
|
-
function createRootHandle() {
|
|
4664
|
-
let binding;
|
|
4665
|
-
const handle = {
|
|
4666
|
-
view() {
|
|
4667
|
-
if (!binding) {
|
|
4668
|
-
throw new RuntimeRunStateError(
|
|
4669
|
-
"RootHandle.view: handle is not bound to a live run (attach it before run, read after run starts)"
|
|
4670
|
-
);
|
|
4671
|
-
}
|
|
4672
|
-
return binding.scope.view;
|
|
4673
|
-
},
|
|
4674
|
-
signal(msg) {
|
|
4675
|
-
if (!binding) {
|
|
4676
|
-
throw new RuntimeRunStateError("RootHandle.signal: handle is not bound to a live run");
|
|
4677
|
-
}
|
|
4678
|
-
binding.signal(msg);
|
|
4679
|
-
},
|
|
4680
|
-
abort(reason) {
|
|
4681
|
-
if (!binding) {
|
|
4682
|
-
throw new RuntimeRunStateError("RootHandle.abort: handle is not bound to a live run");
|
|
4683
|
-
}
|
|
4684
|
-
binding.cascadeAbort(reason ?? "root handle aborted");
|
|
4685
|
-
}
|
|
4686
|
-
};
|
|
4687
|
-
rootControls.set(handle, {
|
|
4688
|
-
bind(b) {
|
|
4689
|
-
binding = b;
|
|
4690
|
-
},
|
|
4691
|
-
unbind() {
|
|
4692
|
-
binding = void 0;
|
|
4693
|
-
}
|
|
4694
|
-
});
|
|
4695
|
-
return handle;
|
|
4696
|
-
}
|
|
4697
4788
|
function pushRootSignal(cascadeAbort) {
|
|
4698
4789
|
return (msg) => {
|
|
4699
4790
|
if (msg.kind === "cancel") cascadeAbort(msg.reason ?? "root signal: cancel");
|
|
@@ -4962,12 +5053,12 @@ async function trajectoryReport(journal, blobs, root, options = {}) {
|
|
|
4962
5053
|
label: ev.label,
|
|
4963
5054
|
runtime: ev.runtime,
|
|
4964
5055
|
status: "pending",
|
|
4965
|
-
ownSpend:
|
|
5056
|
+
ownSpend: zeroSpend3(),
|
|
4966
5057
|
children: []
|
|
4967
5058
|
});
|
|
4968
5059
|
}
|
|
4969
5060
|
for (const ev of closes) {
|
|
4970
|
-
const node =
|
|
5061
|
+
const node = requireNode(nodes, ev.id, root);
|
|
4971
5062
|
if (ev.kind === "cancelled") {
|
|
4972
5063
|
node.status = "cancelled";
|
|
4973
5064
|
continue;
|
|
@@ -4979,7 +5070,7 @@ async function trajectoryReport(journal, blobs, root, options = {}) {
|
|
|
4979
5070
|
}
|
|
4980
5071
|
for (const ev of events) {
|
|
4981
5072
|
if (ev.kind !== "metered") continue;
|
|
4982
|
-
const node =
|
|
5073
|
+
const node = requireNode(nodes, ev.id, root);
|
|
4983
5074
|
node.ownSpend = addNodeSpend(node.ownSpend, ev.spend);
|
|
4984
5075
|
}
|
|
4985
5076
|
if (!nodes.has(root)) {
|
|
@@ -4989,7 +5080,7 @@ async function trajectoryReport(journal, blobs, root, options = {}) {
|
|
|
4989
5080
|
}
|
|
4990
5081
|
for (const ev of spawns) {
|
|
4991
5082
|
if (ev.parent === void 0) continue;
|
|
4992
|
-
|
|
5083
|
+
requireNode(nodes, ev.parent, root).children.push(ev.id);
|
|
4993
5084
|
}
|
|
4994
5085
|
const rolledUp = rollUpSpend(nodes, root);
|
|
4995
5086
|
if (options.withOutputs) {
|
|
@@ -5037,7 +5128,7 @@ function rollUpSpend(nodes, root) {
|
|
|
5037
5128
|
while (stack.length > 0) {
|
|
5038
5129
|
const frame = stack.pop();
|
|
5039
5130
|
if (frame === void 0) continue;
|
|
5040
|
-
const node =
|
|
5131
|
+
const node = requireNode(nodes, frame.id, root);
|
|
5041
5132
|
if (!frame.expanded) {
|
|
5042
5133
|
stack.push({ id: frame.id, expanded: true });
|
|
5043
5134
|
for (const child of node.children) stack.push({ id: child, expanded: false });
|
|
@@ -5086,7 +5177,7 @@ function countStatuses(reported) {
|
|
|
5086
5177
|
for (const node of reported) counts[node.status] += 1;
|
|
5087
5178
|
return counts;
|
|
5088
5179
|
}
|
|
5089
|
-
function
|
|
5180
|
+
function zeroSpend3() {
|
|
5090
5181
|
return { iterations: 0, tokens: zeroTokenUsage(), usd: 0, ms: 0 };
|
|
5091
5182
|
}
|
|
5092
5183
|
function addNodeSpend(a, b) {
|
|
@@ -5146,7 +5237,7 @@ function isNode(node) {
|
|
|
5146
5237
|
function bySeq(a, b) {
|
|
5147
5238
|
return a.seq - b.seq;
|
|
5148
5239
|
}
|
|
5149
|
-
function
|
|
5240
|
+
function requireNode(nodes, id, root) {
|
|
5150
5241
|
const node = nodes.get(id);
|
|
5151
5242
|
if (!node) {
|
|
5152
5243
|
throw new Error(
|
|
@@ -5551,7 +5642,7 @@ var perChild = (innerTurns) => ({
|
|
|
5551
5642
|
maxIterations: innerTurns + 1,
|
|
5552
5643
|
maxTokens: 1e6
|
|
5553
5644
|
});
|
|
5554
|
-
function
|
|
5645
|
+
function depthStrategy(surface, task, opts, cfg) {
|
|
5555
5646
|
const innerTurns = opts.innerTurns ?? 4;
|
|
5556
5647
|
let pendingSteer;
|
|
5557
5648
|
return {
|
|
@@ -5614,7 +5705,7 @@ Address each with the tools, verify they took, then continue.`;
|
|
|
5614
5705
|
}
|
|
5615
5706
|
};
|
|
5616
5707
|
}
|
|
5617
|
-
function
|
|
5708
|
+
function breadthStrategy(_surface, task, opts, cfg) {
|
|
5618
5709
|
const innerTurns = opts.innerTurns ?? 4;
|
|
5619
5710
|
return {
|
|
5620
5711
|
name: "breadth",
|
|
@@ -5657,11 +5748,11 @@ function breadthDriver(_surface, task, opts, cfg) {
|
|
|
5657
5748
|
}
|
|
5658
5749
|
var sample = {
|
|
5659
5750
|
name: "sample",
|
|
5660
|
-
driver: (surface, task, opts, budget) =>
|
|
5751
|
+
driver: (surface, task, opts, budget) => breadthStrategy(surface, task, opts, { width: budget })
|
|
5661
5752
|
};
|
|
5662
5753
|
var refine = {
|
|
5663
5754
|
name: "refine",
|
|
5664
|
-
driver: (surface, task, opts, budget) =>
|
|
5755
|
+
driver: (surface, task, opts, budget) => depthStrategy(surface, task, opts, { maxShots: budget })
|
|
5665
5756
|
};
|
|
5666
5757
|
function defineStrategy(name, run) {
|
|
5667
5758
|
return {
|
|
@@ -6792,6 +6883,9 @@ ${summary}`,
|
|
|
6792
6883
|
};
|
|
6793
6884
|
}
|
|
6794
6885
|
|
|
6886
|
+
// src/runtime/supervise/authoring.ts
|
|
6887
|
+
import { computeFindingId, makeFinding as makeFinding2 } from "@tangle-network/agent-eval";
|
|
6888
|
+
|
|
6795
6889
|
// src/runtime/supervise/completion-gate.ts
|
|
6796
6890
|
function gateOnDeliverable(inner, deliverable) {
|
|
6797
6891
|
let gated;
|
|
@@ -6844,13 +6938,13 @@ function asAuthoredProfile(raw) {
|
|
|
6844
6938
|
...typeof p.model === "string" ? { model: p.model } : {}
|
|
6845
6939
|
};
|
|
6846
6940
|
}
|
|
6847
|
-
function
|
|
6941
|
+
function supervisorInstructions(opts) {
|
|
6848
6942
|
return [
|
|
6849
6943
|
"You are a SUPERVISOR. You do NOT do the work yourself \u2014 your job is to DESIGN and DRIVE specialist worker agents.",
|
|
6850
6944
|
"",
|
|
6851
6945
|
"For the task you are given:",
|
|
6852
6946
|
"1. DECOMPOSE it into the smallest set of sub-tasks a single focused worker can each deliver.",
|
|
6853
|
-
"2. For EACH sub-task, AUTHOR a worker by calling
|
|
6947
|
+
"2. For EACH sub-task, AUTHOR a worker by calling spawn_agent with a COMPLETE `profile`:",
|
|
6854
6948
|
" \u2022 name: a short id for the worker.",
|
|
6855
6949
|
' \u2022 systemPrompt: rich, specific instructions for THIS sub-task \u2014 tell the worker exactly what to produce, how to use its tools fully, and what "done" means. Never a one-liner; write the prompt a power-user would write.',
|
|
6856
6950
|
" \u2022 model: the model best suited to this sub-task (omit to use the default).",
|
|
@@ -6901,6 +6995,93 @@ function authoredWorker(profile, opts) {
|
|
|
6901
6995
|
};
|
|
6902
6996
|
return { name: profile.name, act: async () => "", executorSpec: spec };
|
|
6903
6997
|
}
|
|
6998
|
+
var defaultProfileRichnessThresholds = {
|
|
6999
|
+
minSystemPromptChars: 600,
|
|
7000
|
+
minSystemPromptLines: 6
|
|
7001
|
+
};
|
|
7002
|
+
function resolveSystemPrompt(profile) {
|
|
7003
|
+
const pr = profile.prompt;
|
|
7004
|
+
if (typeof pr === "string") return pr;
|
|
7005
|
+
if (pr && typeof pr === "object") {
|
|
7006
|
+
const o = pr;
|
|
7007
|
+
if (typeof o.systemPrompt === "string") return o.systemPrompt;
|
|
7008
|
+
if (typeof o.system === "string") return o.system;
|
|
7009
|
+
}
|
|
7010
|
+
return "";
|
|
7011
|
+
}
|
|
7012
|
+
function assessAuthoredProfile(profile, opts) {
|
|
7013
|
+
const th = { ...defaultProfileRichnessThresholds, ...opts?.thresholds ?? {} };
|
|
7014
|
+
const systemPrompt = resolveSystemPrompt(profile);
|
|
7015
|
+
const trimmed = systemPrompt.trim();
|
|
7016
|
+
const systemPromptChars = trimmed.length;
|
|
7017
|
+
const systemPromptLines = trimmed ? trimmed.split("\n").filter((l) => l.trim().length > 0).length : 0;
|
|
7018
|
+
const sentenceCount = trimmed ? (trimmed.match(/[.!?](\s|$)/g) ?? []).length || (trimmed ? 1 : 0) : 0;
|
|
7019
|
+
const hasDescription = typeof profile.description === "string" && profile.description.trim().length > 0;
|
|
7020
|
+
const tools = profile.tools;
|
|
7021
|
+
const hasTools = !!tools && Object.keys(tools).length > 0;
|
|
7022
|
+
const skills = profile.resources?.skills;
|
|
7023
|
+
const hasSkills = Array.isArray(skills) && skills.length > 0;
|
|
7024
|
+
const mcp = profile.mcp;
|
|
7025
|
+
const hasMcp = !!mcp && Object.keys(mcp).length > 0;
|
|
7026
|
+
const subagents = profile.subagents;
|
|
7027
|
+
const hasSubagents = !!subagents && Object.keys(subagents).length > 0;
|
|
7028
|
+
const reasons = [];
|
|
7029
|
+
const promptThin = systemPromptChars < th.minSystemPromptChars || systemPromptLines < th.minSystemPromptLines;
|
|
7030
|
+
if (promptThin)
|
|
7031
|
+
reasons.push(
|
|
7032
|
+
`system prompt is thin (${systemPromptChars} chars, ${systemPromptLines} lines; need \u2265${th.minSystemPromptChars} chars and \u2265${th.minSystemPromptLines} lines)`
|
|
7033
|
+
);
|
|
7034
|
+
if (!hasTools)
|
|
7035
|
+
reasons.push("no tools granted (a worker can only act through the tools you grant it)");
|
|
7036
|
+
if (!hasSkills) reasons.push("no skills attached (no reusable how-to notes injected)");
|
|
7037
|
+
if (opts?.needsMcp && !hasMcp) reasons.push("no MCP server, but the task needs data/tool access");
|
|
7038
|
+
const signals = [!promptThin, hasTools, hasSkills, hasDescription, opts?.needsMcp ? hasMcp : true];
|
|
7039
|
+
const richness = signals.filter(Boolean).length / signals.length;
|
|
7040
|
+
const thin = promptThin || !hasTools && !hasSkills && !hasMcp;
|
|
7041
|
+
return {
|
|
7042
|
+
name: profile.name ?? "worker",
|
|
7043
|
+
systemPrompt,
|
|
7044
|
+
systemPromptChars,
|
|
7045
|
+
systemPromptLines,
|
|
7046
|
+
sentenceCount,
|
|
7047
|
+
hasDescription,
|
|
7048
|
+
hasTools,
|
|
7049
|
+
hasSkills,
|
|
7050
|
+
hasMcp,
|
|
7051
|
+
hasSubagents,
|
|
7052
|
+
richness,
|
|
7053
|
+
thin,
|
|
7054
|
+
reasons
|
|
7055
|
+
};
|
|
7056
|
+
}
|
|
7057
|
+
function profileRichnessFinding(richness, opts) {
|
|
7058
|
+
const analyst_id = opts?.analystId ?? "profile-richness";
|
|
7059
|
+
const subject = richness.name;
|
|
7060
|
+
const claim = richness.thin ? `Worker "${richness.name}" was authored as a THIN profile: ${richness.reasons.join("; ")}.` : `Worker "${richness.name}" was authored as a rich profile (richness ${(richness.richness * 100).toFixed(0)}%).`;
|
|
7061
|
+
const severity = richness.thin ? richness.richness < 0.25 ? "high" : "medium" : "info";
|
|
7062
|
+
return makeFinding2({
|
|
7063
|
+
analyst_id,
|
|
7064
|
+
severity,
|
|
7065
|
+
area: "profile-quality",
|
|
7066
|
+
claim,
|
|
7067
|
+
subject,
|
|
7068
|
+
confidence: 0.9,
|
|
7069
|
+
evidence_refs: [
|
|
7070
|
+
{
|
|
7071
|
+
kind: "metric",
|
|
7072
|
+
uri: `profile:${subject}`,
|
|
7073
|
+
excerpt: `chars=${richness.systemPromptChars} lines=${richness.systemPromptLines} tools=${richness.hasTools} skills=${richness.hasSkills} mcp=${richness.hasMcp} richness=${richness.richness.toFixed(2)}`
|
|
7074
|
+
}
|
|
7075
|
+
],
|
|
7076
|
+
...richness.thin ? { recommended_action: `Re-author "${richness.name}" with: ${richness.reasons.join("; ")}.` } : {},
|
|
7077
|
+
id_basis: computeFindingId({
|
|
7078
|
+
analyst_id,
|
|
7079
|
+
area: "profile-quality",
|
|
7080
|
+
subject,
|
|
7081
|
+
claim: `richness:${richness.thin ? "thin" : "rich"}`
|
|
7082
|
+
})
|
|
7083
|
+
});
|
|
7084
|
+
}
|
|
6904
7085
|
|
|
6905
7086
|
// src/runtime/supervise/event-bus.ts
|
|
6906
7087
|
function createEventBus(now = Date.now) {
|
|
@@ -6959,7 +7140,19 @@ function createEventBus(now = Date.now) {
|
|
|
6959
7140
|
}
|
|
6960
7141
|
|
|
6961
7142
|
// src/mcp/tools/coordination.ts
|
|
6962
|
-
var
|
|
7143
|
+
var coordinationVerbNames = [
|
|
7144
|
+
"spawn_agent",
|
|
7145
|
+
"observe_agent",
|
|
7146
|
+
"steer_agent",
|
|
7147
|
+
"await_event",
|
|
7148
|
+
"list_questions",
|
|
7149
|
+
"answer_question",
|
|
7150
|
+
"ask_parent",
|
|
7151
|
+
"stop",
|
|
7152
|
+
"list_analysts",
|
|
7153
|
+
"run_analyst"
|
|
7154
|
+
];
|
|
7155
|
+
var idArg = { type: "string", description: "The workerId returned by spawn_agent." };
|
|
6963
7156
|
function createCoordinationTools(opts) {
|
|
6964
7157
|
let stopped = false;
|
|
6965
7158
|
let reason;
|
|
@@ -6983,6 +7176,28 @@ function createCoordinationTools(opts) {
|
|
|
6983
7176
|
throw new Error("coordination tools: arguments must be an object");
|
|
6984
7177
|
return raw;
|
|
6985
7178
|
};
|
|
7179
|
+
const mergeBudget = (base, raw) => {
|
|
7180
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
7181
|
+
throw new Error('coordination tools: "budget" must be an object');
|
|
7182
|
+
const o = raw;
|
|
7183
|
+
const field = (name) => {
|
|
7184
|
+
const v = o[name];
|
|
7185
|
+
if (v === void 0) return void 0;
|
|
7186
|
+
if (typeof v !== "number" || !Number.isFinite(v))
|
|
7187
|
+
throw new Error(`coordination tools: "budget.${name}" must be a finite number`);
|
|
7188
|
+
return v;
|
|
7189
|
+
};
|
|
7190
|
+
const maxIterations = field("maxIterations");
|
|
7191
|
+
const maxTokens = field("maxTokens");
|
|
7192
|
+
const maxUsd = field("maxUsd");
|
|
7193
|
+
const deadlineMs = field("deadlineMs");
|
|
7194
|
+
return {
|
|
7195
|
+
maxIterations: maxIterations ?? base.maxIterations,
|
|
7196
|
+
maxTokens: maxTokens ?? base.maxTokens,
|
|
7197
|
+
...(maxUsd ?? base.maxUsd) === void 0 ? {} : { maxUsd: maxUsd ?? base.maxUsd },
|
|
7198
|
+
...(deadlineMs ?? base.deadlineMs) === void 0 ? {} : { deadlineMs: deadlineMs ?? base.deadlineMs }
|
|
7199
|
+
};
|
|
7200
|
+
};
|
|
6986
7201
|
const level = (v) => {
|
|
6987
7202
|
if (v === "worker" || v === "driver" || v === "loop") return v;
|
|
6988
7203
|
throw new Error('coordination tools: "level" must be worker, driver, or loop');
|
|
@@ -7101,29 +7316,40 @@ function createCoordinationTools(opts) {
|
|
|
7101
7316
|
};
|
|
7102
7317
|
const tools = [
|
|
7103
7318
|
{
|
|
7104
|
-
name: "
|
|
7105
|
-
description: "Start a worker the driver will drive. `profile` is the worker or another driver; `task` is what it should do. Reserves budget from the conserved pool and fails closed.",
|
|
7319
|
+
name: "spawn_agent",
|
|
7320
|
+
description: "Start a worker the driver will drive. `profile` is the worker or another driver; `task` is what it should do. Reserves budget from the conserved pool and fails closed. Pass an optional `budget` (per-field) to give a hard sub-task more than the default \u2014 it merges over the per-worker default; the conserved pool is still the hard fence.",
|
|
7106
7321
|
inputSchema: {
|
|
7107
7322
|
type: "object",
|
|
7108
7323
|
properties: {
|
|
7109
7324
|
profile: { description: "The worker/driver profile to run." },
|
|
7110
7325
|
task: { description: "The task the worker should perform." },
|
|
7111
|
-
label: { type: "string", description: "Optional trace label." }
|
|
7326
|
+
label: { type: "string", description: "Optional trace label." },
|
|
7327
|
+
budget: {
|
|
7328
|
+
type: "object",
|
|
7329
|
+
description: "Optional per-spawn budget that merges over the per-worker default (per field). Only set the ceilings this sub-task needs raised; the conserved pool still fences.",
|
|
7330
|
+
properties: {
|
|
7331
|
+
maxIterations: { type: "number" },
|
|
7332
|
+
maxTokens: { type: "number" },
|
|
7333
|
+
maxUsd: { type: "number" },
|
|
7334
|
+
deadlineMs: { type: "number" }
|
|
7335
|
+
}
|
|
7336
|
+
}
|
|
7112
7337
|
},
|
|
7113
7338
|
required: ["profile", "task"]
|
|
7114
7339
|
},
|
|
7115
7340
|
handler: (raw) => {
|
|
7116
7341
|
const a = obj2(raw);
|
|
7117
7342
|
const agent = opts.makeWorkerAgent(a.profile);
|
|
7343
|
+
const budget = a.budget === void 0 ? opts.perWorker : mergeBudget(opts.perWorker, a.budget);
|
|
7118
7344
|
const res = opts.scope.spawn(agent, a.task, {
|
|
7119
|
-
budget
|
|
7345
|
+
budget,
|
|
7120
7346
|
label: typeof a.label === "string" ? a.label : "worker"
|
|
7121
7347
|
});
|
|
7122
7348
|
return Promise.resolve(res.ok ? { workerId: res.handle.id } : { error: res.reason });
|
|
7123
7349
|
}
|
|
7124
7350
|
},
|
|
7125
7351
|
{
|
|
7126
|
-
name: "
|
|
7352
|
+
name: "observe_agent",
|
|
7127
7353
|
description: "Inspect a worker status, spend, and settled output artifact when available.",
|
|
7128
7354
|
inputSchema: { type: "object", properties: { workerId: idArg }, required: ["workerId"] },
|
|
7129
7355
|
handler: async (raw) => {
|
|
@@ -7140,7 +7366,7 @@ function createCoordinationTools(opts) {
|
|
|
7140
7366
|
}
|
|
7141
7367
|
},
|
|
7142
7368
|
{
|
|
7143
|
-
name: "
|
|
7369
|
+
name: "steer_agent",
|
|
7144
7370
|
description: "Send a message DOWN to a still-LIVE worker (parent\u2192child): a new instruction, a course correction, or a continuation. The worker drains it at its next step boundary \u2014 and before it may settle, so it cannot finish while a message it never read is pending. A worker that already settled is gone (returns delivered:false) \u2014 spawn a fresh one instead.",
|
|
7145
7371
|
inputSchema: {
|
|
7146
7372
|
type: "object",
|
|
@@ -7361,13 +7587,26 @@ function deadlinePassed(scope, now) {
|
|
|
7361
7587
|
const b = scope.budget;
|
|
7362
7588
|
return b.deadlineMs > 0 && now() >= b.deadlineMs;
|
|
7363
7589
|
}
|
|
7364
|
-
function
|
|
7365
|
-
if (typeof opts.
|
|
7366
|
-
throw new ValidationError("
|
|
7590
|
+
function driverAgent(opts) {
|
|
7591
|
+
if (typeof opts.brain !== "function") {
|
|
7592
|
+
throw new ValidationError("driverAgent: opts.brain must be a function");
|
|
7593
|
+
}
|
|
7594
|
+
if ((opts.extraTools?.length ?? 0) > 0 && typeof opts.executeExtraTool !== "function") {
|
|
7595
|
+
throw new ValidationError(
|
|
7596
|
+
"driverAgent: extraTools requires executeExtraTool (how to run a work-tool call)"
|
|
7597
|
+
);
|
|
7598
|
+
}
|
|
7599
|
+
const reserved = new Set(coordinationVerbNames);
|
|
7600
|
+
for (const t of opts.extraTools ?? []) {
|
|
7601
|
+
if (reserved.has(t.name)) {
|
|
7602
|
+
throw new ValidationError(
|
|
7603
|
+
`driverAgent: extra work tool "${t.name}" collides with a coordination verb`
|
|
7604
|
+
);
|
|
7605
|
+
}
|
|
7367
7606
|
}
|
|
7368
7607
|
if (opts.maxTurns !== void 0 && opts.maxTurns < 0) {
|
|
7369
7608
|
throw new ValidationError(
|
|
7370
|
-
"
|
|
7609
|
+
"driverAgent: maxTurns must be >= 0 (0 lifts the turn cap; bounds become the conserved pool + deadline + abort)"
|
|
7371
7610
|
);
|
|
7372
7611
|
}
|
|
7373
7612
|
const maxTurns = opts.maxTurns === 0 ? runawayTripwireTurns : opts.maxTurns ?? 16;
|
|
@@ -7382,24 +7621,23 @@ function coordinationDriverAgent(opts) {
|
|
|
7382
7621
|
perWorker: opts.perWorker
|
|
7383
7622
|
});
|
|
7384
7623
|
const byName = new Map(coord.tools.map((t) => [t.name, t]));
|
|
7385
|
-
const toolSpecs =
|
|
7386
|
-
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
|
|
7624
|
+
const toolSpecs = [
|
|
7625
|
+
...coord.tools.map((t) => ({
|
|
7626
|
+
type: "function",
|
|
7627
|
+
function: { name: t.name, description: t.description, parameters: t.inputSchema }
|
|
7628
|
+
})),
|
|
7629
|
+
// Work tools the driver calls DIRECTLY — so it can ACT, not only delegate.
|
|
7630
|
+
...(opts.extraTools ?? []).map((t) => ({
|
|
7631
|
+
type: "function",
|
|
7632
|
+
function: { name: t.name, description: t.description, parameters: t.parameters }
|
|
7633
|
+
}))
|
|
7634
|
+
];
|
|
7390
7635
|
const system = typeof opts.systemPrompt === "function" ? opts.systemPrompt(task) : opts.systemPrompt;
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
if (poolStarved(scope, opts.perWorker) || deadlinePassed(scope, now)) break;
|
|
7395
|
-
const res = await opts.chat.next({ system, messages, tools: toolSpecs });
|
|
7396
|
-
const calls = res.toolCalls ?? [];
|
|
7636
|
+
let turn = 0;
|
|
7637
|
+
const chat = async (messages, tools) => {
|
|
7638
|
+
const res = await opts.brain(messages, tools);
|
|
7397
7639
|
if (res.usage || res.costUsd !== void 0) {
|
|
7398
7640
|
const turnSpend = {
|
|
7399
|
-
// iterations:0 — the conserved iteration channel (`maxIterations`) budgets CHILD rounds,
|
|
7400
|
-
// not driver turns; counting turns there would conflate the two AND make a driver arm's
|
|
7401
|
-
// iteration count diverge from a blind arm's. The driver is bounded by maxTurns + the
|
|
7402
|
-
// token/usd pool; its turn COUNT stays observable via the per-turn `agent.turn` events.
|
|
7403
7641
|
iterations: 0,
|
|
7404
7642
|
tokens: { input: res.usage?.input ?? 0, output: res.usage?.output ?? 0 },
|
|
7405
7643
|
usd: res.costUsd ?? 0,
|
|
@@ -7409,28 +7647,47 @@ function coordinationDriverAgent(opts) {
|
|
|
7409
7647
|
kind: "driver-inference",
|
|
7410
7648
|
driver: opts.name,
|
|
7411
7649
|
turn,
|
|
7412
|
-
toolCalls:
|
|
7650
|
+
toolCalls: (res.toolCalls ?? []).map((c) => c.name)
|
|
7413
7651
|
});
|
|
7414
7652
|
}
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
}
|
|
7653
|
+
turn += 1;
|
|
7654
|
+
return res;
|
|
7655
|
+
};
|
|
7656
|
+
await runBrainLoop({
|
|
7657
|
+
chat,
|
|
7658
|
+
tools: toolSpecs,
|
|
7659
|
+
execute: async (name, args) => {
|
|
7660
|
+
if (opts.executeExtraTool) {
|
|
7661
|
+
const worked = await runExtraTool(opts.executeExtraTool, name, args);
|
|
7662
|
+
if (worked !== null && worked !== void 0) return worked;
|
|
7663
|
+
}
|
|
7664
|
+
const tool = byName.get(name);
|
|
7665
|
+
const result = tool ? await runTool(tool, args) : { error: `unknown tool: ${name}` };
|
|
7666
|
+
return safeJson(result);
|
|
7667
|
+
},
|
|
7668
|
+
initialMessages: [
|
|
7669
|
+
{ role: "system", content: system },
|
|
7670
|
+
{ role: "user", content: stringifyTask(task) }
|
|
7671
|
+
],
|
|
7672
|
+
maxTurns,
|
|
7673
|
+
// The conserved-pool + deadline + external-stop bound (what maxTurns=0 relies on): a driver
|
|
7674
|
+
// that can no longer spawn (pool starved) or has run past the deadline stops here instead of
|
|
7675
|
+
// burning turns. Checked before each inference turn.
|
|
7676
|
+
hooks: {
|
|
7677
|
+
stopBefore: () => coord.isStopped() || scope.signal.aborted || poolStarved(scope, opts.perWorker) || deadlinePassed(scope, now)
|
|
7428
7678
|
}
|
|
7429
|
-
}
|
|
7679
|
+
});
|
|
7430
7680
|
return finalize2(coord, opts.blobs);
|
|
7431
7681
|
}
|
|
7432
7682
|
};
|
|
7433
7683
|
}
|
|
7684
|
+
async function runExtraTool(execute, name, args) {
|
|
7685
|
+
try {
|
|
7686
|
+
return await execute(name, args);
|
|
7687
|
+
} catch (e) {
|
|
7688
|
+
return `error: ${e instanceof Error ? e.message : String(e)}`;
|
|
7689
|
+
}
|
|
7690
|
+
}
|
|
7434
7691
|
async function runTool(tool, args) {
|
|
7435
7692
|
try {
|
|
7436
7693
|
return await tool.handler(args);
|
|
@@ -7438,13 +7695,16 @@ async function runTool(tool, args) {
|
|
|
7438
7695
|
return { error: e instanceof Error ? e.message : String(e) };
|
|
7439
7696
|
}
|
|
7440
7697
|
}
|
|
7441
|
-
async function
|
|
7442
|
-
const delivered =
|
|
7698
|
+
async function finalizeBestDelivered(settled, blobs) {
|
|
7699
|
+
const delivered = settled.filter((w) => w.status === "done" && w.valid === true);
|
|
7443
7700
|
if (delivered.length === 0) return void 0;
|
|
7444
7701
|
let best = delivered[0];
|
|
7445
7702
|
for (const w of delivered) if ((w.score ?? 0) > (best.score ?? 0)) best = w;
|
|
7446
7703
|
return best.outRef ? await blobs.get(best.outRef) : void 0;
|
|
7447
7704
|
}
|
|
7705
|
+
async function finalize2(coord, blobs) {
|
|
7706
|
+
return finalizeBestDelivered(coord.settled(), blobs);
|
|
7707
|
+
}
|
|
7448
7708
|
function stringifyTask(task) {
|
|
7449
7709
|
return typeof task === "string" ? task : safeJson(task);
|
|
7450
7710
|
}
|
|
@@ -7495,12 +7755,12 @@ function eventToSnapshot(event) {
|
|
|
7495
7755
|
// src/mcp/delegation-store.ts
|
|
7496
7756
|
import { mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
7497
7757
|
import { dirname } from "path";
|
|
7498
|
-
var DelegationStateCorruptError = class extends
|
|
7758
|
+
var DelegationStateCorruptError = class extends AgentEvalError2 {
|
|
7499
7759
|
constructor(message, options) {
|
|
7500
7760
|
super("validation", message, options);
|
|
7501
7761
|
}
|
|
7502
7762
|
};
|
|
7503
|
-
var DelegationPersistenceError = class extends
|
|
7763
|
+
var DelegationPersistenceError = class extends AgentEvalError2 {
|
|
7504
7764
|
constructor(message, options) {
|
|
7505
7765
|
super("config", message, options);
|
|
7506
7766
|
}
|
|
@@ -8406,7 +8666,7 @@ function createDetachedTurnTrace(options) {
|
|
|
8406
8666
|
function detachedRunningPhase(elapsedMs) {
|
|
8407
8667
|
return elapsedMs === void 0 ? "detached-running" : `detached-running ${Math.round(elapsedMs / 1e3)}s`;
|
|
8408
8668
|
}
|
|
8409
|
-
function
|
|
8669
|
+
function createDetachedTurnResumeDriver(options) {
|
|
8410
8670
|
const cancelHooked = /* @__PURE__ */ new Set();
|
|
8411
8671
|
return {
|
|
8412
8672
|
intervalMs: options.intervalMs ?? DEFAULT_TICK_INTERVAL_MS,
|
|
@@ -9668,6 +9928,16 @@ function watchTrace(source, opts = {}) {
|
|
|
9668
9928
|
});
|
|
9669
9929
|
}
|
|
9670
9930
|
|
|
9931
|
+
// src/runtime/supervise/model-policy.ts
|
|
9932
|
+
function assertModelAllowed(model, allowed) {
|
|
9933
|
+
if (!allowed || model === void 0) return;
|
|
9934
|
+
if (!allowed.includes(model)) {
|
|
9935
|
+
throw new ConfigError(
|
|
9936
|
+
`model ${JSON.stringify(model)} is not in the allowed set ${JSON.stringify([...allowed])}`
|
|
9937
|
+
);
|
|
9938
|
+
}
|
|
9939
|
+
}
|
|
9940
|
+
|
|
9671
9941
|
// src/runtime/supervise/patch-checks.ts
|
|
9672
9942
|
var DEFAULT_MAX_DIFF_LINES = 400;
|
|
9673
9943
|
var secretPathPattern = /(^|\/)(\.env(\.|$)|.*\.(pem|key|p12|pfx|keystore|wallet)|id_rsa|id_ed25519|secrets?\.json|credentials?\.json)$/i;
|
|
@@ -9692,12 +9962,6 @@ function countDiffLines(patch) {
|
|
|
9692
9962
|
}
|
|
9693
9963
|
return count;
|
|
9694
9964
|
}
|
|
9695
|
-
function isNonEmptyPatch(patch) {
|
|
9696
|
-
return touchedPathsFromPatch(patch).length > 0 && patch.trim().length > 0;
|
|
9697
|
-
}
|
|
9698
|
-
function touchesSecretPath(patch) {
|
|
9699
|
-
return touchedPathsFromPatch(patch).filter((p) => secretPathPattern.test(p));
|
|
9700
|
-
}
|
|
9701
9965
|
function runCoderChecks(input, constraints = {}) {
|
|
9702
9966
|
const maxDiff = constraints.maxDiffLines ?? DEFAULT_MAX_DIFF_LINES;
|
|
9703
9967
|
const forbidden = constraints.forbiddenPaths ?? [];
|
|
@@ -9784,72 +10048,132 @@ function signalPass(value, required) {
|
|
|
9784
10048
|
return !required;
|
|
9785
10049
|
}
|
|
9786
10050
|
|
|
9787
|
-
// src/runtime/supervise/
|
|
9788
|
-
function
|
|
9789
|
-
const
|
|
10051
|
+
// src/runtime/supervise/run-context.ts
|
|
10052
|
+
function createInMemoryRunContext(opts = {}) {
|
|
10053
|
+
const base = createExecutorRegistry();
|
|
9790
10054
|
return {
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
...messages.map(toOpenAI)
|
|
9795
|
-
];
|
|
9796
|
-
const oaTools = tools.map((t) => ({
|
|
9797
|
-
type: "function",
|
|
9798
|
-
function: { name: t.name, description: t.description, parameters: t.parameters }
|
|
9799
|
-
}));
|
|
9800
|
-
const r = await routerChatWithTools(c, oa, oaTools, { temperature, toolChoice: "auto" });
|
|
9801
|
-
return {
|
|
9802
|
-
...r.content ? { content: r.content } : {},
|
|
9803
|
-
// Forward the router's REAL usage + cost so the driver meters its own inference against the
|
|
9804
|
-
// conserved pool (the integrity hole: these were dropped on the floor before).
|
|
9805
|
-
...r.usage ? { usage: r.usage } : {},
|
|
9806
|
-
...typeof r.costUsd === "number" ? { costUsd: r.costUsd } : {},
|
|
9807
|
-
toolCalls: r.toolCalls.map((tc) => ({
|
|
9808
|
-
id: tc.id,
|
|
9809
|
-
name: tc.name,
|
|
9810
|
-
arguments: safeParse(tc.arguments)
|
|
9811
|
-
}))
|
|
9812
|
-
};
|
|
9813
|
-
}
|
|
10055
|
+
journal: new InMemorySpawnJournal(),
|
|
10056
|
+
blobs: new InMemoryResultBlobStore(),
|
|
10057
|
+
executors: opts.withDriver ? withDriverExecutor(base) : base
|
|
9814
10058
|
};
|
|
9815
10059
|
}
|
|
9816
|
-
|
|
9817
|
-
|
|
9818
|
-
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
|
|
10060
|
+
|
|
10061
|
+
// src/runtime/supervise/supervisor-agent.ts
|
|
10062
|
+
function supervisorAgent(profile, deps) {
|
|
10063
|
+
const name = profile.name ?? "supervisor";
|
|
10064
|
+
const systemPrompt = profile.systemPrompt ?? "";
|
|
10065
|
+
const harness = profile.harness ?? null;
|
|
10066
|
+
if (harness === null) {
|
|
10067
|
+
const brain = deps.brain ?? routerBrainFromProfile(profile, deps);
|
|
10068
|
+
return driverAgent({
|
|
10069
|
+
name,
|
|
10070
|
+
brain,
|
|
10071
|
+
blobs: deps.blobs,
|
|
10072
|
+
makeWorkerAgent: deps.makeWorkerAgent,
|
|
10073
|
+
perWorker: deps.perWorker,
|
|
10074
|
+
systemPrompt,
|
|
10075
|
+
...deps.extraTools ? { extraTools: deps.extraTools } : {},
|
|
10076
|
+
...deps.executeExtraTool ? { executeExtraTool: deps.executeExtraTool } : {},
|
|
10077
|
+
...deps.maxTurns !== void 0 ? { maxTurns: deps.maxTurns } : {}
|
|
10078
|
+
});
|
|
9827
10079
|
}
|
|
9828
|
-
|
|
9829
|
-
|
|
10080
|
+
const driveHarness = deps.driveHarness;
|
|
10081
|
+
if (!driveHarness) {
|
|
10082
|
+
throw new ValidationError(
|
|
10083
|
+
`supervisorAgent: profile.harness="${harness}" needs deps.driveHarness (how to run the harness with the coordination MCP mounted)`
|
|
10084
|
+
);
|
|
9830
10085
|
}
|
|
9831
|
-
return {
|
|
10086
|
+
return {
|
|
10087
|
+
name,
|
|
10088
|
+
async act(task, scope) {
|
|
10089
|
+
const mcp = await serveCoordinationMcp({
|
|
10090
|
+
scope,
|
|
10091
|
+
blobs: deps.blobs,
|
|
10092
|
+
makeWorkerAgent: deps.makeWorkerAgent,
|
|
10093
|
+
perWorker: deps.perWorker
|
|
10094
|
+
});
|
|
10095
|
+
try {
|
|
10096
|
+
await driveHarness({ profile, task, scope, coordinationMcpUrl: mcp.url });
|
|
10097
|
+
return await finalizeBestDelivered(mcp.settled(), deps.blobs);
|
|
10098
|
+
} finally {
|
|
10099
|
+
await mcp.close();
|
|
10100
|
+
}
|
|
10101
|
+
}
|
|
10102
|
+
};
|
|
9832
10103
|
}
|
|
9833
|
-
function
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
10104
|
+
function routerBrainFromProfile(profile, deps) {
|
|
10105
|
+
if (!deps.router) {
|
|
10106
|
+
throw new ValidationError(
|
|
10107
|
+
"supervisorAgent: a router-brained supervisor (harness null) needs deps.router (or deps.brain)"
|
|
10108
|
+
);
|
|
9838
10109
|
}
|
|
10110
|
+
return routerBrain({ ...deps.router, model: profile.model ?? deps.router.model });
|
|
9839
10111
|
}
|
|
9840
10112
|
|
|
9841
|
-
// src/runtime/supervise/
|
|
9842
|
-
function
|
|
9843
|
-
|
|
10113
|
+
// src/runtime/supervise/supervise.ts
|
|
10114
|
+
function workerFromBackend(backend, deliverable) {
|
|
10115
|
+
return (rawProfile) => {
|
|
10116
|
+
const p = rawProfile ?? {};
|
|
10117
|
+
const name = typeof p.name === "string" && p.name.length > 0 ? p.name : "worker";
|
|
10118
|
+
const spec = { profile: rawProfile, harness: null };
|
|
10119
|
+
const ctx = { signal: new AbortController().signal, seams: {} };
|
|
10120
|
+
const built = createExecutor(backend)(spec, ctx);
|
|
10121
|
+
const executor = deliverable ? gateOnDeliverable(built, deliverable) : built;
|
|
10122
|
+
return { name, act: async () => "", executorSpec: { ...spec, executor } };
|
|
10123
|
+
};
|
|
10124
|
+
}
|
|
10125
|
+
function defaultPerWorker(budget) {
|
|
9844
10126
|
return {
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
executors: opts.withDriver ? withDriverExecutor(base) : base
|
|
10127
|
+
maxIterations: budget.maxIterations,
|
|
10128
|
+
maxTokens: Math.max(1, Math.floor(budget.maxTokens / 4))
|
|
9848
10129
|
};
|
|
9849
10130
|
}
|
|
10131
|
+
function supervise(profile, task, opts) {
|
|
10132
|
+
const backendModel = opts.backend?.model;
|
|
10133
|
+
assertModelAllowed(opts.router?.model, opts.allowedModels);
|
|
10134
|
+
assertModelAllowed(profile.model, opts.allowedModels);
|
|
10135
|
+
assertModelAllowed(
|
|
10136
|
+
typeof backendModel === "string" ? backendModel : void 0,
|
|
10137
|
+
opts.allowedModels
|
|
10138
|
+
);
|
|
10139
|
+
const ctx = createInMemoryRunContext({ withDriver: true });
|
|
10140
|
+
const blobs = opts.blobs ?? ctx.blobs;
|
|
10141
|
+
const perWorker = opts.perWorker ?? defaultPerWorker(opts.budget);
|
|
10142
|
+
let makeWorkerAgent = opts.makeWorkerAgent;
|
|
10143
|
+
if (!makeWorkerAgent) {
|
|
10144
|
+
if (!opts.backend) {
|
|
10145
|
+
throw new ValidationError(
|
|
10146
|
+
"supervise: provide opts.backend (where workers run) or opts.makeWorkerAgent"
|
|
10147
|
+
);
|
|
10148
|
+
}
|
|
10149
|
+
makeWorkerAgent = workerFromBackend(opts.backend, opts.deliverable);
|
|
10150
|
+
}
|
|
10151
|
+
const agent = supervisorAgent(profile, {
|
|
10152
|
+
blobs,
|
|
10153
|
+
makeWorkerAgent,
|
|
10154
|
+
perWorker,
|
|
10155
|
+
...opts.router ? { router: opts.router } : {},
|
|
10156
|
+
...opts.brain ? { brain: opts.brain } : {},
|
|
10157
|
+
...opts.driveHarness ? { driveHarness: opts.driveHarness } : {},
|
|
10158
|
+
...opts.extraTools ? { extraTools: opts.extraTools } : {},
|
|
10159
|
+
...opts.executeExtraTool ? { executeExtraTool: opts.executeExtraTool } : {},
|
|
10160
|
+
...opts.maxTurns !== void 0 ? { maxTurns: opts.maxTurns } : {}
|
|
10161
|
+
});
|
|
10162
|
+
return createSupervisor().run(agent, task, {
|
|
10163
|
+
budget: opts.budget,
|
|
10164
|
+
runId: opts.runId ?? "supervise",
|
|
10165
|
+
journal: ctx.journal,
|
|
10166
|
+
blobs,
|
|
10167
|
+
executors: ctx.executors,
|
|
10168
|
+
maxDepth: opts.maxDepth ?? 8,
|
|
10169
|
+
...opts.now ? { now: opts.now } : {}
|
|
10170
|
+
});
|
|
10171
|
+
}
|
|
9850
10172
|
|
|
9851
10173
|
// src/runtime/supervise/trace-source.ts
|
|
9852
10174
|
function toToolSpan(input, runId, seq, at) {
|
|
10175
|
+
const startedAt = typeof input.startedAt === "number" ? input.startedAt : at;
|
|
10176
|
+
const endedAt = typeof input.endedAt === "number" ? input.endedAt : startedAt;
|
|
9853
10177
|
return {
|
|
9854
10178
|
spanId: `${runId}-t${seq}`,
|
|
9855
10179
|
runId,
|
|
@@ -9858,8 +10182,8 @@ function toToolSpan(input, runId, seq, at) {
|
|
|
9858
10182
|
toolName: input.toolName,
|
|
9859
10183
|
args: input.args,
|
|
9860
10184
|
status: input.status ?? "ok",
|
|
9861
|
-
startedAt
|
|
9862
|
-
endedAt
|
|
10185
|
+
startedAt,
|
|
10186
|
+
endedAt,
|
|
9863
10187
|
...input.result !== void 0 ? { result: input.result } : {}
|
|
9864
10188
|
};
|
|
9865
10189
|
}
|
|
@@ -9899,7 +10223,7 @@ var decodeOpenAiPart = (p) => {
|
|
|
9899
10223
|
const rawArgs = fn?.arguments ?? p.arguments;
|
|
9900
10224
|
return {
|
|
9901
10225
|
toolName: name,
|
|
9902
|
-
args: typeof rawArgs === "string" ?
|
|
10226
|
+
args: typeof rawArgs === "string" ? safeParse(rawArgs) : rawArgs ?? {},
|
|
9903
10227
|
...str(p.id) ? { callId: p.id } : str(fn?.id) ? { callId: fn?.id } : {}
|
|
9904
10228
|
};
|
|
9905
10229
|
};
|
|
@@ -9923,7 +10247,7 @@ function decodeToolPart(part, harness) {
|
|
|
9923
10247
|
}
|
|
9924
10248
|
return void 0;
|
|
9925
10249
|
}
|
|
9926
|
-
function
|
|
10250
|
+
function safeParse(s) {
|
|
9927
10251
|
try {
|
|
9928
10252
|
return JSON.parse(s);
|
|
9929
10253
|
} catch {
|
|
@@ -10369,13 +10693,22 @@ function tail(s) {
|
|
|
10369
10693
|
}
|
|
10370
10694
|
|
|
10371
10695
|
export {
|
|
10696
|
+
SessionMismatchError,
|
|
10697
|
+
BackendTransportError,
|
|
10698
|
+
RuntimeRunStateError,
|
|
10699
|
+
PlannerError,
|
|
10700
|
+
AgentEvalError2 as AgentEvalError,
|
|
10701
|
+
ConfigError,
|
|
10702
|
+
JudgeError,
|
|
10703
|
+
NotFoundError,
|
|
10704
|
+
ValidationError,
|
|
10705
|
+
runLocalHarness,
|
|
10706
|
+
assertModelAllowed,
|
|
10707
|
+
extractLlmCallEvent,
|
|
10708
|
+
mapSandboxEvent,
|
|
10372
10709
|
contentAddress,
|
|
10373
10710
|
InMemoryResultBlobStore,
|
|
10374
|
-
FileResultBlobStore,
|
|
10375
10711
|
InMemorySpawnJournal,
|
|
10376
|
-
FileSpawnJournal,
|
|
10377
|
-
replaySpawnTree,
|
|
10378
|
-
materializeTreeView,
|
|
10379
10712
|
anytimeReport,
|
|
10380
10713
|
renderAnytimeTable,
|
|
10381
10714
|
defaultAuditorInstruction,
|
|
@@ -10398,7 +10731,6 @@ export {
|
|
|
10398
10731
|
probeSandboxCapabilities,
|
|
10399
10732
|
createSandboxLineage,
|
|
10400
10733
|
runLoop,
|
|
10401
|
-
describeSandboxPlacement,
|
|
10402
10734
|
createSandboxForSpec,
|
|
10403
10735
|
defaultSelectWinner,
|
|
10404
10736
|
loopDispatch,
|
|
@@ -10407,7 +10739,6 @@ export {
|
|
|
10407
10739
|
createScopeAnalyst,
|
|
10408
10740
|
registryScopeAnalyst,
|
|
10409
10741
|
buildSteerContext,
|
|
10410
|
-
nestedScopeSeamKey,
|
|
10411
10742
|
createScope,
|
|
10412
10743
|
settledToIteration,
|
|
10413
10744
|
selectValidWinner,
|
|
@@ -10421,14 +10752,10 @@ export {
|
|
|
10421
10752
|
InMemoryCorpus,
|
|
10422
10753
|
FileCorpus,
|
|
10423
10754
|
renderCorpusToInstructions,
|
|
10424
|
-
driverRuntime,
|
|
10425
|
-
driverChild,
|
|
10426
|
-
isDriverSpec,
|
|
10427
|
-
driverExecutorFactory,
|
|
10428
|
-
withDriverExecutor,
|
|
10429
10755
|
routerChatWithUsage,
|
|
10430
10756
|
routerChatWithTools,
|
|
10431
10757
|
routerToolLoop,
|
|
10758
|
+
routerBrain,
|
|
10432
10759
|
createInbox,
|
|
10433
10760
|
createWorktree,
|
|
10434
10761
|
captureWorktreeDiff,
|
|
@@ -10441,7 +10768,6 @@ export {
|
|
|
10441
10768
|
spendFromUsageEvents,
|
|
10442
10769
|
createBudgetPool,
|
|
10443
10770
|
createSupervisor,
|
|
10444
|
-
createRootHandle,
|
|
10445
10771
|
createShapeRegistry,
|
|
10446
10772
|
builtinShapes,
|
|
10447
10773
|
registerShape,
|
|
@@ -10450,8 +10776,8 @@ export {
|
|
|
10450
10776
|
trajectoryReport,
|
|
10451
10777
|
equalKOnCost,
|
|
10452
10778
|
promotionGate,
|
|
10453
|
-
|
|
10454
|
-
|
|
10779
|
+
depthStrategy,
|
|
10780
|
+
breadthStrategy,
|
|
10455
10781
|
sample,
|
|
10456
10782
|
refine,
|
|
10457
10783
|
defineStrategy,
|
|
@@ -10470,11 +10796,15 @@ export {
|
|
|
10470
10796
|
runStrategyEvolution,
|
|
10471
10797
|
gateOnDeliverable,
|
|
10472
10798
|
asAuthoredProfile,
|
|
10473
|
-
|
|
10799
|
+
supervisorInstructions,
|
|
10474
10800
|
authoredWorker,
|
|
10801
|
+
defaultProfileRichnessThresholds,
|
|
10802
|
+
assessAuthoredProfile,
|
|
10803
|
+
profileRichnessFinding,
|
|
10475
10804
|
createEventBus,
|
|
10476
10805
|
createCoordinationTools,
|
|
10477
|
-
|
|
10806
|
+
driverAgent,
|
|
10807
|
+
finalizeBestDelivered,
|
|
10478
10808
|
InMemoryFeedbackStore,
|
|
10479
10809
|
eventToSnapshot,
|
|
10480
10810
|
DelegationStateCorruptError,
|
|
@@ -10493,7 +10823,7 @@ export {
|
|
|
10493
10823
|
parseDetachedSessionRef,
|
|
10494
10824
|
detachedTurnEvents,
|
|
10495
10825
|
runDetachedTurn,
|
|
10496
|
-
|
|
10826
|
+
createDetachedTurnResumeDriver,
|
|
10497
10827
|
DELEGATE_CODE_TOOL_NAME,
|
|
10498
10828
|
DELEGATE_CODE_DESCRIPTION,
|
|
10499
10829
|
DELEGATE_CODE_INPUT_SCHEMA,
|
|
@@ -10529,22 +10859,14 @@ export {
|
|
|
10529
10859
|
serveCoordinationMcp,
|
|
10530
10860
|
defaultToolDetectors,
|
|
10531
10861
|
watchTrace,
|
|
10532
|
-
touchedPathsFromPatch,
|
|
10533
|
-
countDiffLines,
|
|
10534
|
-
isNonEmptyPatch,
|
|
10535
|
-
touchesSecretPath,
|
|
10536
10862
|
runCoderChecks,
|
|
10537
10863
|
patchDelivered,
|
|
10538
|
-
routerDriverChat,
|
|
10539
10864
|
createInMemoryRunContext,
|
|
10540
|
-
|
|
10541
|
-
|
|
10542
|
-
|
|
10543
|
-
decodeOpenAiPart,
|
|
10544
|
-
toolPartDecoders,
|
|
10865
|
+
supervisorAgent,
|
|
10866
|
+
workerFromBackend,
|
|
10867
|
+
supervise,
|
|
10545
10868
|
decodeToolPart,
|
|
10546
10869
|
createPushTraceSource,
|
|
10547
|
-
createPartsTraceSource,
|
|
10548
10870
|
sandboxSessionTraceSource,
|
|
10549
10871
|
analyzeTrace,
|
|
10550
10872
|
worktreeFanout,
|
|
@@ -10553,6 +10875,8 @@ export {
|
|
|
10553
10875
|
localShell,
|
|
10554
10876
|
gitWorkspace,
|
|
10555
10877
|
jjWorkspace,
|
|
10556
|
-
runInWorkspace
|
|
10878
|
+
runInWorkspace,
|
|
10879
|
+
computeFindingId2 as computeFindingId,
|
|
10880
|
+
makeFinding3 as makeFinding
|
|
10557
10881
|
};
|
|
10558
|
-
//# sourceMappingURL=chunk-
|
|
10882
|
+
//# sourceMappingURL=chunk-QXWGSDAQ.js.map
|