@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.
Files changed (78) hide show
  1. package/README.md +81 -13
  2. package/dist/agent.d.ts +4 -5
  3. package/dist/agent.js +3 -6
  4. package/dist/agent.js.map +1 -1
  5. package/dist/chunk-BYZCXQHF.js +474 -0
  6. package/dist/chunk-BYZCXQHF.js.map +1 -0
  7. package/dist/{chunk-OYU5LR4T.js → chunk-EDCVUZZC.js} +2 -2
  8. package/dist/{chunk-QNUEFNU7.js → chunk-L5ZFBVT6.js} +6 -6
  9. package/dist/chunk-L5ZFBVT6.js.map +1 -0
  10. package/dist/{chunk-VKUHUFX7.js → chunk-QXWGSDAQ.js} +914 -590
  11. package/dist/chunk-QXWGSDAQ.js.map +1 -0
  12. package/dist/{chunk-LTEF2LYD.js → chunk-ZNQVMMR5.js} +3 -3
  13. package/dist/{coordination-Curpzeyc.d.ts → coordination-C7WxwHXq.d.ts} +8 -1
  14. package/dist/{delegates-CLFNAKyi.d.ts → delegates-DqAgo32T.d.ts} +105 -10
  15. package/dist/{improvement-adapter-BC4HhuAR.d.ts → improvement-adapter-BVuMragr.d.ts} +1 -1
  16. package/dist/index.d.ts +439 -100
  17. package/dist/index.js +583 -125
  18. package/dist/index.js.map +1 -1
  19. package/dist/intelligence.d.ts +2 -3
  20. package/dist/{loop-runner-bin-B6dzNZC8.d.ts → loop-runner-bin-B0NeLTRd.d.ts} +4 -4
  21. package/dist/loop-runner-bin.d.ts +7 -10
  22. package/dist/loop-runner-bin.js +4 -7
  23. package/dist/loops.d.ts +3149 -16
  24. package/dist/loops.js +34 -63
  25. package/dist/mcp/bin.js +14 -16
  26. package/dist/mcp/bin.js.map +1 -1
  27. package/dist/mcp/index.d.ts +8 -12
  28. package/dist/mcp/index.js +16 -19
  29. package/dist/mcp/index.js.map +1 -1
  30. package/dist/{openai-tools-CA2N3-Ak.d.ts → openai-tools-DPx9Gzvn.d.ts} +1 -1
  31. package/dist/profiles.d.ts +94 -6
  32. package/dist/profiles.js +320 -9
  33. package/dist/profiles.js.map +1 -1
  34. package/dist/{router-client-30Y_pca8.d.ts → router-client-C7kp_ECN.d.ts} +37 -1
  35. package/dist/{substrate-CUgk7F7s.d.ts → substrate-BoRXgvka.d.ts} +52 -1
  36. package/dist/{types-Crxftafi.d.ts → types-BYa2ZOAx.d.ts} +83 -2
  37. package/dist/{types-p8dWBIXL.d.ts → types-DJu6TBGp.d.ts} +2 -16
  38. package/dist/{worktree-fanout-DUiKPApb.d.ts → worktree-fanout-gNfl0Byj.d.ts} +9 -37
  39. package/package.json +9 -39
  40. package/dist/analyst-loop.d.ts +0 -52
  41. package/dist/analyst-loop.js +0 -11
  42. package/dist/analyst-loop.js.map +0 -1
  43. package/dist/audit.d.ts +0 -93
  44. package/dist/audit.js +0 -312
  45. package/dist/audit.js.map +0 -1
  46. package/dist/chunk-4B6U4CVQ.js +0 -15
  47. package/dist/chunk-4B6U4CVQ.js.map +0 -1
  48. package/dist/chunk-FCIPUALH.js +0 -214
  49. package/dist/chunk-FCIPUALH.js.map +0 -1
  50. package/dist/chunk-O2UPHN7X.js +0 -114
  51. package/dist/chunk-O2UPHN7X.js.map +0 -1
  52. package/dist/chunk-P5OKDSLB.js +0 -580
  53. package/dist/chunk-P5OKDSLB.js.map +0 -1
  54. package/dist/chunk-QNUEFNU7.js.map +0 -1
  55. package/dist/chunk-VKUHUFX7.js.map +0 -1
  56. package/dist/chunk-VLF5RHEQ.js +0 -143
  57. package/dist/chunk-VLF5RHEQ.js.map +0 -1
  58. package/dist/coder-2leJPOvC.d.ts +0 -52
  59. package/dist/improvement.d.ts +0 -208
  60. package/dist/improvement.js +0 -343
  61. package/dist/improvement.js.map +0 -1
  62. package/dist/local-harness-BE_h8szs.d.ts +0 -93
  63. package/dist/platform.d.ts +0 -255
  64. package/dist/platform.js +0 -229
  65. package/dist/platform.js.map +0 -1
  66. package/dist/run-loop-D3PwlG7J.d.ts +0 -112
  67. package/dist/runtime-hooks-C7JwKb9E.d.ts +0 -70
  68. package/dist/runtime.d.ts +0 -3108
  69. package/dist/runtime.js +0 -263
  70. package/dist/runtime.js.map +0 -1
  71. package/dist/topology.d.ts +0 -126
  72. package/dist/topology.js +0 -333
  73. package/dist/topology.js.map +0 -1
  74. package/dist/workflow.d.ts +0 -551
  75. package/dist/workflow.js +0 -1781
  76. package/dist/workflow.js.map +0 -1
  77. /package/dist/{chunk-OYU5LR4T.js.map → chunk-EDCVUZZC.js.map} +0 -0
  78. /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 spawn4(agent, task, opts) {
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: zeroSpend2(),
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, zeroSpend2());
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: spawn4,
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 zeroSpend2() {
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 (isNoEntError2(err)) return /* @__PURE__ */ new Map();
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 isNoEntError2(err) {
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 spawn3 } from "child_process";
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 maxTurns = opts?.maxTurns ?? 4;
3397
- const messages = opts?.initialMessages ? [...opts.initialMessages] : [
3398
- { role: "system", content: system },
3399
- { role: "user", content: user }
3400
- ];
3401
- let toolCalls = 0;
3402
- let lastText = "";
3403
- const usage = { input: 0, output: 0 };
3404
- const toolTrace = [];
3405
- for (let turn = 1; turn <= maxTurns; turn += 1) {
3406
- const r = await routerChatWithTools(cfg, messages, tools, {
3407
- ...opts?.temperature !== void 0 ? { temperature: opts.temperature } : {},
3408
- ...opts?.maxTokens ? { maxTokens: opts.maxTokens } : {},
3409
- ...opts?.signal ? { signal: opts.signal } : {}
3410
- });
3411
- if (r.usage) {
3412
- usage.input += r.usage.input;
3413
- usage.output += r.usage.output;
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 spawn2 } from "child_process";
3362
+ import { spawn as spawn3 } from "child_process";
3498
3363
 
3499
- // src/mcp/worktree.ts
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 = spawn("git", args, { cwd, stdio: "pipe" });
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 = spawn2("/bin/sh", ["-c", opts.command], {
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 zeroSpend3() {
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?.({ toolName, args, status });
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 = spawn3(args.seam.bin, args.seam.args ?? [], {
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: zeroSpend3() });
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
- async execute(task, signal) {
4229
- const messages = taskToMessages(task, spec);
4230
- const started = Date.now();
4231
- const linked = linkSignals2(signal, controller.signal);
4232
- const timer = seam.timeoutMs ? setTimeout(() => controller.abort(), seam.timeoutMs) : void 0;
4233
- try {
4234
- const res = await fetch(`${seam.bridgeUrl.replace(/\/$/, "")}/v1/chat/completions`, {
4235
- method: "POST",
4236
- headers: {
4237
- "content-type": "application/json",
4238
- authorization: `Bearer ${seam.bridgeBearer}`
4239
- },
4240
- body: JSON.stringify({
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
- const data = await res.json();
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 execute()");
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: zeroSpend4(),
5056
+ ownSpend: zeroSpend3(),
4966
5057
  children: []
4967
5058
  });
4968
5059
  }
4969
5060
  for (const ev of closes) {
4970
- const node = requireNode2(nodes, ev.id, root);
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 = requireNode2(nodes, ev.id, root);
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
- requireNode2(nodes, ev.parent, root).children.push(ev.id);
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 = requireNode2(nodes, frame.id, root);
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 zeroSpend4() {
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 requireNode2(nodes, id, root) {
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 depthDriver(surface, task, opts, cfg) {
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 breadthDriver(_surface, task, opts, cfg) {
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) => breadthDriver(surface, task, opts, { width: 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) => depthDriver(surface, task, opts, { maxShots: 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 supervisorSkill(opts) {
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 spawn_worker with a COMPLETE `profile`:",
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 idArg = { type: "string", description: "The workerId returned by spawn_worker." };
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: "spawn_worker",
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: opts.perWorker,
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: "observe_worker",
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: "steer_worker",
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 coordinationDriverAgent(opts) {
7365
- if (typeof opts.chat?.next !== "function") {
7366
- throw new ValidationError("coordinationDriverAgent: opts.chat.next must be a function");
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
- "coordinationDriverAgent: maxTurns must be >= 0 (0 lifts the turn cap; bounds become the conserved pool + deadline + abort)"
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 = coord.tools.map((t) => ({
7386
- name: t.name,
7387
- description: t.description,
7388
- parameters: t.inputSchema
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
- const messages = [{ role: "user", content: stringifyTask(task) }];
7392
- for (let turn = 0; turn < maxTurns; turn += 1) {
7393
- if (coord.isStopped() || scope.signal.aborted) break;
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: calls.map((c) => c.name)
7650
+ toolCalls: (res.toolCalls ?? []).map((c) => c.name)
7413
7651
  });
7414
7652
  }
7415
- if (calls.length === 0) {
7416
- return finalize2(coord, opts.blobs);
7417
- }
7418
- messages.push({ role: "assistant", content: res.content ?? "", toolCalls: calls });
7419
- for (const tc of calls) {
7420
- const tool = byName.get(tc.name);
7421
- const result = tool ? await runTool(tool, tc.arguments) : { error: `unknown tool: ${tc.name}` };
7422
- messages.push({
7423
- role: "tool",
7424
- ...tc.id ? { toolCallId: tc.id } : {},
7425
- name: tc.name,
7426
- content: safeJson(result)
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 finalize2(coord, blobs) {
7442
- const delivered = coord.settled().filter((w) => w.status === "done" && w.valid === true);
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 AgentEvalError {
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 AgentEvalError {
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 createDriveTurnResumeDriver(options) {
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/router-driver-chat.ts
9788
- function routerDriverChat(c, opts = {}) {
9789
- const temperature = opts.temperature ?? 0.4;
10051
+ // src/runtime/supervise/run-context.ts
10052
+ function createInMemoryRunContext(opts = {}) {
10053
+ const base = createExecutorRegistry();
9790
10054
  return {
9791
- next: async ({ system, messages, tools }) => {
9792
- const oa = [
9793
- { role: "system", content: system },
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
- function toOpenAI(m) {
9817
- if (m.role === "assistant" && m.toolCalls?.length) {
9818
- return {
9819
- role: "assistant",
9820
- content: m.content ?? "",
9821
- tool_calls: m.toolCalls.map((tc) => ({
9822
- id: tc.id ?? tc.name,
9823
- type: "function",
9824
- function: { name: tc.name, arguments: JSON.stringify(tc.arguments) }
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
- if (m.role === "tool") {
9829
- return { role: "tool", tool_call_id: m.toolCallId ?? m.name ?? "call", content: m.content };
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 { role: m.role, content: m.content };
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 safeParse(s) {
9834
- try {
9835
- return JSON.parse(s);
9836
- } catch {
9837
- return {};
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/run-context.ts
9842
- function createInMemoryRunContext(opts = {}) {
9843
- const base = createExecutorRegistry();
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
- journal: new InMemorySpawnJournal(),
9846
- blobs: new InMemoryResultBlobStore(),
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: at,
9862
- endedAt: at,
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" ? safeParse2(rawArgs) : rawArgs ?? {},
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 safeParse2(s) {
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
- depthDriver,
10454
- breadthDriver,
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
- supervisorSkill,
10799
+ supervisorInstructions,
10474
10800
  authoredWorker,
10801
+ defaultProfileRichnessThresholds,
10802
+ assessAuthoredProfile,
10803
+ profileRichnessFinding,
10475
10804
  createEventBus,
10476
10805
  createCoordinationTools,
10477
- coordinationDriverAgent,
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
- createDriveTurnResumeDriver,
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
- toToolSpan,
10541
- decodeOpencodePart,
10542
- decodeAnthropicPart,
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-VKUHUFX7.js.map
10882
+ //# sourceMappingURL=chunk-QXWGSDAQ.js.map