@tangle-network/agent-runtime 0.109.2 → 0.111.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 (72) hide show
  1. package/dist/{activation-CM-L6TtL.js → activation-CsuHCZVN.js} +3 -3
  2. package/dist/{activation-CM-L6TtL.js.map → activation-CsuHCZVN.js.map} +1 -1
  3. package/dist/agent.d.ts +4 -4
  4. package/dist/agent.js +2 -2
  5. package/dist/agent.js.map +1 -1
  6. package/dist/{analyst-loop-C8cGThTW.js → analyst-loop-BoNIG2hA.js} +30 -9
  7. package/dist/analyst-loop-BoNIG2hA.js.map +1 -0
  8. package/dist/analyst-loop.d.ts +1 -1
  9. package/dist/analyst-loop.js +1 -1
  10. package/dist/candidate-execution/index.js +4 -4
  11. package/dist/{candidate-execution-nYMa-bc-.js → candidate-execution-Co3sRC_7.js} +4 -4
  12. package/dist/{candidate-execution-nYMa-bc-.js.map → candidate-execution-Co3sRC_7.js.map} +1 -1
  13. package/dist/{environment-provider-CfLUmKmf.js → environment-provider-BsHpW4Dp.js} +52 -5
  14. package/dist/environment-provider-BsHpW4Dp.js.map +1 -0
  15. package/dist/{environment-provider-CMqSAp-O.d.ts → environment-provider-CTEMEP9u.d.ts} +9 -1
  16. package/dist/environment-provider.d.ts +1 -1
  17. package/dist/environment-provider.js +1 -1
  18. package/dist/{improvement-adapter-BaAdfJKT.d.ts → improvement-adapter-D5gwwoXQ.d.ts} +2 -2
  19. package/dist/{improvement-cycle-9O4iVFOA.js → improvement-cycle-ryAyCLKN.js} +5 -5
  20. package/dist/{improvement-cycle-9O4iVFOA.js.map → improvement-cycle-ryAyCLKN.js.map} +1 -1
  21. package/dist/{index-BwY61sh3.d.ts → index-BmI2uxy5.d.ts} +3 -3
  22. package/dist/{index-CFJ_1m1U.d.ts → index-DlLPNELY.d.ts} +298 -92
  23. package/dist/{index-HsQm1Rrr.d.ts → index-sLuBoGud.d.ts} +6 -6
  24. package/dist/index.d.ts +5 -5
  25. package/dist/index.js +11 -11
  26. package/dist/intelligence.d.ts +2 -2
  27. package/dist/intelligence.js +39 -9
  28. package/dist/intelligence.js.map +1 -1
  29. package/dist/kernel.d.ts +3 -3
  30. package/dist/kernel.js +7 -7
  31. package/dist/{knowledge-1a38bcUT.js → knowledge-DBNAteaC.js} +5 -5
  32. package/dist/{knowledge-1a38bcUT.js.map → knowledge-DBNAteaC.js.map} +1 -1
  33. package/dist/knowledge.d.ts +1 -1
  34. package/dist/knowledge.js +1 -1
  35. package/dist/{loop-runner-bin-C35m19w0.js → loop-runner-bin-BLOckrqT.js} +4 -4
  36. package/dist/{loop-runner-bin-C35m19w0.js.map → loop-runner-bin-BLOckrqT.js.map} +1 -1
  37. package/dist/{loop-runner-bin-DUQF0bYz.d.ts → loop-runner-bin-vRo5TZt_.d.ts} +4 -4
  38. package/dist/loop-runner-bin.d.ts +1 -1
  39. package/dist/loop-runner-bin.js +1 -1
  40. package/dist/mcp/bin.js +1 -1
  41. package/dist/mcp/index.d.ts +1 -1
  42. package/dist/mcp/index.js +5 -5
  43. package/dist/{openai-tools-DT9FH2_t.js → openai-tools-st-hERvA.js} +2 -2
  44. package/dist/{openai-tools-DT9FH2_t.js.map → openai-tools-st-hERvA.js.map} +1 -1
  45. package/dist/{prepare-Pr19X93k.js → prepare-BKVdOn0w.js} +15 -14
  46. package/dist/prepare-BKVdOn0w.js.map +1 -0
  47. package/dist/primeintellect/index.d.ts +1 -1
  48. package/dist/{protected-model-port-uthtDNqu.js → protected-model-port-BtldAE9j.js} +2 -2
  49. package/dist/{protected-model-port-uthtDNqu.js.map → protected-model-port-BtldAE9j.js.map} +1 -1
  50. package/dist/{runtime-dpJZmZtt.js → runtime-fwz-erxT.js} +422 -15
  51. package/dist/runtime-fwz-erxT.js.map +1 -0
  52. package/dist/{spawn-journal-CwPvKUTa.js → spawn-journal-DLhnom3e.js} +2 -2
  53. package/dist/{spawn-journal-CwPvKUTa.js.map → spawn-journal-DLhnom3e.js.map} +1 -1
  54. package/dist/{structural-rollout-ASQLr4-v.js → structural-rollout-CgnNy7_4.js} +3 -3
  55. package/dist/{structural-rollout-ASQLr4-v.js.map → structural-rollout-CgnNy7_4.js.map} +1 -1
  56. package/dist/{supervise-DyPmmhJ6.js → supervise-CeZtA1wu.js} +223 -107
  57. package/dist/supervise-CeZtA1wu.js.map +1 -0
  58. package/dist/{supervisor-sTJC9psT.js → supervisor-ByCPHcp9.js} +82 -24
  59. package/dist/supervisor-ByCPHcp9.js.map +1 -0
  60. package/dist/testing.js +9 -9
  61. package/dist/{types-CfGKhIuj.d.ts → types-zWfqDjeL.d.ts} +10 -1
  62. package/dist/{util-MVgdwuIS.js → util-Cc9g9Y-o.js} +2 -2
  63. package/dist/{util-MVgdwuIS.js.map → util-Cc9g9Y-o.js.map} +1 -1
  64. package/dist/{workspace-archive-C9w_rxt6.js → workspace-archive-CYYxZyA7.js} +2 -2
  65. package/dist/{workspace-archive-C9w_rxt6.js.map → workspace-archive-CYYxZyA7.js.map} +1 -1
  66. package/package.json +7 -7
  67. package/dist/analyst-loop-C8cGThTW.js.map +0 -1
  68. package/dist/environment-provider-CfLUmKmf.js.map +0 -1
  69. package/dist/prepare-Pr19X93k.js.map +0 -1
  70. package/dist/runtime-dpJZmZtt.js.map +0 -1
  71. package/dist/supervise-DyPmmhJ6.js.map +0 -1
  72. package/dist/supervisor-sTJC9psT.js.map +0 -1
