@tangle-network/agent-runtime 0.69.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-G6U3GVK2.js → chunk-EDCVUZZC.js} +2 -2
  8. package/dist/{chunk-RTDI2DHD.js → chunk-L5ZFBVT6.js} +6 -6
  9. package/dist/chunk-L5ZFBVT6.js.map +1 -0
  10. package/dist/{chunk-NLRA6434.js → chunk-QXWGSDAQ.js} +716 -535
  11. package/dist/chunk-QXWGSDAQ.js.map +1 -0
  12. package/dist/{chunk-QZ6FA5LM.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-K4FQSEXQ.js +0 -214
  49. package/dist/chunk-K4FQSEXQ.js.map +0 -1
  50. package/dist/chunk-NLRA6434.js.map +0 -1
  51. package/dist/chunk-O2UPHN7X.js +0 -114
  52. package/dist/chunk-O2UPHN7X.js.map +0 -1
  53. package/dist/chunk-P5OKDSLB.js +0 -580
  54. package/dist/chunk-P5OKDSLB.js.map +0 -1
  55. package/dist/chunk-RTDI2DHD.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 -3120
  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-G6U3GVK2.js.map → chunk-EDCVUZZC.js.map} +0 -0
  78. /package/dist/{chunk-QZ6FA5LM.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,12 +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";
3315
3158
  import { randomUUID as randomUUID2 } from "crypto";
3316
3159
  import { estimateCost as estimateCost2, isModelPriced as isModelPriced2 } from "@tangle-network/agent-eval";
3317
3160
 
3318
3161
  // src/runtime/router-client.ts
3319
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
3320
3215
  async function routerChatWithUsage(cfg, messages, opts) {
3321
3216
  const url = `${cfg.routerBaseUrl.replace(/\/$/, "")}/chat/completions`;
3322
3217
  const headers = { "content-type": "application/json", authorization: `Bearer ${cfg.routerKey}` };
@@ -3394,56 +3289,25 @@ async function routerChatWithTools(cfg, messages, tools, opts) {
3394
3289
  };
3395
3290
  }
3396
3291
  async function routerToolLoop(cfg, system, user, tools, execute, opts) {
3397
- const maxTurns = opts?.maxTurns ?? 4;
3398
- const messages = opts?.initialMessages ? [...opts.initialMessages] : [
3292
+ const initialMessages = opts?.initialMessages ?? [
3399
3293
  { role: "system", content: system },
3400
3294
  { role: "user", content: user }
3401
3295
  ];
3402
- let toolCalls = 0;
3403
- let lastText = "";
3404
- const usage = { input: 0, output: 0 };
3405
- const toolTrace = [];
3406
- for (let turn = 1; turn <= maxTurns; turn += 1) {
3407
- const r = await routerChatWithTools(cfg, messages, tools, {
3296
+ return runBrainLoop({
3297
+ chat: (messages, toolSpecs) => routerChatWithTools(cfg, messages, toolSpecs, {
3408
3298
  ...opts?.temperature !== void 0 ? { temperature: opts.temperature } : {},
3409
3299
  ...opts?.maxTokens ? { maxTokens: opts.maxTokens } : {},
3410
3300
  ...opts?.signal ? { signal: opts.signal } : {}
3411
- });
3412
- if (r.usage) {
3413
- usage.input += r.usage.input;
3414
- usage.output += r.usage.output;
3415
- }
3416
- if (r.content) lastText = r.content;
3417
- if (r.toolCalls.length === 0)
3418
- return { final: lastText, turns: turn, toolCalls, toolTrace, usage, messages };
3419
- messages.push({
3420
- role: "assistant",
3421
- content: r.content ?? "",
3422
- tool_calls: r.toolCalls.map((tc) => ({
3423
- id: tc.id,
3424
- type: "function",
3425
- function: { name: tc.name, arguments: tc.arguments }
3426
- }))
3427
- });
3428
- for (const tc of r.toolCalls) {
3429
- toolCalls += 1;
3430
- let args = {};
3431
- try {
3432
- args = JSON.parse(tc.arguments);
3433
- } catch {
3434
- messages.push({
3435
- role: "tool",
3436
- tool_call_id: tc.id,
3437
- content: `error: arguments were not valid JSON: ${tc.arguments.slice(0, 200)}`
3438
- });
3439
- continue;
3440
- }
3441
- const out = await execute(tc.name, args);
3442
- messages.push({ role: "tool", tool_call_id: tc.id, content: out });
3443
- toolTrace.push({ name: tc.name, args: tc.arguments, result: out });
3444
- }
3445
- }
3446
- return { final: lastText, turns: maxTurns, toolCalls, toolTrace, usage, messages };
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" });
3447
3311
  }
3448
3312
 
3449
3313
  // src/runtime/supervise/inbox.ts
@@ -3495,14 +3359,123 @@ ${lines.join("\n")}`;
3495
3359
  import { randomUUID } from "crypto";
3496
3360
 
3497
3361
  // src/mcp/worktree-harness.ts
3498
- import { spawn as spawn2 } from "child_process";
3362
+ import { spawn as spawn3 } from "child_process";
3499
3363
 
3500
- // src/mcp/worktree.ts
3364
+ // src/mcp/local-harness.ts
3501
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";
3502
3475
  async function runGitAsync(args, cwd, runner) {
3503
3476
  if (runner) return runner(args, { cwd });
3504
3477
  return new Promise((resolve, reject) => {
3505
- const proc = spawn("git", args, { cwd, stdio: "pipe" });
3478
+ const proc = spawn2("git", args, { cwd, stdio: "pipe" });
3506
3479
  let stdout = "";
3507
3480
  let stderr = "";
3508
3481
  proc.stdout?.on("data", (c) => {
@@ -3668,7 +3641,7 @@ async function runChecks(opts) {
3668
3641
  }
3669
3642
  function defaultRunCommand(opts) {
3670
3643
  return new Promise((resolve, reject) => {
3671
- const child = spawn2("/bin/sh", ["-c", opts.command], {
3644
+ const child = spawn3("/bin/sh", ["-c", opts.command], {
3672
3645
  cwd: opts.cwd,
3673
3646
  stdio: ["ignore", "pipe", "pipe"]
3674
3647
  });
@@ -3791,7 +3764,7 @@ function contentRef(prefix, value) {
3791
3764
  }
3792
3765
  return `${prefix}:${(h >>> 0).toString(16).padStart(8, "0")}`;
3793
3766
  }
3794
- function zeroSpend3() {
3767
+ function zeroSpend2() {
3795
3768
  return { iterations: 0, tokens: zeroTokenUsage(), usd: 0, ms: 0 };
3796
3769
  }
3797
3770
  var routerInlineExecutor = (spec, ctx) => {
@@ -3963,15 +3936,24 @@ var routerToolsInlineExecutor = (spec, ctx) => {
3963
3936
  const toolName = tc?.function?.name ?? "";
3964
3937
  let result;
3965
3938
  let status = "ok";
3939
+ const toolStartedAt = Date.now();
3966
3940
  try {
3967
3941
  result = await seam.executeToolCall(toolName, args, task);
3968
3942
  } catch (e) {
3969
3943
  status = "error";
3970
3944
  result = `error: ${e instanceof Error ? e.message : String(e)}`;
3971
3945
  }
3946
+ const toolEndedAt = Date.now();
3972
3947
  messages.push({ role: "tool", tool_call_id: id, content: result });
3973
3948
  try {
3974
- 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
+ });
3975
3957
  } catch {
3976
3958
  }
3977
3959
  }
@@ -4151,7 +4133,7 @@ var cliExecutor = (_spec, ctx) => {
4151
4133
  };
4152
4134
  async function* streamCliLeaf(args) {
4153
4135
  const prompt = taskToPrompt(args.task);
4154
- const proc = spawn3(args.seam.bin, args.seam.args ?? [], {
4136
+ const proc = spawn4(args.seam.bin, args.seam.args ?? [], {
4155
4137
  ...args.seam.cwd ? { cwd: args.seam.cwd } : {},
4156
4138
  env: { ...process.env, ...args.seam.env ?? {} },
4157
4139
  stdio: ["pipe", "pipe", "pipe"]
@@ -4188,7 +4170,7 @@ async function* streamCliLeaf(args) {
4188
4170
  );
4189
4171
  }
4190
4172
  const out = { content: chunks.join("") };
4191
- args.onArtifact({ outRef: contentRef("cli", out), out, spent: zeroSpend3() });
4173
+ args.onArtifact({ outRef: contentRef("cli", out), out, spent: zeroSpend2() });
4192
4174
  yield { kind: "iteration" };
4193
4175
  }
4194
4176
  function killWithGrace(proc, grace) {
@@ -4803,40 +4785,6 @@ function createSupervisor() {
4803
4785
  return { run, attach };
4804
4786
  }
4805
4787
  var rootControls = /* @__PURE__ */ new WeakMap();
4806
- function createRootHandle() {
4807
- let binding;
4808
- const handle = {
4809
- view() {
4810
- if (!binding) {
4811
- throw new RuntimeRunStateError(
4812
- "RootHandle.view: handle is not bound to a live run (attach it before run, read after run starts)"
4813
- );
4814
- }
4815
- return binding.scope.view;
4816
- },
4817
- signal(msg) {
4818
- if (!binding) {
4819
- throw new RuntimeRunStateError("RootHandle.signal: handle is not bound to a live run");
4820
- }
4821
- binding.signal(msg);
4822
- },
4823
- abort(reason) {
4824
- if (!binding) {
4825
- throw new RuntimeRunStateError("RootHandle.abort: handle is not bound to a live run");
4826
- }
4827
- binding.cascadeAbort(reason ?? "root handle aborted");
4828
- }
4829
- };
4830
- rootControls.set(handle, {
4831
- bind(b) {
4832
- binding = b;
4833
- },
4834
- unbind() {
4835
- binding = void 0;
4836
- }
4837
- });
4838
- return handle;
4839
- }
4840
4788
  function pushRootSignal(cascadeAbort) {
4841
4789
  return (msg) => {
4842
4790
  if (msg.kind === "cancel") cascadeAbort(msg.reason ?? "root signal: cancel");
@@ -5105,12 +5053,12 @@ async function trajectoryReport(journal, blobs, root, options = {}) {
5105
5053
  label: ev.label,
5106
5054
  runtime: ev.runtime,
5107
5055
  status: "pending",
5108
- ownSpend: zeroSpend4(),
5056
+ ownSpend: zeroSpend3(),
5109
5057
  children: []
5110
5058
  });
5111
5059
  }
5112
5060
  for (const ev of closes) {
5113
- const node = requireNode2(nodes, ev.id, root);
5061
+ const node = requireNode(nodes, ev.id, root);
5114
5062
  if (ev.kind === "cancelled") {
5115
5063
  node.status = "cancelled";
5116
5064
  continue;
@@ -5122,7 +5070,7 @@ async function trajectoryReport(journal, blobs, root, options = {}) {
5122
5070
  }
5123
5071
  for (const ev of events) {
5124
5072
  if (ev.kind !== "metered") continue;
5125
- const node = requireNode2(nodes, ev.id, root);
5073
+ const node = requireNode(nodes, ev.id, root);
5126
5074
  node.ownSpend = addNodeSpend(node.ownSpend, ev.spend);
5127
5075
  }
5128
5076
  if (!nodes.has(root)) {
@@ -5132,7 +5080,7 @@ async function trajectoryReport(journal, blobs, root, options = {}) {
5132
5080
  }
5133
5081
  for (const ev of spawns) {
5134
5082
  if (ev.parent === void 0) continue;
5135
- requireNode2(nodes, ev.parent, root).children.push(ev.id);
5083
+ requireNode(nodes, ev.parent, root).children.push(ev.id);
5136
5084
  }
5137
5085
  const rolledUp = rollUpSpend(nodes, root);
5138
5086
  if (options.withOutputs) {
@@ -5180,7 +5128,7 @@ function rollUpSpend(nodes, root) {
5180
5128
  while (stack.length > 0) {
5181
5129
  const frame = stack.pop();
5182
5130
  if (frame === void 0) continue;
5183
- const node = requireNode2(nodes, frame.id, root);
5131
+ const node = requireNode(nodes, frame.id, root);
5184
5132
  if (!frame.expanded) {
5185
5133
  stack.push({ id: frame.id, expanded: true });
5186
5134
  for (const child of node.children) stack.push({ id: child, expanded: false });
@@ -5229,7 +5177,7 @@ function countStatuses(reported) {
5229
5177
  for (const node of reported) counts[node.status] += 1;
5230
5178
  return counts;
5231
5179
  }
5232
- function zeroSpend4() {
5180
+ function zeroSpend3() {
5233
5181
  return { iterations: 0, tokens: zeroTokenUsage(), usd: 0, ms: 0 };
5234
5182
  }
5235
5183
  function addNodeSpend(a, b) {
@@ -5289,7 +5237,7 @@ function isNode(node) {
5289
5237
  function bySeq(a, b) {
5290
5238
  return a.seq - b.seq;
5291
5239
  }
5292
- function requireNode2(nodes, id, root) {
5240
+ function requireNode(nodes, id, root) {
5293
5241
  const node = nodes.get(id);
5294
5242
  if (!node) {
5295
5243
  throw new Error(
@@ -5694,7 +5642,7 @@ var perChild = (innerTurns) => ({
5694
5642
  maxIterations: innerTurns + 1,
5695
5643
  maxTokens: 1e6
5696
5644
  });
5697
- function depthDriver(surface, task, opts, cfg) {
5645
+ function depthStrategy(surface, task, opts, cfg) {
5698
5646
  const innerTurns = opts.innerTurns ?? 4;
5699
5647
  let pendingSteer;
5700
5648
  return {
@@ -5757,7 +5705,7 @@ Address each with the tools, verify they took, then continue.`;
5757
5705
  }
5758
5706
  };
5759
5707
  }
5760
- function breadthDriver(_surface, task, opts, cfg) {
5708
+ function breadthStrategy(_surface, task, opts, cfg) {
5761
5709
  const innerTurns = opts.innerTurns ?? 4;
5762
5710
  return {
5763
5711
  name: "breadth",
@@ -5800,11 +5748,11 @@ function breadthDriver(_surface, task, opts, cfg) {
5800
5748
  }
5801
5749
  var sample = {
5802
5750
  name: "sample",
5803
- driver: (surface, task, opts, budget) => breadthDriver(surface, task, opts, { width: budget })
5751
+ driver: (surface, task, opts, budget) => breadthStrategy(surface, task, opts, { width: budget })
5804
5752
  };
5805
5753
  var refine = {
5806
5754
  name: "refine",
5807
- driver: (surface, task, opts, budget) => depthDriver(surface, task, opts, { maxShots: budget })
5755
+ driver: (surface, task, opts, budget) => depthStrategy(surface, task, opts, { maxShots: budget })
5808
5756
  };
5809
5757
  function defineStrategy(name, run) {
5810
5758
  return {
@@ -6935,6 +6883,9 @@ ${summary}`,
6935
6883
  };
6936
6884
  }
6937
6885
 
6886
+ // src/runtime/supervise/authoring.ts
6887
+ import { computeFindingId, makeFinding as makeFinding2 } from "@tangle-network/agent-eval";
6888
+
6938
6889
  // src/runtime/supervise/completion-gate.ts
6939
6890
  function gateOnDeliverable(inner, deliverable) {
6940
6891
  let gated;
@@ -6987,13 +6938,13 @@ function asAuthoredProfile(raw) {
6987
6938
  ...typeof p.model === "string" ? { model: p.model } : {}
6988
6939
  };
6989
6940
  }
6990
- function supervisorSkill(opts) {
6941
+ function supervisorInstructions(opts) {
6991
6942
  return [
6992
6943
  "You are a SUPERVISOR. You do NOT do the work yourself \u2014 your job is to DESIGN and DRIVE specialist worker agents.",
6993
6944
  "",
6994
6945
  "For the task you are given:",
6995
6946
  "1. DECOMPOSE it into the smallest set of sub-tasks a single focused worker can each deliver.",
6996
- "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`:",
6997
6948
  " \u2022 name: a short id for the worker.",
6998
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.',
6999
6950
  " \u2022 model: the model best suited to this sub-task (omit to use the default).",
@@ -7044,6 +6995,93 @@ function authoredWorker(profile, opts) {
7044
6995
  };
7045
6996
  return { name: profile.name, act: async () => "", executorSpec: spec };
7046
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
+ }
7047
7085
 
7048
7086
  // src/runtime/supervise/event-bus.ts
7049
7087
  function createEventBus(now = Date.now) {
@@ -7102,7 +7140,19 @@ function createEventBus(now = Date.now) {
7102
7140
  }
7103
7141
 
7104
7142
  // src/mcp/tools/coordination.ts
7105
- 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." };
7106
7156
  function createCoordinationTools(opts) {
7107
7157
  let stopped = false;
7108
7158
  let reason;
@@ -7126,6 +7176,28 @@ function createCoordinationTools(opts) {
7126
7176
  throw new Error("coordination tools: arguments must be an object");
7127
7177
  return raw;
7128
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
+ };
7129
7201
  const level = (v) => {
7130
7202
  if (v === "worker" || v === "driver" || v === "loop") return v;
7131
7203
  throw new Error('coordination tools: "level" must be worker, driver, or loop');
@@ -7244,29 +7316,40 @@ function createCoordinationTools(opts) {
7244
7316
  };
7245
7317
  const tools = [
7246
7318
  {
7247
- name: "spawn_worker",
7248
- 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.",
7249
7321
  inputSchema: {
7250
7322
  type: "object",
7251
7323
  properties: {
7252
7324
  profile: { description: "The worker/driver profile to run." },
7253
7325
  task: { description: "The task the worker should perform." },
7254
- 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
+ }
7255
7337
  },
7256
7338
  required: ["profile", "task"]
7257
7339
  },
7258
7340
  handler: (raw) => {
7259
7341
  const a = obj2(raw);
7260
7342
  const agent = opts.makeWorkerAgent(a.profile);
7343
+ const budget = a.budget === void 0 ? opts.perWorker : mergeBudget(opts.perWorker, a.budget);
7261
7344
  const res = opts.scope.spawn(agent, a.task, {
7262
- budget: opts.perWorker,
7345
+ budget,
7263
7346
  label: typeof a.label === "string" ? a.label : "worker"
7264
7347
  });
7265
7348
  return Promise.resolve(res.ok ? { workerId: res.handle.id } : { error: res.reason });
7266
7349
  }
7267
7350
  },
7268
7351
  {
7269
- name: "observe_worker",
7352
+ name: "observe_agent",
7270
7353
  description: "Inspect a worker status, spend, and settled output artifact when available.",
7271
7354
  inputSchema: { type: "object", properties: { workerId: idArg }, required: ["workerId"] },
7272
7355
  handler: async (raw) => {
@@ -7283,7 +7366,7 @@ function createCoordinationTools(opts) {
7283
7366
  }
7284
7367
  },
7285
7368
  {
7286
- name: "steer_worker",
7369
+ name: "steer_agent",
7287
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.",
7288
7371
  inputSchema: {
7289
7372
  type: "object",
@@ -7504,13 +7587,26 @@ function deadlinePassed(scope, now) {
7504
7587
  const b = scope.budget;
7505
7588
  return b.deadlineMs > 0 && now() >= b.deadlineMs;
7506
7589
  }
7507
- function coordinationDriverAgent(opts) {
7508
- if (typeof opts.chat?.next !== "function") {
7509
- 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
+ }
7510
7606
  }
7511
7607
  if (opts.maxTurns !== void 0 && opts.maxTurns < 0) {
7512
7608
  throw new ValidationError(
7513
- "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)"
7514
7610
  );
7515
7611
  }
7516
7612
  const maxTurns = opts.maxTurns === 0 ? runawayTripwireTurns : opts.maxTurns ?? 16;
@@ -7525,24 +7621,23 @@ function coordinationDriverAgent(opts) {
7525
7621
  perWorker: opts.perWorker
7526
7622
  });
7527
7623
  const byName = new Map(coord.tools.map((t) => [t.name, t]));
7528
- const toolSpecs = coord.tools.map((t) => ({
7529
- name: t.name,
7530
- description: t.description,
7531
- parameters: t.inputSchema
7532
- }));
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
+ ];
7533
7635
  const system = typeof opts.systemPrompt === "function" ? opts.systemPrompt(task) : opts.systemPrompt;
7534
- const messages = [{ role: "user", content: stringifyTask(task) }];
7535
- for (let turn = 0; turn < maxTurns; turn += 1) {
7536
- if (coord.isStopped() || scope.signal.aborted) break;
7537
- if (poolStarved(scope, opts.perWorker) || deadlinePassed(scope, now)) break;
7538
- const res = await opts.chat.next({ system, messages, tools: toolSpecs });
7539
- const calls = res.toolCalls ?? [];
7636
+ let turn = 0;
7637
+ const chat = async (messages, tools) => {
7638
+ const res = await opts.brain(messages, tools);
7540
7639
  if (res.usage || res.costUsd !== void 0) {
7541
7640
  const turnSpend = {
7542
- // iterations:0 — the conserved iteration channel (`maxIterations`) budgets CHILD rounds,
7543
- // not driver turns; counting turns there would conflate the two AND make a driver arm's
7544
- // iteration count diverge from a blind arm's. The driver is bounded by maxTurns + the
7545
- // token/usd pool; its turn COUNT stays observable via the per-turn `agent.turn` events.
7546
7641
  iterations: 0,
7547
7642
  tokens: { input: res.usage?.input ?? 0, output: res.usage?.output ?? 0 },
7548
7643
  usd: res.costUsd ?? 0,
@@ -7552,28 +7647,47 @@ function coordinationDriverAgent(opts) {
7552
7647
  kind: "driver-inference",
7553
7648
  driver: opts.name,
7554
7649
  turn,
7555
- toolCalls: calls.map((c) => c.name)
7650
+ toolCalls: (res.toolCalls ?? []).map((c) => c.name)
7556
7651
  });
7557
7652
  }
7558
- if (calls.length === 0) {
7559
- return finalize2(coord, opts.blobs);
7560
- }
7561
- messages.push({ role: "assistant", content: res.content ?? "", toolCalls: calls });
7562
- for (const tc of calls) {
7563
- const tool = byName.get(tc.name);
7564
- const result = tool ? await runTool(tool, tc.arguments) : { error: `unknown tool: ${tc.name}` };
7565
- messages.push({
7566
- role: "tool",
7567
- ...tc.id ? { toolCallId: tc.id } : {},
7568
- name: tc.name,
7569
- content: safeJson(result)
7570
- });
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)
7571
7678
  }
7572
- }
7679
+ });
7573
7680
  return finalize2(coord, opts.blobs);
7574
7681
  }
7575
7682
  };
7576
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
+ }
7577
7691
  async function runTool(tool, args) {
7578
7692
  try {
7579
7693
  return await tool.handler(args);
@@ -7581,13 +7695,16 @@ async function runTool(tool, args) {
7581
7695
  return { error: e instanceof Error ? e.message : String(e) };
7582
7696
  }
7583
7697
  }
7584
- async function finalize2(coord, blobs) {
7585
- 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);
7586
7700
  if (delivered.length === 0) return void 0;
7587
7701
  let best = delivered[0];
7588
7702
  for (const w of delivered) if ((w.score ?? 0) > (best.score ?? 0)) best = w;
7589
7703
  return best.outRef ? await blobs.get(best.outRef) : void 0;
7590
7704
  }
7705
+ async function finalize2(coord, blobs) {
7706
+ return finalizeBestDelivered(coord.settled(), blobs);
7707
+ }
7591
7708
  function stringifyTask(task) {
7592
7709
  return typeof task === "string" ? task : safeJson(task);
7593
7710
  }
@@ -7638,12 +7755,12 @@ function eventToSnapshot(event) {
7638
7755
  // src/mcp/delegation-store.ts
7639
7756
  import { mkdir, readFile, rename, writeFile } from "fs/promises";
7640
7757
  import { dirname } from "path";
7641
- var DelegationStateCorruptError = class extends AgentEvalError {
7758
+ var DelegationStateCorruptError = class extends AgentEvalError2 {
7642
7759
  constructor(message, options) {
7643
7760
  super("validation", message, options);
7644
7761
  }
7645
7762
  };
7646
- var DelegationPersistenceError = class extends AgentEvalError {
7763
+ var DelegationPersistenceError = class extends AgentEvalError2 {
7647
7764
  constructor(message, options) {
7648
7765
  super("config", message, options);
7649
7766
  }
@@ -8549,7 +8666,7 @@ function createDetachedTurnTrace(options) {
8549
8666
  function detachedRunningPhase(elapsedMs) {
8550
8667
  return elapsedMs === void 0 ? "detached-running" : `detached-running ${Math.round(elapsedMs / 1e3)}s`;
8551
8668
  }
8552
- function createDriveTurnResumeDriver(options) {
8669
+ function createDetachedTurnResumeDriver(options) {
8553
8670
  const cancelHooked = /* @__PURE__ */ new Set();
8554
8671
  return {
8555
8672
  intervalMs: options.intervalMs ?? DEFAULT_TICK_INTERVAL_MS,
@@ -9811,6 +9928,16 @@ function watchTrace(source, opts = {}) {
9811
9928
  });
9812
9929
  }
9813
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
+
9814
9941
  // src/runtime/supervise/patch-checks.ts
9815
9942
  var DEFAULT_MAX_DIFF_LINES = 400;
9816
9943
  var secretPathPattern = /(^|\/)(\.env(\.|$)|.*\.(pem|key|p12|pfx|keystore|wallet)|id_rsa|id_ed25519|secrets?\.json|credentials?\.json)$/i;
@@ -9835,12 +9962,6 @@ function countDiffLines(patch) {
9835
9962
  }
9836
9963
  return count;
9837
9964
  }
9838
- function isNonEmptyPatch(patch) {
9839
- return touchedPathsFromPatch(patch).length > 0 && patch.trim().length > 0;
9840
- }
9841
- function touchesSecretPath(patch) {
9842
- return touchedPathsFromPatch(patch).filter((p) => secretPathPattern.test(p));
9843
- }
9844
9965
  function runCoderChecks(input, constraints = {}) {
9845
9966
  const maxDiff = constraints.maxDiffLines ?? DEFAULT_MAX_DIFF_LINES;
9846
9967
  const forbidden = constraints.forbiddenPaths ?? [];
@@ -9927,72 +10048,132 @@ function signalPass(value, required) {
9927
10048
  return !required;
9928
10049
  }
9929
10050
 
9930
- // src/runtime/supervise/router-driver-chat.ts
9931
- function routerDriverChat(c, opts = {}) {
9932
- const temperature = opts.temperature ?? 0.4;
10051
+ // src/runtime/supervise/run-context.ts
10052
+ function createInMemoryRunContext(opts = {}) {
10053
+ const base = createExecutorRegistry();
9933
10054
  return {
9934
- next: async ({ system, messages, tools }) => {
9935
- const oa = [
9936
- { role: "system", content: system },
9937
- ...messages.map(toOpenAI)
9938
- ];
9939
- const oaTools = tools.map((t) => ({
9940
- type: "function",
9941
- function: { name: t.name, description: t.description, parameters: t.parameters }
9942
- }));
9943
- const r = await routerChatWithTools(c, oa, oaTools, { temperature, toolChoice: "auto" });
9944
- return {
9945
- ...r.content ? { content: r.content } : {},
9946
- // Forward the router's REAL usage + cost so the driver meters its own inference against the
9947
- // conserved pool (the integrity hole: these were dropped on the floor before).
9948
- ...r.usage ? { usage: r.usage } : {},
9949
- ...typeof r.costUsd === "number" ? { costUsd: r.costUsd } : {},
9950
- toolCalls: r.toolCalls.map((tc) => ({
9951
- id: tc.id,
9952
- name: tc.name,
9953
- arguments: safeParse(tc.arguments)
9954
- }))
9955
- };
9956
- }
10055
+ journal: new InMemorySpawnJournal(),
10056
+ blobs: new InMemoryResultBlobStore(),
10057
+ executors: opts.withDriver ? withDriverExecutor(base) : base
9957
10058
  };
9958
10059
  }
9959
- function toOpenAI(m) {
9960
- if (m.role === "assistant" && m.toolCalls?.length) {
9961
- return {
9962
- role: "assistant",
9963
- content: m.content ?? "",
9964
- tool_calls: m.toolCalls.map((tc) => ({
9965
- id: tc.id ?? tc.name,
9966
- type: "function",
9967
- function: { name: tc.name, arguments: JSON.stringify(tc.arguments) }
9968
- }))
9969
- };
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
+ });
9970
10079
  }
9971
- if (m.role === "tool") {
9972
- 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
+ );
9973
10085
  }
9974
- 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
+ };
9975
10103
  }
9976
- function safeParse(s) {
9977
- try {
9978
- return JSON.parse(s);
9979
- } catch {
9980
- 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
+ );
9981
10109
  }
10110
+ return routerBrain({ ...deps.router, model: profile.model ?? deps.router.model });
9982
10111
  }
9983
10112
 
9984
- // src/runtime/supervise/run-context.ts
9985
- function createInMemoryRunContext(opts = {}) {
9986
- 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) {
9987
10126
  return {
9988
- journal: new InMemorySpawnJournal(),
9989
- blobs: new InMemoryResultBlobStore(),
9990
- executors: opts.withDriver ? withDriverExecutor(base) : base
10127
+ maxIterations: budget.maxIterations,
10128
+ maxTokens: Math.max(1, Math.floor(budget.maxTokens / 4))
9991
10129
  };
9992
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
+ }
9993
10172
 
9994
10173
  // src/runtime/supervise/trace-source.ts
9995
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;
9996
10177
  return {
9997
10178
  spanId: `${runId}-t${seq}`,
9998
10179
  runId,
@@ -10001,8 +10182,8 @@ function toToolSpan(input, runId, seq, at) {
10001
10182
  toolName: input.toolName,
10002
10183
  args: input.args,
10003
10184
  status: input.status ?? "ok",
10004
- startedAt: at,
10005
- endedAt: at,
10185
+ startedAt,
10186
+ endedAt,
10006
10187
  ...input.result !== void 0 ? { result: input.result } : {}
10007
10188
  };
10008
10189
  }
@@ -10042,7 +10223,7 @@ var decodeOpenAiPart = (p) => {
10042
10223
  const rawArgs = fn?.arguments ?? p.arguments;
10043
10224
  return {
10044
10225
  toolName: name,
10045
- args: typeof rawArgs === "string" ? safeParse2(rawArgs) : rawArgs ?? {},
10226
+ args: typeof rawArgs === "string" ? safeParse(rawArgs) : rawArgs ?? {},
10046
10227
  ...str(p.id) ? { callId: p.id } : str(fn?.id) ? { callId: fn?.id } : {}
10047
10228
  };
10048
10229
  };
@@ -10066,7 +10247,7 @@ function decodeToolPart(part, harness) {
10066
10247
  }
10067
10248
  return void 0;
10068
10249
  }
10069
- function safeParse2(s) {
10250
+ function safeParse(s) {
10070
10251
  try {
10071
10252
  return JSON.parse(s);
10072
10253
  } catch {
@@ -10512,13 +10693,22 @@ function tail(s) {
10512
10693
  }
10513
10694
 
10514
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,
10515
10709
  contentAddress,
10516
10710
  InMemoryResultBlobStore,
10517
- FileResultBlobStore,
10518
10711
  InMemorySpawnJournal,
10519
- FileSpawnJournal,
10520
- replaySpawnTree,
10521
- materializeTreeView,
10522
10712
  anytimeReport,
10523
10713
  renderAnytimeTable,
10524
10714
  defaultAuditorInstruction,
@@ -10541,7 +10731,6 @@ export {
10541
10731
  probeSandboxCapabilities,
10542
10732
  createSandboxLineage,
10543
10733
  runLoop,
10544
- describeSandboxPlacement,
10545
10734
  createSandboxForSpec,
10546
10735
  defaultSelectWinner,
10547
10736
  loopDispatch,
@@ -10550,7 +10739,6 @@ export {
10550
10739
  createScopeAnalyst,
10551
10740
  registryScopeAnalyst,
10552
10741
  buildSteerContext,
10553
- nestedScopeSeamKey,
10554
10742
  createScope,
10555
10743
  settledToIteration,
10556
10744
  selectValidWinner,
@@ -10564,14 +10752,10 @@ export {
10564
10752
  InMemoryCorpus,
10565
10753
  FileCorpus,
10566
10754
  renderCorpusToInstructions,
10567
- driverRuntime,
10568
- driverChild,
10569
- isDriverSpec,
10570
- driverExecutorFactory,
10571
- withDriverExecutor,
10572
10755
  routerChatWithUsage,
10573
10756
  routerChatWithTools,
10574
10757
  routerToolLoop,
10758
+ routerBrain,
10575
10759
  createInbox,
10576
10760
  createWorktree,
10577
10761
  captureWorktreeDiff,
@@ -10584,7 +10768,6 @@ export {
10584
10768
  spendFromUsageEvents,
10585
10769
  createBudgetPool,
10586
10770
  createSupervisor,
10587
- createRootHandle,
10588
10771
  createShapeRegistry,
10589
10772
  builtinShapes,
10590
10773
  registerShape,
@@ -10593,8 +10776,8 @@ export {
10593
10776
  trajectoryReport,
10594
10777
  equalKOnCost,
10595
10778
  promotionGate,
10596
- depthDriver,
10597
- breadthDriver,
10779
+ depthStrategy,
10780
+ breadthStrategy,
10598
10781
  sample,
10599
10782
  refine,
10600
10783
  defineStrategy,
@@ -10613,11 +10796,15 @@ export {
10613
10796
  runStrategyEvolution,
10614
10797
  gateOnDeliverable,
10615
10798
  asAuthoredProfile,
10616
- supervisorSkill,
10799
+ supervisorInstructions,
10617
10800
  authoredWorker,
10801
+ defaultProfileRichnessThresholds,
10802
+ assessAuthoredProfile,
10803
+ profileRichnessFinding,
10618
10804
  createEventBus,
10619
10805
  createCoordinationTools,
10620
- coordinationDriverAgent,
10806
+ driverAgent,
10807
+ finalizeBestDelivered,
10621
10808
  InMemoryFeedbackStore,
10622
10809
  eventToSnapshot,
10623
10810
  DelegationStateCorruptError,
@@ -10636,7 +10823,7 @@ export {
10636
10823
  parseDetachedSessionRef,
10637
10824
  detachedTurnEvents,
10638
10825
  runDetachedTurn,
10639
- createDriveTurnResumeDriver,
10826
+ createDetachedTurnResumeDriver,
10640
10827
  DELEGATE_CODE_TOOL_NAME,
10641
10828
  DELEGATE_CODE_DESCRIPTION,
10642
10829
  DELEGATE_CODE_INPUT_SCHEMA,
@@ -10672,22 +10859,14 @@ export {
10672
10859
  serveCoordinationMcp,
10673
10860
  defaultToolDetectors,
10674
10861
  watchTrace,
10675
- touchedPathsFromPatch,
10676
- countDiffLines,
10677
- isNonEmptyPatch,
10678
- touchesSecretPath,
10679
10862
  runCoderChecks,
10680
10863
  patchDelivered,
10681
- routerDriverChat,
10682
10864
  createInMemoryRunContext,
10683
- toToolSpan,
10684
- decodeOpencodePart,
10685
- decodeAnthropicPart,
10686
- decodeOpenAiPart,
10687
- toolPartDecoders,
10865
+ supervisorAgent,
10866
+ workerFromBackend,
10867
+ supervise,
10688
10868
  decodeToolPart,
10689
10869
  createPushTraceSource,
10690
- createPartsTraceSource,
10691
10870
  sandboxSessionTraceSource,
10692
10871
  analyzeTrace,
10693
10872
  worktreeFanout,
@@ -10696,6 +10875,8 @@ export {
10696
10875
  localShell,
10697
10876
  gitWorkspace,
10698
10877
  jjWorkspace,
10699
- runInWorkspace
10878
+ runInWorkspace,
10879
+ computeFindingId2 as computeFindingId,
10880
+ makeFinding3 as makeFinding
10700
10881
  };
10701
- //# sourceMappingURL=chunk-NLRA6434.js.map
10882
+ //# sourceMappingURL=chunk-QXWGSDAQ.js.map