@tangle-network/agent-runtime 0.72.0 → 0.73.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 (46) hide show
  1. package/dist/agent.d.ts +1 -1
  2. package/dist/agent.js +4 -3
  3. package/dist/agent.js.map +1 -1
  4. package/dist/analyst-loop.d.ts +1 -1
  5. package/dist/analyst-loop.js +3 -2
  6. package/dist/{chunk-VYXBFWHZ.js → chunk-7ODB76J5.js} +2 -2
  7. package/dist/{chunk-PHKNOAOU.js → chunk-HPYWEFVY.js} +25 -7
  8. package/dist/chunk-HPYWEFVY.js.map +1 -0
  9. package/dist/{chunk-P5OKDSLB.js → chunk-IODKUOBA.js} +5 -3
  10. package/dist/{chunk-P5OKDSLB.js.map → chunk-IODKUOBA.js.map} +1 -1
  11. package/dist/chunk-NBV35BR6.js +68 -0
  12. package/dist/chunk-NBV35BR6.js.map +1 -0
  13. package/dist/{chunk-55WKGOGU.js → chunk-NCH4XUZ7.js} +111 -31
  14. package/dist/chunk-NCH4XUZ7.js.map +1 -0
  15. package/dist/{chunk-VLF5RHEQ.js → chunk-T2HVQVB4.js} +1 -66
  16. package/dist/chunk-T2HVQVB4.js.map +1 -0
  17. package/dist/{chunk-HXVMLRYU.js → chunk-U56XGKVY.js} +7 -7
  18. package/dist/{coordination-CFVF0OzX.d.ts → coordination-DU0saWeg.d.ts} +8 -2
  19. package/dist/index.d.ts +6 -6
  20. package/dist/index.js +10 -9
  21. package/dist/index.js.map +1 -1
  22. package/dist/intelligence.d.ts +1 -1
  23. package/dist/lifecycle.d.ts +281 -0
  24. package/dist/lifecycle.js +174 -0
  25. package/dist/lifecycle.js.map +1 -0
  26. package/dist/{loop-runner-bin-B7biH0Gk.d.ts → loop-runner-bin-eD3m0rHW.d.ts} +2 -2
  27. package/dist/loop-runner-bin.d.ts +4 -4
  28. package/dist/loop-runner-bin.js +6 -5
  29. package/dist/loops.d.ts +45 -9
  30. package/dist/loops.js +6 -3
  31. package/dist/mcp/bin.js +6 -5
  32. package/dist/mcp/bin.js.map +1 -1
  33. package/dist/mcp/index.d.ts +6 -6
  34. package/dist/mcp/index.js +5 -4
  35. package/dist/mcp/index.js.map +1 -1
  36. package/dist/{openai-tools-DOI5mKNw.d.ts → openai-tools-CBurv8Cu.d.ts} +1 -1
  37. package/dist/profiles.d.ts +1 -1
  38. package/dist/{types-K8-xkiw1.d.ts → types-JufmXF2a.d.ts} +80 -1
  39. package/dist/{worktree-JXGJ1MxQ.d.ts → worktree-DaxOvw-C.d.ts} +1 -1
  40. package/dist/{worktree-fanout-DJHQy7Ux.d.ts → worktree-fanout-DIffZohV.d.ts} +15 -5
  41. package/package.json +6 -1
  42. package/dist/chunk-55WKGOGU.js.map +0 -1
  43. package/dist/chunk-PHKNOAOU.js.map +0 -1
  44. package/dist/chunk-VLF5RHEQ.js.map +0 -1
  45. /package/dist/{chunk-VYXBFWHZ.js.map → chunk-7ODB76J5.js.map} +0 -0
  46. /package/dist/{chunk-HXVMLRYU.js.map → chunk-U56XGKVY.js.map} +0 -0
@@ -1,14 +1,16 @@
1
1
  import {
2
2
  buildLoopSpanNodes
3
3
  } from "./chunk-VMNEQHJR.js";