@@ -1,10 +1,10 @@
1
1
  import { c as RuntimeRunStateError, i as ConfigError, o as NotFoundError, t as AgentEvalError$1, u as ValidationError } from "./errors-DEAvWQPy.js";
2
- import { a as randomSuffix, c as stringifySafe, d as withTimeout, f as zeroTokenUsage, i as mapWithConcurrency, l as throwAbort, n as deleteBoxSafe, o as randomUuid, s as sleep, t as addTokenUsage, u as throwIfAborted } from "./util-MVgdwuIS.js";
3
- import { a as contentAddress, i as InMemorySpawnJournal, n as FileSpawnJournal, r as InMemoryResultBlobStore, t as FileResultBlobStore } from "./spawn-journal-CwPvKUTa.js";
4
- import { A as createWorktree, C as routerChatWithUsage, D as runWorktreeChecks, O as runWorktreeHarness, T as runBrainLoop, a as runFinalizer, i as pickBestDelivered, j as removeWorktree, k as captureWorktreeDiff, l as withDriverExecutor, n as bestDelivered, o as runTree, t as createSupervisor, x as routerBrain, y as createActivityLog } from "./supervisor-sTJC9psT.js";
2
+ import { a as mapWithConcurrency, c as sleep, d as throwIfAborted, f as withTimeout, l as stringifySafe, n as addTokenUsage, o as randomSuffix, p as zeroTokenUsage, r as deleteBoxSafe, s as randomUuid, t as abortError, u as throwAbort } from "./util-Cc9g9Y-o.js";
3
+ import { a as contentAddress, i as InMemorySpawnJournal, n as FileSpawnJournal, r as InMemoryResultBlobStore, t as FileResultBlobStore } from "./spawn-journal-DLhnom3e.js";
4
+ import { A as createWorktree, C as routerChatWithUsage, D as runWorktreeChecks, O as runWorktreeHarness, T as runBrainLoop, a as runFinalizer, i as pickBestDelivered, j as removeWorktree, k as captureWorktreeDiff, l as withDriverExecutor, n as bestDelivered, o as runTree, t as createSupervisor, x as routerBrain, y as createActivityLog } from "./supervisor-ByCPHcp9.js";
5
5
  import { i as notifyRuntimeHookEvent } from "./runtime-hooks-C7iJOWm3.js";
6
6
  import { a as notifySandboxEventObserver, n as extractLlmCallEvent } from "./sandbox-events-DeI5xX8P.js";
7
- import { i as resolveAgentEnvironmentProvider, n as providerAsExecutor } from "./environment-provider-CfLUmKmf.js";
7
+ import { i as resolveAgentEnvironmentProvider, n as providerAsExecutor, s as buildBackendOptions } from "./environment-provider-BsHpW4Dp.js";
8
8
  import { r as buildLoopSpanNodes } from "./otel-export-D34IQW1C.js";
9
9
  import { t as createStdioToolServer } from "./tool-server-RcWgLIsL.js";
10
10
  import { n as UI_LENSES } from "./substrate-B0TYNrXn.js";
@@ -263,37 +263,6 @@ function isRetryable(err) {
263
263
  return /provision failed|edge data plane|not reachable|failed to create sandbox/i.test(msg);
264
264
  }
265
265
  //#endregion
266
- //#region src/runtime/sandbox-backend.ts
267
- /**
268
- * Resolve the backend `type`: an explicit override wins, then the profile's
269
- * `metadata.backendType` hint, else the SDK's profile-driven default
270
- * (`'opencode'` on the platform side). A profile with no hint falls through to
271
- * the default rather than asserting provenance the profile never declared.
272
- */
273
- function resolveBackendType(profile, override) {
274
- if (override?.type) return override.type;
275
- const explicit = profile.metadata?.backendType;
276
- if (typeof explicit === "string") return explicit;
277
- return "opencode";
278
- }
279
- /**
280
- * Build `CreateSandboxOptions` for `profile`, merging `overrides` and setting
281
- * `backend.profile`. `model`/`server` from an override backend pass through.
282
- */
283
- function buildBackendOptions(profile, overrides) {
284
- const base = overrides ?? {};
285
- const overrideBackend = base.backend;
286
- return {
287
- ...base,
288
- backend: {
289
- type: resolveBackendType(profile, overrideBackend),
290
- profile,
291
- ...overrideBackend?.model ? { model: overrideBackend.model } : {},
292
- ...overrideBackend?.server ? { server: overrideBackend.server } : {}
293
- }
294
- };
295
- }
296
- //#endregion
297
266
  //#region src/runtime/sandbox-capabilities.ts
298
267
  const probeCache = /* @__PURE__ */ new WeakMap();