4
+ import {
5
+ extractLlmCallEvent
6
+ } from "./chunk-T2HVQVB4.js";
4
7
  import {
5
8
  AgentEvalError,
6
9
  ConfigError,
7
10
  NotFoundError,
8
11
  RuntimeRunStateError,
9
- ValidationError,
10
- extractLlmCallEvent
11
- } from "./chunk-VLF5RHEQ.js";
12
+ ValidationError
13
+ } from "./chunk-NBV35BR6.js";
12
14
  import {
13
15
  UI_LENSES
14
16
  } from "./chunk-WIR4HOOJ.js";
@@ -162,6 +164,9 @@ function throwAbort() {
162
164
  function throwIfAborted(signal) {
163
165
  if (signal?.aborted) throw abortError();
164
166
  }
167
+ function isAbortError(err) {
168
+ return err instanceof Error && err.name === "AbortError";
169
+ }
165
170
  function sleep(ms, signal) {
166
171
  return new Promise((resolve) => {
167
172
  if (signal?.aborted) {
@@ -564,6 +569,8 @@ function createSandboxLineage(client, capabilities, options = {}) {
564
569
  throw new ValidationError("createSandboxLineage: client.create is required");
565
570
  }
566
571
  const streaming = options.streaming ?? "sse";
572
+ const recordMount = options.recordMount ?? (() => {
573
+ });
567
574
  const forkConcurrency = Math.max(
568
575
  1,
569
576
  Math.floor(options.maxConcurrency ?? DEFAULT_FORK_CONCURRENCY)
@@ -573,7 +580,7 @@ function createSandboxLineage(client, capabilities, options = {}) {
573
580
  if (signal.aborted) throwAbort();
574
581
  const opts = buildBackendOptions(spec.profile, spec.sandboxOverrides);
575
582
  const box = await acquireSandbox(client, opts, { signal });
576
- await spec.prepareBox?.(box, { signal });
583
+ await spec.prepareBox?.(box, { signal, recordMount });
577
584
  owned.push(box);
578
585
  return box;
579
586
  };
@@ -602,7 +609,7 @@ function createSandboxLineage(client, capabilities, options = {}) {
602
609
  if (checkpointId !== void 0) {
603
610
  const box2 = await forkFromCheckpoint(parent.box, checkpointId, signal);
604
611
  owned.push(box2);
605
- await spec.prepareBox?.(box2, { signal });
612
+ await spec.prepareBox?.(box2, { signal, recordMount });
606
613
  const sessionId2 = mintSessionId();
607
614
  return {
608
615
  handle: { box: box2, sessionId: sessionId2 },
@@ -691,13 +698,17 @@ async function runLoop(options) {
691
698
  const loopStart = now();
692
699
  const driverName = options.driver.name ?? "driver";
693
700
  const iterations = [];
701
+ const mounts = [];
702
+ const recordMount = (entry) => {
703
+ mounts.push(entry);
704
+ };
694
705
  let round = 0;
695
706
  const ownedBoxes = [];
696
707
  const collectBox = options.onWorkerBox ? (box) => {
697
708
  ownedBoxes.push(box);
698
709
  options.onWorkerBox?.(box);
699
710
  } : void 0;
700
- const lineageState = await setUpLineage(options, maxConcurrency);
711
+ const lineageState = await setUpLineage(options, maxConcurrency, recordMount);
701
712
  emitRunLoopHook(options, {
702
713
  target: "agent.run",
703
714
  phase: "before",
@@ -808,7 +819,8 @@ async function runLoop(options) {
808
819
  parentIndex,
809
820
  collectBox,
810
821
  lineagePlan,
811
- lineageState
822
+ lineageState,
823
+ recordMount
812
824
  });
813
825
  if (controller.signal.aborted) throwAbort();
814
826
  emitRunLoopHook(options, {
@@ -835,11 +847,19 @@ async function runLoop(options) {
835
847
  payload: { decision: stringifySafe(decision), historyLength: iterations.length }
836
848
  });
837
849
  if (isTerminalDecision(decision)) {
838
- return await finalizeAndEmitEnded(options, decision, iterations, loopStart, now, runId);
850
+ return await finalizeAndEmitEnded(
851
+ options,
852
+ decision,
853
+ iterations,
854
+ loopStart,
855
+ now,
856
+ runId,
857
+ mounts
858
+ );
839
859
  }
840
860
  if (lineageState) await pruneLineage(lineageState, iterations);
841
861
  }
842
- return await decideAndFinalize(options, iterations, loopStart, now, runId);
862
+ return await decideAndFinalize(options, iterations, loopStart, now, runId, mounts);
843
863
  } finally {
844
864
  if (options.ctx.signal) options.ctx.signal.removeEventListener("abort", onOuterAbort);
845
865
  await Promise.allSettled(
@@ -849,7 +869,7 @@ async function runLoop(options) {
849
869
  if (lineageState) await lineageState.lineage.teardown();
850
870
  }
851
871
  }
852
- async function setUpLineage(options, maxConcurrency) {
872
+ async function setUpLineage(options, maxConcurrency, recordMount) {
853
873
  const lineageOpts = options.lineage;
854
874
  if (!lineageOpts || !lineageOpts.sessionContinuity && !lineageOpts.forkFanout) return void 0;
855
875
  if (options.onWorkerBox) {
@@ -861,7 +881,8 @@ async function setUpLineage(options, maxConcurrency) {
861
881
  return {
862
882
  lineage: createSandboxLineage(options.ctx.sandboxClient, capabilities, {
863
883
  maxConcurrency,
864
- streaming: lineageOpts.streaming
884
+ streaming: lineageOpts.streaming,
885
+ recordMount
865
886
  }),
866
887
  options: lineageOpts,
867
888
  handles: /* @__PURE__ */ new Map(),
@@ -991,7 +1012,7 @@ async function executeIteration(args) {
991
1012
  args.lineageState?.handles.set(args.item.index, acquired.handle);
992
1013
  stream = acquired.events;
993
1014
  } else {
994
- box = await createSandboxForSpec(args.ctx.sandboxClient, spec, args.signal);
1015
+ box = await createSandboxForSpec(args.ctx.sandboxClient, spec, args.signal, args.recordMount);
995
1016
  const prompt = spec.taskToPrompt(args.item.task);
996
1017
  stream = args.streaming === "poll" ? promptEvents("poll", box, prompt, `${args.runId}-i${args.item.index}`, args.signal) : box.streamPrompt(prompt, { signal: args.signal });
997
1018
  }
@@ -1060,13 +1081,13 @@ async function executeIteration(args) {
1060
1081
  await destroySandboxSafe(box, args.ctx.traceEmitter, args.runId, args.now);
1061
1082
  }
1062
1083
  }
1063
- if (isAbortError(slot.error) || args.signal.aborted) {
1084
+ if (isAbortError2(slot.error) || args.signal.aborted) {
1064
1085
  if (slot.error) throw slot.error;
1065
1086
  throwAbort();
1066
1087
  }
1067
1088
  if (slot.error instanceof ValidationError) throw slot.error;
1068
1089
  }
1069
- function isAbortError(err) {
1090
+ function isAbortError2(err) {
1070
1091
  return err instanceof Error && err.name === "AbortError";
1071
1092
  }
1072
1093
  var TEARDOWN_TIMEOUT_MS2 = 15e3;
@@ -1120,15 +1141,35 @@ function readSandboxId(box) {
1120
1141
  const raw = box.id;
1121
1142
  return typeof raw === "string" && raw.length > 0 ? raw : void 0;
1122
1143
  }
1123
- async function createSandboxForSpec(client, spec, signal) {
1144
+ async function createSandboxForSpec(client, spec, signal, recordMount) {
1124
1145
  const opts = buildBackendOptions(spec.profile, spec.sandboxOverrides);
1125
1146
  if (signal.aborted) throwAbort();
1126
1147
  const box = await acquireSandbox(client, opts, { signal });
1127
- await spec.prepareBox?.(box, { signal });
1148
+ await invokePrepareBox(spec, box, signal, recordMount);
1128
1149
  return box;
1129
1150
  }
1151
+ async function invokePrepareBox(spec, box, signal, recordMount) {
1152
+ if (!spec.prepareBox) return;
1153
+ await spec.prepareBox(box, { signal, recordMount: recordMount ?? noopMountRecorder });
1154
+ }
1155
+ var noopMountRecorder = () => {
1156
+ };
1130
1157
  function finalize(args) {
1131
- const winner = args.options.selectWinner ? args.options.selectWinner(args.iterations) : args.options.driver.selectWinner?.(args.iterations) ?? defaultSelectWinner(args.iterations);
1158
+ let selector;
1159
+ let winner;
1160
+ if (args.options.selectWinner) {
1161
+ selector = "caller";
1162
+ winner = args.options.selectWinner(args.iterations);
1163
+ } else {
1164
+ const authored = args.options.driver.selectWinner?.(args.iterations);
1165
+ if (authored) {
1166
+ selector = "driver";
1167
+ winner = authored;
1168
+ } else {
1169
+ selector = "default";
1170
+ winner = defaultSelectWinner(args.iterations);
1171
+ }
1172
+ }
1132
1173
  const costUsd = args.iterations.reduce((sum, iter) => sum + (iter.costUsd || 0), 0);
1133
1174
  const tokenUsage = args.iterations.reduce((acc, iter) => {
1134
1175
  addTokenUsage(acc, iter.tokenUsage);
@@ -1140,11 +1181,36 @@ function finalize(args) {
1140
1181
  winner,
1141
1182
  durationMs: args.now() - args.startMs,
1142
1183
  costUsd,
1143
- tokenUsage
1184
+ tokenUsage,
1185
+ provenance: {
1186
+ mounts: args.mounts,
1187
+ selectionReceipts: buildSelectionReceipts(args.iterations, winner, selector)
1188
+ }
1144
1189
  };
1145
1190
  return result;
1146
1191
  }
1147
- async function decideAndFinalize(options, iterations, startMs, now, runId) {
1192
+ function buildSelectionReceipts(iterations, winner, selector) {
1193
+ const receipts = [];
1194
+ for (const iter of iterations) {
1195
+ if (iter.output === void 0 || iter.error) continue;
1196
+ const selected = winner?.iterationIndex === iter.index;
1197
+ const receipt = {
1198
+ candidateIndex: iter.index,
1199
+ selected,
1200
+ selector
1201
+ };
1202
+ if (iter.verdict?.score !== void 0) receipt.score = iter.verdict.score;
1203
+ if (selector === "default") receipt.reason = defaultSelectorReason(iter, selected);
1204
+ receipts.push(receipt);
1205
+ }
1206
+ return receipts;
1207
+ }
1208
+ function defaultSelectorReason(iter, selected) {
1209
+ const valid = iter.verdict?.valid === true;
1210
+ if (selected) return valid ? "best valid score" : "best non-errored score (no valid candidate)";
1211
+ return valid ? "valid but not top score" : "not selected";
1212
+ }
1213
+ async function decideAndFinalize(options, iterations, startMs, now, runId, mounts) {
1148
1214
  emitRunLoopHook(options, {
1149
1215
  target: "agent.decision",
1150
1216
  phase: "before",
@@ -1166,10 +1232,10 @@ async function decideAndFinalize(options, iterations, startMs, now, runId) {
1166
1232
  timestamp: now(),
1167
1233
  payload: { decision: stringifySafe(decision), historyLength: iterations.length }
1168
1234
  });
1169
- return finalizeAndEmitEnded(options, decision, iterations, startMs, now, runId);
1235
+ return finalizeAndEmitEnded(options, decision, iterations, startMs, now, runId, mounts);
1170
1236
  }
1171
- async function finalizeAndEmitEnded(options, decision, iterations, startMs, now, runId) {
1172
- const result = finalize({ options, decision, iterations, startMs, now, runId });
1237
+ async function finalizeAndEmitEnded(options, decision, iterations, startMs, now, runId, mounts) {
1238
+ const result = finalize({ options, decision, iterations, startMs, now, runId, mounts });
1173
1239
  emitRunLoopHook(options, {
1174
1240
  target: "agent.run",
1175
1241
  phase: "after",
@@ -1605,7 +1671,7 @@ async function runChild(live, executor, childAbort, task, opts, pool, ticket, bl
1605
1671
  } catch (err) {
1606
1672
  reconcileOnce(live.spent);
1607
1673
  await teardownSafe(executor, "brutalKill");
1608
- const aborted = childAbort.signal.aborted || isAbortError2(err);
1674
+ const aborted = childAbort.signal.aborted || isAbortError3(err);
1609
1675
  return downRecord(errMessage(err), aborted || isInfraError(err), executor.metered?.());
1610
1676
  }
1611
1677
  }
@@ -1707,7 +1773,7 @@ function isAgentSpec(value) {
1707
1773
  const v = value;
1708
1774
  return "profile" in v && "harness" in v;
1709
1775
  }
1710
- function isAbortError2(err) {
1776
+ function isAbortError3(err) {
1711
1777
  return typeof err === "object" && err !== null && "name" in err && err.name === "AbortError";
1712
1778
  }
1713
1779
  function isInfraError(err) {
@@ -2126,12 +2192,12 @@ function createWorktreeCliExecutor(options) {
2126
2192
  }
2127
2193
  const runId = options.runId ?? randomUUID();
2128
2194
  const controller = new AbortController();
2195
+ const budgetExempt = options.budgetExempt ?? true;
2129
2196
  let run;
2130
2197
  let artifact;
2131
2198
  return {
2132
2199
  runtime: "cli",
2133
- // A harness CLI cannot account tokens — exclude it from the conserved pool + equal-k.
2134
- budgetExempt: true,
2200
+ budgetExempt,
2135
2201
  async execute(_task, signal) {
2136
2202
  const linked = linkSignals(signal, controller.signal);
2137
2203
  const started = Date.now();
@@ -2153,7 +2219,9 @@ function createWorktreeCliExecutor(options) {
2153
2219
  });
2154
2220
  const spent = {
2155
2221
  iterations: 1,
2156
- // budgetExempt: spend is recorded zero (not metered), never a fabricated cost.
2222
+ // The worktree-harness core surfaces no token/usd usage, so tokens/usd are a genuine zero
2223
+ // (NOT a fabricated cost). When budgetExempt is true the pool ignores this spend entirely;
2224
+ // when explicitly false the scope debits exactly this captured spend — the real iteration.
2157
2225
  tokens: zeroTokenUsage(),
2158
2226
  usd: 0,
2159
2227
  ms: Date.now() - started
@@ -3769,10 +3837,14 @@ function createCoordinationTools(opts) {
3769
3837
  return q.status !== "answered" && q.status !== "deferred";
3770
3838
  });
3771
3839
  };
3840
+ const maxLiveWorkers = opts.maxLiveWorkers;
3841
+ const liveWorkerCount = () => opts.scope.view.nodes.filter(
3842
+ (n) => n.status !== "done" && n.status !== "failed" && n.status !== "cancelled"
3843
+ ).length;
3772
3844
  const tools = [
3773
3845
  {
3774
3846
  name: "spawn_agent",
3775
- 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.",
3847
+ 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. When a max-live-workers cap is set it also fails closed (`error: "max-live-workers"`) while that many workers are still in flight \u2014 settle or steer one before spawning another.',
3776
3848
  inputSchema: {
3777
3849
  type: "object",
3778
3850
  properties: {
@@ -3794,6 +3866,8 @@ function createCoordinationTools(opts) {
3794
3866
  },
3795
3867
  handler: (raw) => {
3796
3868
  const a = obj(raw);
3869
+ if (maxLiveWorkers !== void 0 && maxLiveWorkers > 0 && liveWorkerCount() >= maxLiveWorkers)
3870
+ return Promise.resolve({ error: "max-live-workers" });
3797
3871
  const agent = opts.makeWorkerAgent(a.profile);
3798
3872
  const budget = a.budget === void 0 ? opts.perWorker : mergeBudget(opts.perWorker, a.budget);
3799
3873
  const res = opts.scope.spawn(agent, a.task, {
@@ -4073,7 +4147,8 @@ function driverAgent(opts) {
4073
4147
  scope,
4074
4148
  blobs: opts.blobs,
4075
4149
  makeWorkerAgent: opts.makeWorkerAgent,
4076
- perWorker: opts.perWorker
4150
+ perWorker: opts.perWorker,
4151
+ ...opts.maxLiveWorkers !== void 0 ? { maxLiveWorkers: opts.maxLiveWorkers } : {}
4077
4152
  });
4078
4153
  const byName = new Map(coord.tools.map((t) => [t.name, t]));
4079
4154
  const toolSpecs = [
@@ -5157,6 +5232,7 @@ function supervise(profile, task, opts) {
5157
5232
  blobs,
5158
5233
  makeWorkerAgent,
5159
5234
  perWorker,
5235
+ ...opts.maxLiveWorkers !== void 0 ? { maxLiveWorkers: opts.maxLiveWorkers } : {},
5160
5236
  ...opts.router ? { router: opts.router } : {},
5161
5237
  ...opts.brain ? { brain: opts.brain } : {},
5162
5238
  ...opts.driveHarness ? { driveHarness: opts.driveHarness } : {},
@@ -6036,6 +6112,7 @@ async function serveCoordinationMcp(opts) {
6036
6112
  blobs: opts.blobs,
6037
6113
  makeWorkerAgent: opts.makeWorkerAgent,
6038
6114
  perWorker: opts.perWorker,
6115
+ ...opts.maxLiveWorkers !== void 0 ? { maxLiveWorkers: opts.maxLiveWorkers } : {},
6039
6116
  ...opts.analysts ? { analysts: opts.analysts } : {},
6040
6117
  ...opts.analyzeOnSettle ? { analyzeOnSettle: opts.analyzeOnSettle } : {},
6041
6118
  ...opts.onEvent ? { onEvent: opts.onEvent } : {},
@@ -6112,6 +6189,7 @@ function supervisorAgent(profile, deps) {
6112
6189
  makeWorkerAgent: deps.makeWorkerAgent,
6113
6190
  perWorker: deps.perWorker,
6114
6191
  systemPrompt,
6192
+ ...deps.maxLiveWorkers !== void 0 ? { maxLiveWorkers: deps.maxLiveWorkers } : {},
6115
6193
  ...deps.extraTools ? { extraTools: deps.extraTools } : {},
6116
6194
  ...deps.executeExtraTool ? { executeExtraTool: deps.executeExtraTool } : {},
6117
6195
  ...deps.maxTurns !== void 0 ? { maxTurns: deps.maxTurns } : {}
@@ -6130,7 +6208,8 @@ function supervisorAgent(profile, deps) {
6130
6208
  scope,
6131
6209
  blobs: deps.blobs,
6132
6210
  makeWorkerAgent: deps.makeWorkerAgent,
6133
- perWorker: deps.perWorker
6211
+ perWorker: deps.perWorker,
6212
+ ...deps.maxLiveWorkers !== void 0 ? { maxLiveWorkers: deps.maxLiveWorkers } : {}
6134
6213
  });
6135
6214
  try {
6136
6215
  await driveHarness({ profile, task, scope, coordinationMcpUrl: mcp.url });
@@ -6157,6 +6236,7 @@ export {
6157
6236
  randomSuffix,
6158
6237
  throwAbort,
6159
6238
  throwIfAborted,
6239
+ isAbortError,
6160
6240
  sleep,
6161
6241
  stringifySafe,
6162
6242
  zeroTokenUsage,
@@ -6253,4 +6333,4 @@ export {
6253
6333
  createInProcessTransport,
6254
6334
  serveCoordinationMcp
6255
6335
  };
6256
- //# sourceMappingURL=chunk-55WKGOGU.js.map
6336
+ //# sourceMappingURL=chunk-NCH4XUZ7.js.map