299
268
  /**
@@ -1317,7 +1286,9 @@ function toToolSpan(input, runId, seq, at) {
1317
1286
  name: input.toolName,
1318
1287
  toolName: input.toolName,
1319
1288
  args: input.args,
1289
+ ...input.argsCaptured === false ? { argsCaptured: false } : {},
1320
1290
  status: input.status ?? "ok",
1291
+ ...input.error !== void 0 ? { error: input.error } : {},
1321
1292
  startedAt,
1322
1293
  endedAt,
1323
1294
  ...input.result !== void 0 ? { result: input.result } : {}
@@ -1517,13 +1488,13 @@ function sandboxSessionTraceSource(box, sessionId, opts = {}) {
1517
1488
  * already maintains. So this module is a thin protocol adapter, and every capability maps onto a
1518
1489
  * verb pi already has:
1519
1490
  *
1520
- * `execute` → `prompt`, draining pi's event stream until `agent_end`
1491
+ * `execute` → `prompt`, draining pi's event stream until `agent_settled`
1521
1492
  * `deliver` → `prompt` with `streamingBehavior` — pi owns the queue, we do not
1522
1493
  * `teardown` → `abort`, then close stdin and reap the process
1523
1494
  * `progress` → pi's `tool_execution_start`/`_end` + `turn_end` events, plus `get_state`'s
1524
1495
  * `pendingMessageCount` mirrored locally so the read stays synchronous
1525
1496
  * `traceSource` → the same tool events decoded into the shared `ToolSpan` currency
1526
- * `resultArtifact` → the last assistant text collected off the stream
1497
+ * `resultArtifact` → the terminal successful assistant turn
1527
1498
  *
1528
1499
  * It is registered through the DOCUMENTED extension point (`ExecutorRegistry.register('pi', …)`),
1529
1500
  * so nothing in the resolver switches on it and a consumer can replace it wholesale.
@@ -1532,9 +1503,11 @@ function sandboxSessionTraceSource(box, sessionId, opts = {}) {
1532
1503
  * are read structurally off JSON lines, so a pi that adds commands stays compatible and a pi that
1533
1504
  * is not installed simply fails loud at spawn instead of at import.
1534
1505
  *
1535
- * Usage accounting: pi reports token usage on its assistant messages when the provider supplies
1536
- * it. Nothing is fabricated a turn whose usage pi does not report contributes an `iteration`
1537
- * event and zero tokens, exactly like the other honest executors.
1506
+ * Usage accounting: pi repeats the same assistant receipt in `message_end` and `turn_end`.
1507
+ * Only `turn_end` is counted, once per model call. Pi reports cache traffic separately from fresh
1508
+ * input, so all three input classes are folded into Runtime's two-field token total. Subscription
1509
+ * usage whose dollar price is absent or zero stays explicitly unknown through the live usage
1510
+ * stream and terminal artifact.
1538
1511
  *
1539
1512
  * @experimental
1540
1513
  */
@@ -1598,10 +1571,10 @@ const piExecutor = (spec, ctx) => {
1598
1571
  };
1599
1572
  };
1600
1573
  /**
1601
- * One pi RPC session, run to `agent_end`. Every steer delivered while the turn is in flight is
1574
+ * One pi RPC session, run to `agent_settled`. Every steer delivered while the turn is in flight is
1602
1575
  * forwarded to pi IMMEDIATELY (pi queues and delivers it at its own turn boundary — the queue we
1603
- * deliberately do not reimplement), and any steer still unread when pi goes idle re-prompts it,
1604
- * so a pi worker cannot settle while a message it never saw is pending.
1576
+ * deliberately do not reimplement), and any steer still unread when pi settles re-prompts it.
1577
+ * `agent_end` is deliberately not terminal: Pi may auto-retry or compact after emitting it.
1605
1578
  */
1606
1579
  async function* streamPiSession(args) {
1607
1580
  const { seam, inbox, activity, state } = args;
@@ -1611,12 +1584,23 @@ async function* streamPiSession(args) {
1611
1584
  output: 0
1612
1585
  };
1613
1586
  let usd = 0;
1587
+ let usdKnown = true;
1588
+ throwIfAborted(args.signal);
1589
+ throwIfAborted(args.controller.signal);
1614
1590
  const proc = spawnPi(seam);
1615
1591
  state.proc = proc;
1616
1592
  state.note = "connected";
1617
1593
  const events = [];
1618
- let idle = false;
1594
+ const pendingTools = /* @__PURE__ */ new Map();
1595
+ const awaitingPromptResponses = /* @__PURE__ */ new Set();
1596
+ let settled = false;
1597
+ let acceptedPromptSinceSettlement = false;
1598
+ let promptSequence = 0;
1599
+ let lastAssistant;
1619
1600
  let failure;
1601
+ let abortDeadline;
1602
+ let exited = false;
1603
+ let exitCode;
1620
1604
  let wake;
1621
1605
  const notify = () => {
1622
1606
  const w = wake;
@@ -1625,59 +1609,80 @@ async function* streamPiSession(args) {
1625
1609
  };
1626
1610
  const stdoutLines = readJsonLines(proc, (value) => {
1627
1611
  const ev = value;
1628
- if (ev.type === "agent_start") idle = false;
1629
- if (ev.type === "agent_end") idle = true;
1630
1612
  events.push(ev);
1631
1613
  notify();
1632
1614
  });
1633
1615
  proc.once("exit", (code) => {
1634
- if (!idle && code !== 0 && code !== null) failure = new ValidationError(`piExecutor: pi exited with code ${code}`);
1635
- idle = true;
1616
+ exited = true;
1617
+ exitCode = code;
1636
1618
  notify();
1637
1619
  });
1638
1620
  proc.once("error", (e) => {
1639
1621
  failure = new ValidationError(`piExecutor: pi failed to start: ${e.message}`);
1640
- idle = true;
1641
1622
  notify();
1642
1623
  });
1643
1624
  const abortAll = () => {
1625
+ if (abortDeadline !== void 0) return;
1644
1626
  sendCommand(proc, { type: "abort" });
1645
- idle = true;
1627
+ abortDeadline = Date.now() + PI_ABORT_RECEIPT_MS;
1628
+ state.note = "aborting";
1646
1629
  notify();
1647
1630
  };
1648
- if (args.signal.aborted || args.controller.signal.aborted) abortAll();
1649
- else {
1650
- args.signal.addEventListener("abort", abortAll, { once: true });
1651
- args.controller.signal.addEventListener("abort", abortAll, { once: true });
1652
- }
1631
+ args.signal.addEventListener("abort", abortAll, { once: true });
1632
+ args.controller.signal.addEventListener("abort", abortAll, { once: true });
1653
1633
  const system = args.spec.profile.prompt?.systemPrompt;
1654
1634
  const opening = system ? `${system}\n\n${taskText(args.task)}` : taskText(args.task);
1655
1635
  const deadline = seam.turnTimeoutMs ? Date.now() + seam.turnTimeoutMs : void 0;
1656
- try {
1636
+ const sendPrompt = (message, streamingBehavior) => {
1637
+ const id = `agent-runtime-prompt-${++promptSequence}`;
1638
+ awaitingPromptResponses.add(id);
1657
1639
  sendCommand(proc, {
1640
+ id,
1658
1641
  type: "prompt",
1659
- message: opening
1642
+ message,
1643
+ ...streamingBehavior ? { streamingBehavior } : {}
1660
1644
  });
1645
+ };
1646
+ try {
1647
+ if (args.signal.aborted || args.controller.signal.aborted) throw abortError();
1648
+ sendPrompt(opening);
1661
1649
  state.note = "turn 0";
1662
1650
  for (;;) {
1663
- if (!idle) forwardPending(proc, inbox, activity);
1651
+ if (!settled && abortDeadline === void 0) forwardPending(inbox, activity, sendPrompt);
1664
1652
  while (events.length > 0) {
1665
1653
  const ev = events.shift();
1666
- for (const usage of projectPiEvent(ev, args, tokens)) {
1667
- if (usage.kind === "cost") usd += usage.usd;
1654
+ if (ev.type === "response" && ev.command === "prompt" && typeof ev.id === "string" && awaitingPromptResponses.delete(ev.id)) if (ev.success === true) acceptedPromptSinceSettlement = true;
1655
+ else failure = new ValidationError(`piExecutor: Pi rejected prompt: ${ev.error ?? "unknown RPC error"}`);
1656
+ if (ev.type === "agent_start") settled = false;
1657
+ if (ev.type === "agent_settled") {
1658
+ settled = true;
1659
+ acceptedPromptSinceSettlement = false;
1660
+ }
1661
+ const projected = projectPiEvent(ev, args, tokens, pendingTools);
1662
+ if (projected.assistant) lastAssistant = projected.assistant;
1663
+ for (const usage of projected.events) {
1664
+ if (usage.kind === "cost") {
1665
+ usd += usage.usd;
1666
+ if (usage.usdKnown === false) usdKnown = false;
1667
+ }
1668
1668
  yield usage;
1669
1669
  }
1670
1670
  }
1671
1671
  if (failure) throw failure;
1672
- if (deadline !== void 0 && Date.now() > deadline) throw new ValidationError("piExecutor: turn exceeded turnTimeoutMs");
1673
- if (idle) {
1672
+ if (abortDeadline !== void 0 && (settled || exited)) throw abortError();
1673
+ if (abortDeadline === void 0 && exited && (!settled || awaitingPromptResponses.size > 0 || acceptedPromptSinceSettlement)) throw new ValidationError(`piExecutor: pi exited before agent_settled (code ${exitCode ?? "unknown"})`);
1674
+ if (abortDeadline === void 0 && deadline !== void 0 && Date.now() > deadline) throw new ValidationError("piExecutor: turn exceeded turnTimeoutMs");
1675
+ if (abortDeadline !== void 0 && Date.now() > abortDeadline) {
1676
+ const error = abortError();
1677
+ error.message = `piExecutor: abort did not settle within ${PI_ABORT_RECEIPT_MS}ms`;
1678
+ throw error;
1679
+ }
1680
+ if (settled && awaitingPromptResponses.size === 0 && !acceptedPromptSinceSettlement) {
1674
1681
  const pending = inbox.drain();
1675
1682
  if (pending.length === 0) break;
1676
- idle = false;
1677
- sendCommand(proc, {
1678
- type: "prompt",
1679
- message: inbox.fold(pending)
1680
- });
1683
+ settled = false;
1684
+ lastAssistant = void 0;
1685
+ sendPrompt(inbox.fold(pending));
1681
1686
  state.note = `turn ${state.turns}`;
1682
1687
  continue;
1683
1688
  }
@@ -1699,10 +1704,16 @@ async function* streamPiSession(args) {
1699
1704
  args.controller.signal.removeEventListener("abort", abortAll);
1700
1705
  await killPi(proc, 2e3).catch(() => ({ destroyed: false }));
1701
1706
  }
1707
+ if (args.signal.aborted || args.controller.signal.aborted) throw abortError();
1708
+ if (!lastAssistant) throw new ValidationError("piExecutor: agent_settled without an assistant turn");
1709
+ if (lastAssistant.stopReason === "aborted") throw abortError();
1710
+ if (lastAssistant.stopReason === "error") throw new ValidationError(`piExecutor: Pi assistant failed: ${lastAssistant.errorMessage ?? "unknown provider error"}`);
1711
+ state.lastText = lastAssistant.text;
1702
1712
  const spent = {
1703
1713
  iterations: state.turns,
1704
1714
  tokens,
1705
1715
  usd,
1716
+ ...usdKnown ? {} : { usdKnown: false },
1706
1717
  ms: Date.now() - started
1707
1718
  };
1708
1719
  state.artifact = {
@@ -1715,14 +1726,10 @@ async function* streamPiSession(args) {
1715
1726
  };
1716
1727
  }
1717
1728
  /** Route messages through pi's state-safe prompt command; pi owns the queue and idle transition. */
1718
- function forwardPending(proc, inbox, activity) {
1729
+ function forwardPending(inbox, activity, sendPrompt) {
1719
1730
  const pending = inbox.drain();
1720
1731
  for (const m of pending) {
1721
- sendCommand(proc, {
1722
- type: "prompt",
1723
- message: renderOne(m),
1724
- streamingBehavior: m.interrupt ? "steer" : "followUp"
1725
- });
1732
+ sendPrompt(renderOne(m), m.interrupt ? "steer" : "followUp");
1726
1733
  activity.push({
1727
1734
  at: Date.now(),
1728
1735
  kind: "note",
@@ -1737,7 +1744,7 @@ function renderOne(m) {
1737
1744
  }
1738
1745
  /** Project one pi event onto usage events, updating turn count / activity / trace as a side
1739
1746
  * effect. pi's tool events are the live trace; its `turn_end` bumps the turn counter. */
1740
- function projectPiEvent(ev, args, tokens) {
1747
+ function projectPiEvent(ev, args, tokens, pendingTools) {
1741
1748
  const out = [];
1742
1749
  const at = Date.now();
1743
1750
  if (ev.type === "tool_execution_start" && typeof ev.toolName === "string") {
@@ -1747,10 +1754,18 @@ function projectPiEvent(ev, args, tokens) {
1747
1754
  label: ev.toolName,
1748
1755
  detail: describeArgs$1(ev.args)
1749
1756
  });
1750
- return out;
1757
+ if (typeof ev.toolCallId === "string") pendingTools.set(ev.toolCallId, {
1758
+ args: ev.args ?? {},
1759
+ startedAt: at
1760
+ });
1761
+ return { events: out };
1751
1762
  }
1752
1763
  if (ev.type === "tool_execution_end" && typeof ev.toolName === "string") {
1753
1764
  const status = ev.isError === true ? "error" : "ok";
1765
+ const callId = typeof ev.toolCallId === "string" ? ev.toolCallId : void 0;
1766
+ const started = callId ? pendingTools.get(callId) : void 0;
1767
+ if (callId) pendingTools.delete(callId);
1768
+ const error = status === "error" ? describeToolError(ev.result) : void 0;
1754
1769
  args.activity.push({
1755
1770
  at,
1756
1771
  kind: "tool",
@@ -1759,13 +1774,19 @@ function projectPiEvent(ev, args, tokens) {
1759
1774
  });
1760
1775
  args.record({
1761
1776
  toolName: ev.toolName,
1762
- args: ev.args ?? {},
1777
+ args: started?.args ?? {},
1778
+ ...started ? {} : { argsCaptured: false },
1763
1779
  status,
1764
- ...typeof ev.toolCallId === "string" ? { callId: ev.toolCallId } : {}
1780
+ ...ev.result !== void 0 ? { result: ev.result } : {},
1781
+ ...error !== void 0 ? { error } : {},
1782
+ ...callId ? { callId } : {},
1783
+ ...started ? { startedAt: started.startedAt } : {},
1784
+ endedAt: at
1765
1785
  });
1766
- return out;
1786
+ return { events: out };
1767
1787
  }
1768
- if (ev.type === "turn_end" || ev.type === "message_end") {
1788
+ if (ev.type === "message_end") return { events: out };
1789
+ if (ev.type === "turn_end") {
1769
1790
  const usage = readUsage(ev.message);
1770
1791
  if (usage && (usage.input || usage.output)) {
1771
1792
  tokens.input += usage.input;
@@ -1776,38 +1797,55 @@ function projectPiEvent(ev, args, tokens) {
1776
1797
  output: usage.output
1777
1798
  });
1778
1799
  }
1779
- if (usage?.usd) out.push({
1800
+ out.push(usage?.usd !== void 0 ? {
1780
1801
  kind: "cost",
1781
1802
  usd: usage.usd
1803
+ } : {
1804
+ kind: "cost",
1805
+ usd: 0,
1806
+ usdKnown: false
1782
1807
  });
1783
- const text = readText(ev.message);
1784
- if (text) args.state.lastText = text;
1785
- if (ev.type === "turn_end") {
1786
- args.state.turns += 1;
1787
- args.activity.push({
1788
- at,
1789
- kind: "turn",
1790
- label: `turn ${args.state.turns}`
1791
- });
1792
- out.push({ kind: "iteration" });
1793
- }
1808
+ args.state.turns += 1;
1809
+ args.activity.push({
1810
+ at,
1811
+ kind: "turn",
1812
+ label: `turn ${args.state.turns}`
1813
+ });
1814
+ out.push({ kind: "iteration" });
1815
+ const assistant = readAssistantOutcome(ev.message);
1816
+ return {
1817
+ events: out,
1818
+ ...assistant ? { assistant } : {}
1819
+ };
1794
1820
  }
1795
- return out;
1821
+ return { events: out };
1796
1822
  }
1797
- /** pi's assistant message carries provider usage when the provider reported it. Absent, nothing
1798
- * is fabricated the turn still counts as an iteration with zero tokens. */
1823
+ /** Pi's fresh input excludes cache reads and writes. Runtime's input channel includes all model
1824
+ * input, so combine them once at the assistant receipt. A missing or zero price is unknown because
1825
+ * subscription-backed providers report zero even when compute was not free. */
1799
1826
  function readUsage(message) {
1800
1827
  if (!message || typeof message !== "object") return void 0;
1801
1828
  const usage = message.usage;
1802
1829
  if (!usage || typeof usage !== "object") return void 0;
1803
1830
  const u = usage;
1804
- const input = num(u.input) ?? num(u.inputTokens) ?? num(u.prompt_tokens) ?? 0;
1831
+ const input = num(u.prompt_tokens) ?? (num(u.input) ?? num(u.inputTokens) ?? 0) + (num(u.cacheRead) ?? num(u.cache_read_input_tokens) ?? num(u.cacheReadInputTokens) ?? 0) + (num(u.cacheWrite) ?? num(u.cache_creation_input_tokens) ?? num(u.cacheCreationInputTokens) ?? 0);
1805
1832
  const output = num(u.output) ?? num(u.outputTokens) ?? num(u.completion_tokens) ?? 0;
1806
1833
  const costRaw = u.cost;
1834
+ const reportedUsd = num(costRaw) ?? (costRaw && typeof costRaw === "object" ? num(costRaw.total) ?? num(costRaw.totalCost) : void 0);
1807
1835
  return {
1808
1836
  input,
1809
1837
  output,
1810
- usd: num(costRaw) ?? (costRaw && typeof costRaw === "object" ? num(costRaw.totalCost) ?? 0 : 0)
1838
+ ...reportedUsd !== void 0 && reportedUsd > 0 ? { usd: reportedUsd } : {}
1839
+ };
1840
+ }
1841
+ function readAssistantOutcome(message) {
1842
+ if (!message || typeof message !== "object") return void 0;
1843
+ const value = message;
1844
+ if (value.role !== "assistant") return void 0;
1845
+ return {
1846
+ text: readText(message) ?? "",
1847
+ ...typeof value.stopReason === "string" ? { stopReason: value.stopReason } : {},
1848
+ ...typeof value.errorMessage === "string" ? { errorMessage: value.errorMessage } : {}
1811
1849
  };
1812
1850
  }
1813
1851
  function readText(message) {
@@ -1819,7 +1857,7 @@ function readText(message) {
1819
1857
  return text.length > 0 ? text : void 0;
1820
1858
  }
1821
1859
  function num(v) {
1822
- return typeof v === "number" && Number.isFinite(v) ? v : void 0;
1860
+ return typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : void 0;
1823
1861
  }
1824
1862
  function describeArgs$1(argsValue) {
1825
1863
  if (!argsValue || typeof argsValue !== "object") return void 0;
@@ -1837,6 +1875,18 @@ function describeArgs$1(argsValue) {
1837
1875
  if (typeof v === "string" && v.length > 0) return v.length > 120 ? `${v.slice(0, 117)}...` : v;
1838
1876
  }
1839
1877
  }
1878
+ function describeToolError(result) {
1879
+ if (typeof result === "string" && result.length > 0) return result;
1880
+ if (result && typeof result === "object") {
1881
+ const value = result;
1882
+ const direct = value.error ?? value.message;
1883
+ if (typeof direct === "string" && direct.length > 0) return direct;
1884
+ if (Array.isArray(value.content)) {
1885
+ const text = value.content.map((block) => block && typeof block === "object" && typeof block.text === "string" ? block.text : "").filter(Boolean).join("\n");
1886
+ if (text.length > 0) return text;
1887
+ }
1888
+ }
1889
+ }
1840
1890
  function taskText(task) {
1841
1891
  if (typeof task === "string") return task;
1842
1892
  try {
@@ -1901,6 +1951,8 @@ function readJsonLines(proc, onValue) {
1901
1951
  * Without it the SIGTERM races the command down the pipe and pi never sees the abort at all —
1902
1952
  * which defeats the reason to wrap pi rather than kill it (a clean abort finalizes its session). */
1903
1953
  const PI_ABORT_GRACE_MS = 500;
1954
+ /** Maximum wait for Pi's aborted receipt and `agent_settled` before forced teardown. */
1955
+ const PI_ABORT_RECEIPT_MS = 2e3;
1904
1956
  async function killPi(proc, grace) {
1905
1957
  if (proc.exitCode !== null || proc.killed) return { destroyed: true };
1906
1958
  if (grace === "brutalKill") {
@@ -3920,6 +3972,7 @@ const coordinationVerbNames = [
3920
3972
  "list_questions",
3921
3973
  "answer_question",
3922
3974
  "ask_parent",
3975
+ "submit_result",
3923
3976
  "stop",
3924
3977
  "list_analysts",
3925
3978
  "run_analyst"
@@ -3930,8 +3983,10 @@ const idArg = {
3930
3983
  };
3931
3984
  /** Build the driver's MCP tools over a live scope. */
3932
3985
  function createCoordinationTools(opts) {
3986
+ const deliverable = opts.deliverable;
3933
3987
  let stopped = false;
3934
3988
  let reason;
3989
+ let submitted;
3935
3990
  let questionSeq = 0;
3936
3991
  const ledger = [];
3937
3992
  const questions = [...opts.priorQuestions ?? []];
@@ -4572,6 +4627,53 @@ function createCoordinationTools(opts) {
4572
4627
  })) };
4573
4628
  }
4574
4629
  },
4630
+ ...deliverable ? [{
4631
+ name: "submit_result",
4632
+ description: [
4633
+ "Submit the complete result to the injected independent check.",
4634
+ "The first passing result is retained; stop work when accepted.",
4635
+ ...deliverable.describe ? [`Expected result: ${deliverable.describe}`] : []
4636
+ ].join(" "),
4637
+ inputSchema: {
4638
+ type: "object",
4639
+ properties: { result: { description: "The complete result in the form requested by the task." } },
4640
+ required: ["result"],
4641
+ additionalProperties: false
4642
+ },
4643
+ handler: async (raw) => {
4644
+ if (submitted) return {
4645
+ accepted: true,
4646
+ retained: "earlier-passing-result",
4647
+ stop: true
4648
+ };
4649
+ const a = obj(raw);
4650
+ if (!Object.hasOwn(a, "result")) throw new Error("submit_result: \"result\" is required");
4651
+ const result = structuredClone(a.result);
4652
+ let accepted = false;
4653
+ try {
4654
+ accepted = await deliverable.check(result) === true;
4655
+ } catch {
4656
+ accepted = false;
4657
+ }
4658
+ if (!accepted) return {
4659
+ accepted: false,
4660
+ stop: false
4661
+ };
4662
+ if (submitted) return {
4663
+ accepted: true,
4664
+ retained: "earlier-passing-result",
4665
+ stop: true
4666
+ };
4667
+ submitted = Object.freeze({ result });
4668
+ stopped = true;
4669
+ reason = "result-accepted";
4670
+ return {
4671
+ accepted: true,
4672
+ retained: "this-result",
4673
+ stop: true
4674
+ };
4675
+ }
4676
+ }] : [],
4575
4677
  {
4576
4678
  name: "stop",
4577
4679
  description: "Declare the run complete.",
@@ -4641,6 +4743,7 @@ function createCoordinationTools(opts) {
4641
4743
  stats: () => bus.stats(),
4642
4744
  isStopped: () => stopped,
4643
4745
  stopReason: () => reason,
4746
+ submittedResult: () => submitted,
4644
4747
  settled: () => ledger,
4645
4748
  questions: () => questions,
4646
4749
  drainResolved
@@ -5113,6 +5216,7 @@ function driverAgent(opts) {
5113
5216
  blobs: opts.blobs,
5114
5217
  makeWorkerAgent: opts.makeWorkerAgent,
5115
5218
  perWorker: opts.perWorker,
5219
+ ...opts.deliverable ? { deliverable: opts.deliverable } : {},
5116
5220
  ...opts.maxLiveWorkers !== void 0 ? { maxLiveWorkers: opts.maxLiveWorkers } : {},
5117
5221
  ...opts.analysts ? { analysts: opts.analysts } : {},
5118
5222
  ...opts.analyzeOnSettle ? { analyzeOnSettle: opts.analyzeOnSettle } : {},
@@ -5234,6 +5338,8 @@ function driverAgent(opts) {
5234
5338
  } }
5235
5339
  });
5236
5340
  await coord.drainResolved();
5341
+ const submitted = coord.submittedResult();
5342
+ if (submitted) return submitted.result;
5237
5343
  return runFinalizer(opts.finalizer ?? bestDelivered, {
5238
5344
  settled: coord.settled(),
5239
5345
  blobs: opts.blobs,
@@ -7242,6 +7348,7 @@ async function serveCoordinationMcp(opts) {
7242
7348
  blobs: opts.blobs,
7243
7349
  makeWorkerAgent: opts.makeWorkerAgent,
7244
7350
  perWorker: opts.perWorker,
7351
+ ...opts.deliverable ? { deliverable: opts.deliverable } : {},
7245
7352
  ...opts.maxLiveWorkers !== void 0 ? { maxLiveWorkers: opts.maxLiveWorkers } : {},
7246
7353
  awaitTimeoutMs: opts.awaitTimeoutMs ?? 15e3,
7247
7354
  ...opts.analysts ? { analysts: opts.analysts } : {},
@@ -7303,6 +7410,7 @@ async function serveCoordinationMcp(opts) {
7303
7410
  url: `http://${host}:${port}/mcp`,
7304
7411
  port,
7305
7412
  settled: () => coord.settled(),
7413
+ submittedResult: () => coord.submittedResult(),
7306
7414
  drainResolved: () => coord.drainResolved(),
7307
7415
  isStopped: () => coord.isStopped(),
7308
7416
  history: () => coord.history(),
@@ -7327,9 +7435,8 @@ async function serveCoordinationMcp(opts) {
7327
7435
  * coordination verbs: `serveCoordinationMcp` exposes spawn/await/steer/stop over the live scope,
7328
7436
  * and the caller's `driveHarness` runs the harness with that MCP mounted. The harness IS the brain.
7329
7437
  *
7330
- * Both arms spawn children through the SAME `makeWorkerAgent` seam and finalize through the SAME
7331
- * seam (`runFinalizer` over DELIVERED children only default keep-best, never the driver's own
7332
- * prose).
7438
+ * Both arms spawn children through the SAME `makeWorkerAgent` seam and apply the SAME independent
7439
+ * deliverable check to direct submissions. Raw driver prose is never eligible.
7333
7440
  */
7334
7441
  /** The standing strategy a router-brained supervisor runs with when its profile names no
7335
7442
  * `systemPrompt`. The brain's competence IS this prompt: without it the brain has the coordination
@@ -7365,6 +7472,7 @@ function supervisorAgent(profile, deps) {
7365
7472
  makeWorkerAgent: deps.makeWorkerAgent,
7366
7473
  perWorker: deps.perWorker,
7367
7474
  systemPrompt,
7475
+ ...deps.deliverable ? { deliverable: deps.deliverable } : {},
7368
7476
  ...deps.maxLiveWorkers !== void 0 ? { maxLiveWorkers: deps.maxLiveWorkers } : {},
7369
7477
  ...deps.extraTools ? { extraTools: deps.extraTools } : {},
7370
7478
  ...deps.executeExtraTool ? { executeExtraTool: deps.executeExtraTool } : {},
@@ -7390,6 +7498,7 @@ function supervisorAgent(profile, deps) {
7390
7498
  blobs: deps.blobs,
7391
7499
  makeWorkerAgent: deps.makeWorkerAgent,
7392
7500
  perWorker: deps.perWorker,
7501
+ ...deps.deliverable ? { deliverable: deps.deliverable } : {},
7393
7502
  ...deps.maxLiveWorkers !== void 0 ? { maxLiveWorkers: deps.maxLiveWorkers } : {},
7394
7503
  ...deps.analysts ? { analysts: deps.analysts } : {},
7395
7504
  ...deps.analyzeOnSettle ? { analyzeOnSettle: deps.analyzeOnSettle } : {},
@@ -7399,13 +7508,19 @@ function supervisorAgent(profile, deps) {
7399
7508
  ...deps.priorCoordination?.questions.length ? { priorQuestions: deps.priorCoordination.questions } : {}
7400
7509
  });
7401
7510
  try {
7402
- await driveHarness({
7403
- profile,
7404
- task,
7405
- scope,
7406
- coordinationMcpUrl: mcp.url
7407
- });
7511
+ try {
7512
+ await driveHarness({
7513
+ profile,
7514
+ task,
7515
+ scope,
7516
+ coordinationMcpUrl: mcp.url
7517
+ });
7518
+ } catch (error) {
7519
+ if (!mcp.submittedResult()) throw error;
7520
+ }
7408
7521
  await mcp.drainResolved();
7522
+ const submitted = mcp.submittedResult();
7523
+ if (submitted) return submitted.result;
7409
7524
  return await runFinalizer(deps.finalizer ?? bestDelivered, {
7410
7525
  settled: mcp.settled(),
7411
7526
  blobs: deps.blobs,
@@ -7485,6 +7600,7 @@ function supervise(profile, task, opts) {
7485
7600
  blobs,
7486
7601
  makeWorkerAgent: workerFactory,
7487
7602
  perWorker,
7603
+ ...opts.deliverable ? { deliverable: opts.deliverable } : {},
7488
7604
  ...log ? { onEvent: (ev) => log.append(runId, ev, new Date(now()).toISOString()) } : {},
7489
7605
  ...priorCoordination && (priorCoordination.questions.length > 0 || priorCoordination.findings.length > 0) ? { priorCoordination } : {},
7490
7606
  ...opts.finalizer ? { finalizer: opts.finalizer } : {},
@@ -7520,4 +7636,4 @@ function supervise(profile, task, opts) {
7520
7636
  //#endregion
7521
7637
  export { eventToSnapshot as $, createDelegateHandler as A, createSteerableSandboxSession as At, DelegationTaskQueue as B, runAgentRounds as Bt, DELEGATE_FEEDBACK_INPUT_SCHEMA as C, createFileRunContext as Ct, DELEGATE_DESCRIPTION as D, createExecutorRegistry as Dt, validateDelegateFeedbackArgs as E, createExecutor as Et, assessAuthoredProfile as F, decodeToolPart as Ft, capDelegationTrace as G, FileCoordinationLog as Gt, DELEGATION_TRACE_MAX_BYTES as H, createSandboxLineage as Ht, authoredWorker as I, sandboxSessionTraceSource as It, DelegationPersistenceError as J, composeLoopTraceEmitters as K, assertModelAllowed as Kt, defaultProfileRichnessThresholds as L, createInbox as Lt, defaultDelegateBudget as M, piExecutor as Mt, delegate as N, piSeamKey as Nt, DELEGATE_INPUT_SCHEMA as O, createWorktreeCliExecutor as Ot, asAuthoredProfile as P, createPushTraceSource as Pt, InMemoryFeedbackStore as Q, profileRichnessFinding as R, createSandboxForSpec as Rt, DELEGATE_FEEDBACK_DESCRIPTION as S, watchTrace as St, createDelegateFeedbackHandler as T, cliWorktreeExecutor as Tt, DELEGATION_TRACE_MAX_SPANS as U, probeSandboxCapabilities as Ut, hashIdempotencyInput as V, runLoop as Vt, buildDelegationTraceSpans as W, acquireSandbox as Wt, FileDelegationStore as X, DelegationStateCorruptError as Y, InMemoryDelegationStore as Z, DELEGATE_UI_AUDIT_DESCRIPTION as _, effectiveConcurrency as _t, createInProcessTransport as a, createProgressTracker as at, createDelegateUiAuditHandler as b, rollingDispatch as bt, DELEGATION_STATUS_INPUT_SCHEMA as c, sampleFromSettled as ct, validateDelegationStatusArgs as d, bestSoFar as dt, driverAgent as et, DELEGATION_HISTORY_DESCRIPTION as f, plateauLength as ft, validateDelegationHistoryArgs as g, createEventBus as gt, createDelegationHistoryHandler as h, createCoordinationTools as ht, serveCoordinationMcp as i, anyOf as it, validateDelegateArgs as j, PI_RUNTIME as jt, DELEGATE_TOOL_NAME as k, DEFAULT_SANDBOX_STEERING_MAX_TURNS as kt, DELEGATION_STATUS_TOOL_NAME as l, anytimeReport as lt, DELEGATION_HISTORY_TOOL_NAME as m, DEFAULT_AWAIT_EVENT_TIMEOUT_MS as mt, workerFromBackend as n, allOf as nt, createMcpServer as o, noProgressFor as ot, DELEGATION_HISTORY_INPUT_SCHEMA as p, renderAnytimeTable as pt, createDelegationTraceCollector as q, gateOnDeliverable as qt, supervisorAgent as r, allWorkersStalled as rt, DELEGATION_STATUS_DESCRIPTION as s, plateau as st, supervise as t, finalizeBestDelivered as tt, createDelegationStatusHandler as u, areaUnderCurve as ut, DELEGATE_UI_AUDIT_INPUT_SCHEMA as v, freeSlots as vt, DELEGATE_FEEDBACK_TOOL_NAME as w, createInMemoryRunContext as wt, validateDelegateUiAuditArgs as x, defaultToolDetectors as xt, DELEGATE_UI_AUDIT_TOOL_NAME as y, queueOf as yt, supervisorInstructions as z, defaultSelectWinner as zt };
7522
7638
 
7523
- //# sourceMappingURL=supervise-DyPmmhJ6.js.map
7639
+ //# sourceMappingURL=supervise-CeZtA1wu.js.map