@tangle-network/agent-runtime 0.39.0 → 0.41.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 (37) hide show
  1. package/README.md +265 -69
  2. package/dist/{chunk-AXWGLYSF.js → chunk-4GI7C36B.js} +3 -3
  3. package/dist/{chunk-VLXRXMTF.js → chunk-FJ4GDNVN.js} +5 -4
  4. package/dist/chunk-FJ4GDNVN.js.map +1 -0
  5. package/dist/{chunk-HSX6PFZR.js → chunk-HVYOHJHK.js} +338 -2
  6. package/dist/chunk-HVYOHJHK.js.map +1 -0
  7. package/dist/chunk-NRZOXCJK.js +64 -0
  8. package/dist/chunk-NRZOXCJK.js.map +1 -0
  9. package/dist/{chunk-7JBDJQLO.js → chunk-OISRXLWI.js} +8 -3
  10. package/dist/chunk-OISRXLWI.js.map +1 -0
  11. package/dist/{chunk-PK5DYSNO.js → chunk-WSJJGSD3.js} +51 -5
  12. package/dist/chunk-WSJJGSD3.js.map +1 -0
  13. package/dist/{dynamic-DcrwVGuV.d.ts → dynamic-CazTl_Zp.d.ts} +3 -1
  14. package/dist/index.d.ts +4 -4
  15. package/dist/index.js +9 -8
  16. package/dist/index.js.map +1 -1
  17. package/dist/{kb-gate-YdPNEagq.d.ts → kb-gate-NzOJSnOk.d.ts} +9 -1
  18. package/dist/{loop-runner-bin-DgZj0zfJ.d.ts → loop-runner-bin-DYRzk2cT.d.ts} +3 -3
  19. package/dist/loop-runner-bin.d.ts +4 -4
  20. package/dist/loop-runner-bin.js +3 -3
  21. package/dist/loops.d.ts +4 -4
  22. package/dist/loops.js +1 -1
  23. package/dist/mcp/bin.js +28 -17
  24. package/dist/mcp/bin.js.map +1 -1
  25. package/dist/mcp/index.d.ts +3 -3
  26. package/dist/mcp/index.js +9 -49
  27. package/dist/mcp/index.js.map +1 -1
  28. package/dist/profiles.d.ts +1 -1
  29. package/dist/{types-B9O7l-ij.d.ts → types-BrJKXXI8.d.ts} +8 -1
  30. package/package.json +1 -1
  31. package/dist/chunk-7JBDJQLO.js.map +0 -1
  32. package/dist/chunk-7ZECSZ3C.js +0 -400
  33. package/dist/chunk-7ZECSZ3C.js.map +0 -1
  34. package/dist/chunk-HSX6PFZR.js.map +0 -1
  35. package/dist/chunk-PK5DYSNO.js.map +0 -1
  36. package/dist/chunk-VLXRXMTF.js.map +0 -1
  37. /package/dist/{chunk-AXWGLYSF.js.map → chunk-4GI7C36B.js.map} +0 -0
@@ -45,7 +45,12 @@ function createDynamicDriver(options) {
45
45
  },
46
46
  describePlan() {
47
47
  if (!pending) return void 0;
48
- return pending.rationale !== void 0 ? { kind: pending.kind, rationale: pending.rationale } : { kind: pending.kind };
48
+ const out = { kind: pending.kind };
49
+ if (pending.rationale !== void 0) out.rationale = pending.rationale;
50
+ if (pending.kind !== "stop" && pending.parentIndex !== void 0) {
51
+ out.parentIndex = pending.parentIndex;
52
+ }
53
+ return out;
49
54
  }
50
55
  };
51
56
  }
@@ -339,7 +344,7 @@ async function runLoop(options) {
339
344
  const baseIndex = iterations.length;
340
345
  const remaining = maxIterations - iterations.length;
341
346
  const slice = planned.slice(0, remaining);
342
- const parentIndex = roundIndex === 0 ? void 0 : branchPoint(iterations);
347
+ const parentIndex = planDesc?.parentIndex ?? (roundIndex === 0 ? void 0 : branchPoint(iterations));
343
348
  const childIndices = slice.map((_, i) => baseIndex + i);
344
349
  await emitTrace(options.ctx.traceEmitter, {
345
350
  kind: "loop.plan",
@@ -765,4 +770,4 @@ export {
765
770
  loopDispatch,
766
771
  loopCampaignDispatch
767
772
  };
768
- //# sourceMappingURL=chunk-7JBDJQLO.js.map
773
+ //# sourceMappingURL=chunk-OISRXLWI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/loops/drivers/dynamic.ts","../src/loops/drivers/refine.ts","../src/loops/drivers/sandbox-planner.ts","../src/loops/report-usage.ts","../src/loops/run-loop.ts","../src/loops/loop-dispatch.ts"],"sourcesContent":["/**\n * @experimental\n *\n * Dynamic driver — the agent authors the loop topology at runtime.\n *\n * Where `refine` and `fanout-vote` encode a fixed shape as a pure function of\n * history, this driver delegates the per-round shape to an injected\n * `TopologyPlanner`. Each round the planner inspects the task + iteration\n * history and emits one `TopologyMove`:\n * - `refine` → one task next round (optionally rewritten from the prior attempt)\n * - `fanout` → N tasks next round (the kernel round-robins `agentRuns`, so a\n * 2-harness fanout dispatches branch 0 to harness A and branch 1 to harness B)\n * - `stop` → terminate; the kernel selects the winner across all iterations\n *\n * The planner is the brain; this driver is the structure. It maps moves onto\n * the kernel's `plan`/`decide` contract, enforces the iteration + fanout caps,\n * and fails loud on a malformed move. The planner is injected exactly like\n * `refine`'s `refineTask` and `fanout-vote`'s `selector` — so a test can drive\n * a deterministic policy through the real kernel, and production can wire it to\n * an LLM via `createSandboxPlanner`.\n *\n * Topology is orthogonal to harness: the planner never names a backend. Which\n * harness runs a branch is decided by the `AgentRunSpec` the kernel round-robins\n * to, so one dynamic driver works across claude-code, codex, opencode, pi —\n * including fanning a single round across several at once.\n */\n\nimport { PlannerError, ValidationError } from '../../errors'\nimport type { Driver, Iteration } from '../types'\n\n/** Terminal once `decide` returns `'done'` (a kernel terminal decision). */\nexport type DynamicDecision = 'continue' | 'done'\n\n/**\n * One topology decision for the next round. `fanout` carries explicit tasks\n * rather than a count so the planner can issue heterogeneous branches (a\n * different sub-task per harness); pass N copies of one task for a homogeneous\n * fanout that relies on `agentRuns` diversity instead.\n *\n * @experimental\n */\nexport type TopologyMove<Task> =\n | { kind: 'refine'; task: Task; rationale?: string; parentIndex?: number }\n | { kind: 'fanout'; tasks: Task[]; rationale?: string; parentIndex?: number }\n | { kind: 'stop'; rationale?: string }\n\n/** @experimental */\nexport interface PlannerContext<Task, Output> {\n /** The root task the loop was invoked with — stable across rounds. */\n task: Task\n /** Every iteration so far, in dispatch order, with outputs + verdicts. */\n history: ReadonlyArray<Iteration<Task, Output>>\n /** `history.length` — iterations already spent. */\n iterationsSpent: number\n /** Iterations left before the driver's `maxIterations` cap forces a stop. */\n iterationsRemaining: number\n}\n\n/**\n * Chooses the next topology move from the task + history. Sync or async; an\n * async planner is where an LLM call goes (see `createSandboxPlanner`).\n *\n * @experimental\n */\nexport type TopologyPlanner<Task, Output> = (\n ctx: PlannerContext<Task, Output>,\n) => TopologyMove<Task> | Promise<TopologyMove<Task>>\n\n/** @experimental */\nexport interface CreateDynamicDriverOptions<Task, Output> {\n /** The agent-authored topology policy. Invoked once per round in `plan`. */\n planner: TopologyPlanner<Task, Output>\n /**\n * Hard safety cap on total iterations. When reached, the driver stops before\n * consulting the planner. Default 8. Set the kernel's `runLoop`\n * `maxIterations >= ` this so the driver's cap governs and the loop closes on\n * a clean `'done'` rather than a truncated `'continue'`.\n */\n maxIterations?: number\n /** Max branches a single `fanout` move may dispatch. Default 4. */\n maxFanout?: number\n /** Stable identifier surfaced in trace events. Default `'dynamic'`. */\n name?: string\n}\n\n/** @experimental */\nexport function createDynamicDriver<Task, Output>(\n options: CreateDynamicDriverOptions<Task, Output>,\n): Driver<Task, Output, DynamicDecision> {\n if (typeof options.planner !== 'function') {\n throw new ValidationError('createDynamicDriver: planner must be a function')\n }\n const maxIterations = options.maxIterations ?? 8\n if (!Number.isFinite(maxIterations) || maxIterations <= 0) {\n throw new ValidationError('createDynamicDriver: maxIterations must be > 0')\n }\n const maxFanout = options.maxFanout ?? 4\n if (!Number.isFinite(maxFanout) || maxFanout < 1) {\n throw new ValidationError('createDynamicDriver: maxFanout must be >= 1')\n }\n\n // The kernel calls plan(), runs the batch, then calls decide() — strictly\n // sequential, one driver instance per loop. Caching the move the planner\n // chose this round lets decide() report terminality without re-invoking the\n // planner (which would double every LLM call).\n let pending: TopologyMove<Task> | undefined\n\n return {\n name: options.name ?? 'dynamic',\n async plan(task, history) {\n if (history.length >= maxIterations) {\n pending = { kind: 'stop', rationale: `maxIterations (${maxIterations}) reached` }\n return []\n }\n const move = await options.planner({\n task,\n history,\n iterationsSpent: history.length,\n iterationsRemaining: maxIterations - history.length,\n })\n pending = validateMove(move, maxFanout)\n switch (pending.kind) {\n case 'refine':\n return [pending.task]\n case 'fanout':\n return pending.tasks\n case 'stop':\n return []\n }\n },\n decide() {\n // pending is set by the plan() call that immediately precedes every\n // decide(). Only a `stop` move terminates; refine/fanout keep looping so\n // plan() — and thus the planner — runs again next round.\n return pending?.kind === 'stop' ? 'done' : 'continue'\n },\n describePlan() {\n // Surface the move the planner just chose (kind + rationale + an optional\n // DECLARED branch source) so the kernel's loop.plan trace carries the\n // agent's intent — including faithful edge lineage when the planner\n // branched off a specific (non-winner) iteration. `pending` is the move\n // set by the preceding plan().\n if (!pending) return undefined\n const out: { kind: string; rationale?: string; parentIndex?: number } = { kind: pending.kind }\n if (pending.rationale !== undefined) out.rationale = pending.rationale\n if (pending.kind !== 'stop' && pending.parentIndex !== undefined) {\n out.parentIndex = pending.parentIndex\n }\n return out\n },\n }\n}\n\nfunction validateMove<Task>(move: TopologyMove<Task>, maxFanout: number): TopologyMove<Task> {\n if (!move || typeof move !== 'object' || typeof (move as { kind?: unknown }).kind !== 'string') {\n throw new PlannerError(`dynamic planner returned a non-move value: ${describe(move)}`)\n }\n switch (move.kind) {\n case 'refine':\n return move\n case 'stop':\n return move\n case 'fanout': {\n if (!Array.isArray(move.tasks) || move.tasks.length === 0) {\n throw new PlannerError('dynamic planner fanout move must carry a non-empty tasks[]')\n }\n if (move.tasks.length <= maxFanout) return move\n // Clamp rather than reject — over-fanning is a budget concern, not a\n // structural error. The clamp is recorded in the rationale for traces.\n return {\n kind: 'fanout',\n tasks: move.tasks.slice(0, maxFanout),\n rationale: `${move.rationale ?? ''} [clamped ${move.tasks.length}→${maxFanout}]`.trim(),\n }\n }\n default:\n throw new PlannerError(\n `dynamic planner returned unknown move kind: ${describe((move as { kind: unknown }).kind)}`,\n )\n }\n}\n\nfunction describe(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value)\n } catch {\n return String(value)\n }\n}\n\n/**\n * Compact, planner-friendly view of iteration history — what an LLM planner\n * needs to choose the next move without the raw event streams. Output is\n * truncated so a long run's prompt stays bounded.\n *\n * @experimental\n */\nexport function summarizeHistory<Task, Output>(\n history: ReadonlyArray<Iteration<Task, Output>>,\n opts: { maxOutputChars?: number } = {},\n): Array<{\n index: number\n agentRunName: string\n valid?: boolean\n score?: number\n error?: string\n output?: string\n}> {\n const maxOutputChars = opts.maxOutputChars ?? 600\n return history.map((iter) => {\n const row: {\n index: number\n agentRunName: string\n valid?: boolean\n score?: number\n error?: string\n output?: string\n } = { index: iter.index, agentRunName: iter.agentRunName }\n if (iter.verdict) {\n row.valid = iter.verdict.valid\n if (typeof iter.verdict.score === 'number') row.score = iter.verdict.score\n }\n if (iter.error) row.error = iter.error.message\n if (iter.output !== undefined) {\n const serialized = describe(iter.output)\n row.output =\n serialized.length > maxOutputChars ? `${serialized.slice(0, maxOutputChars)}…` : serialized\n }\n return row\n })\n}\n","/**\n * @experimental\n *\n * Refine driver — single task per iteration, validator-gated.\n *\n * `plan` returns `[task]` (possibly transformed via `refineTask`) until the\n * prior verdict is valid OR the local cap is hit, then `[]`.\n * `decide` returns `'stop'` once the latest verdict is valid OR the cap is\n * reached. The kernel's `maxIterations` is an orthogonal safety cap;\n * whichever is lower wins.\n */\n\nimport { ValidationError } from '../../errors'\nimport type { DefaultVerdict, Driver, Iteration } from '../types'\n\nexport type RefineDecision = 'continue' | 'stop'\n\n/** @experimental */\nexport interface CreateRefineDriverOptions<Task> {\n /** Hard cap on iterations. Default 5. */\n maxIterations?: number\n /**\n * Optional task transform applied each round based on the prior verdict.\n * When omitted, the same task is replayed and the agent is expected to\n * inspect the sandbox session state for prior attempts.\n */\n refineTask?: (task: Task, prior: DefaultVerdict) => Task\n /** Stable identifier surfaced in trace events. Default `'refine'`. */\n name?: string\n}\n\n/** @experimental */\nexport function createRefineDriver<Task, Output>(\n options: CreateRefineDriverOptions<Task> = {},\n): Driver<Task, Output, RefineDecision> {\n const maxIterations = options.maxIterations ?? 5\n if (!Number.isFinite(maxIterations) || maxIterations <= 0) {\n throw new ValidationError('createRefineDriver: maxIterations must be > 0')\n }\n const refineTask = options.refineTask\n return {\n name: options.name ?? 'refine',\n async plan(task, history) {\n if (history.length >= maxIterations) return []\n if (history.length === 0) return [task]\n const prior = history.at(-1)\n if (!prior) return [task]\n if (prior.verdict?.valid === true) return []\n // Worker error: replay the same task so the agent can self-correct.\n // The driver has no signal beyond `verdict`; only the validator\n // controls \"good enough\".\n if (!refineTask || !prior.verdict) return [prior.task]\n return [refineTask(prior.task, prior.verdict)]\n },\n decide(history) {\n const last = history.at(-1)\n if (!last) return 'continue'\n if (last.verdict?.valid === true) return 'stop'\n if (history.length >= maxIterations) return 'stop'\n return 'continue'\n },\n }\n}\n\n/**\n * Test helper: select the last-valid iteration (or the last attempt if\n * none passed). Mirrors the kernel's default selector ordering for refine\n * topologies — the most recent successful attempt wins.\n *\n * @experimental\n */\nexport function refineWinnerIndex<Task, Output>(\n iterations: ReadonlyArray<Iteration<Task, Output>>,\n): number | undefined {\n for (let i = iterations.length - 1; i >= 0; i -= 1) {\n if (iterations[i]?.verdict?.valid) return i\n }\n return iterations.length > 0 ? iterations.length - 1 : undefined\n}\n","/**\n * @experimental\n *\n * `createSandboxPlanner` — wire the dynamic driver's `TopologyPlanner` to a\n * real agent. Each round it spins a sandbox on `profile`, streams a prompt that\n * carries the history summary, and decodes the agent's chosen `TopologyMove`\n * from a JSON envelope it emits. This is the \"agent authors its own loop\n * topology\" path: the planner profile can be any harness (claude-code, codex,\n * opencode, pi) — its only job is to read what happened and emit the next move.\n *\n * The planner profile is deliberately distinct from the worker `agentRuns`: a\n * cheap fast model can steer topology while expensive workers do the labor, and\n * the planner never names which harness runs a branch — the kernel's\n * `agentRuns` round-robin decides that.\n *\n * Envelope contract the agent must emit (fenced ```json or a structured\n * `result`/`final` event payload):\n * { \"kind\": \"refine\" | \"fanout\" | \"stop\",\n * \"tasks\"?: [ <task>, ... ], // decoded via `decodeTask`\n * \"n\"?: number, // fanout shorthand: N copies of the root task\n * \"rationale\"?: string }\n *\n * A missing / unparseable / unknown-kind envelope throws `PlannerError` — the\n * loop never silently runs a topology the agent did not choose.\n */\n\nimport type {\n AgentProfile,\n CreateSandboxOptions,\n SandboxEvent,\n} from '@tangle-network/sandbox'\nimport { PlannerError, ValidationError } from '../../errors'\nimport type { AgentRunSpec, LoopSandboxClient } from '../types'\nimport type { PlannerContext, TopologyMove, TopologyPlanner } from './dynamic'\nimport { summarizeHistory } from './dynamic'\n\n/** Raw, pre-decode envelope an agent emits to choose the next move. */\nexport interface TopologyMoveEnvelope {\n kind: string\n tasks?: unknown[]\n n?: number\n rationale?: string\n}\n\n/** @experimental */\nexport interface CreateSandboxPlannerOptions<Task, Output> {\n /** Sandbox client — the planner calls `.create()` once per round. */\n client: LoopSandboxClient\n /** The planner agent. Steers topology; does not run the work. */\n profile: AgentProfile\n /**\n * Decode one raw task from the envelope's `tasks[]` into a domain `Task`.\n * Required because `Task` is opaque to this module — only the caller knows\n * its shape. Throw to reject a malformed task; the error surfaces as a\n * `PlannerError`.\n */\n decodeTask: (raw: unknown, ctx: PlannerContext<Task, Output>) => Task\n /** Override the default prompt (history summary + envelope contract). */\n buildPrompt?: (ctx: PlannerContext<Task, Output>) => string\n /** Override envelope extraction from the event stream. */\n parseEnvelope?: (events: SandboxEvent[]) => TopologyMoveEnvelope | undefined\n /** Sandbox overrides for the planner sandbox (timeouts, env, etc.). */\n sandboxOverrides?: AgentRunSpec<Task>['sandboxOverrides']\n /** Cancellation for the planner's own LLM call. */\n signal?: AbortSignal\n}\n\n/** @experimental */\nexport function createSandboxPlanner<Task, Output>(\n opts: CreateSandboxPlannerOptions<Task, Output>,\n): TopologyPlanner<Task, Output> {\n if (!opts.client || typeof opts.client.create !== 'function') {\n throw new ValidationError('createSandboxPlanner: client.create is required')\n }\n if (typeof opts.decodeTask !== 'function') {\n throw new ValidationError('createSandboxPlanner: decodeTask is required')\n }\n const buildPrompt = opts.buildPrompt ?? defaultBuildPrompt\n const parseEnvelope = opts.parseEnvelope ?? defaultParseEnvelope\n\n return async (ctx) => {\n const box = await opts.client.create(buildSandboxOptions(opts.profile, opts.sandboxOverrides))\n const events: SandboxEvent[] = []\n for await (const event of box.streamPrompt(buildPrompt(ctx), { signal: opts.signal })) {\n events.push(event)\n }\n const envelope = parseEnvelope(events)\n if (!envelope) {\n throw new PlannerError('sandbox planner emitted no parseable topology-move envelope')\n }\n return envelopeToMove(envelope, ctx, opts.decodeTask)\n }\n}\n\nfunction envelopeToMove<Task, Output>(\n envelope: TopologyMoveEnvelope,\n ctx: PlannerContext<Task, Output>,\n decodeTask: (raw: unknown, ctx: PlannerContext<Task, Output>) => Task,\n): TopologyMove<Task> {\n const kind = String(envelope.kind ?? '').toLowerCase()\n const rationale = typeof envelope.rationale === 'string' ? envelope.rationale : undefined\n if (kind === 'stop') {\n return { kind: 'stop', rationale }\n }\n if (kind === 'refine') {\n const raw = Array.isArray(envelope.tasks) ? envelope.tasks[0] : undefined\n // No new task → replay the root task; the worker self-corrects from its\n // own prior attempt in sandbox state, mirroring the refine driver default.\n const task = raw === undefined ? ctx.task : decodeTaskGuarded(decodeTask, raw, ctx)\n return { kind: 'refine', task, rationale }\n }\n if (kind === 'fanout') {\n const tasks = resolveFanoutTasks(envelope, ctx, decodeTask)\n return { kind: 'fanout', tasks, rationale }\n }\n throw new PlannerError(`sandbox planner emitted unknown move kind: ${JSON.stringify(envelope.kind)}`)\n}\n\nfunction resolveFanoutTasks<Task, Output>(\n envelope: TopologyMoveEnvelope,\n ctx: PlannerContext<Task, Output>,\n decodeTask: (raw: unknown, ctx: PlannerContext<Task, Output>) => Task,\n): Task[] {\n if (Array.isArray(envelope.tasks) && envelope.tasks.length > 0) {\n return envelope.tasks.map((raw) => decodeTaskGuarded(decodeTask, raw, ctx))\n }\n // `n` shorthand: N copies of the root task, leaning on `agentRuns` diversity.\n if (typeof envelope.n === 'number' && Number.isFinite(envelope.n) && envelope.n >= 1) {\n return Array.from({ length: Math.floor(envelope.n) }, () => ctx.task)\n }\n throw new PlannerError('sandbox planner fanout envelope needs a non-empty tasks[] or n >= 1')\n}\n\nfunction decodeTaskGuarded<Task, Output>(\n decodeTask: (raw: unknown, ctx: PlannerContext<Task, Output>) => Task,\n raw: unknown,\n ctx: PlannerContext<Task, Output>,\n): Task {\n try {\n return decodeTask(raw, ctx)\n } catch (err) {\n throw new PlannerError(`sandbox planner decodeTask rejected ${JSON.stringify(raw)}`, {\n cause: err,\n })\n }\n}\n\nfunction buildSandboxOptions(\n profile: AgentProfile,\n overrides: AgentRunSpec<unknown>['sandboxOverrides'],\n): CreateSandboxOptions {\n const base = overrides ?? {}\n const overrideBackend = base.backend\n const explicitType = profile.metadata?.backendType\n type BackendType = NonNullable<CreateSandboxOptions['backend']>['type']\n return {\n ...base,\n backend: {\n type: (overrideBackend?.type ?? explicitType ?? 'opencode') as BackendType,\n profile,\n ...(overrideBackend?.model ? { model: overrideBackend.model } : {}),\n ...(overrideBackend?.server ? { server: overrideBackend.server } : {}),\n },\n }\n}\n\nfunction defaultBuildPrompt<Task, Output>(ctx: PlannerContext<Task, Output>): string {\n const summary = summarizeHistory(ctx.history)\n return [\n 'You are the loop planner. You do not do the work — you decide the topology of the next round.',\n '',\n `Root task:\\n${safeJson(ctx.task)}`,\n '',\n `Iterations spent: ${ctx.iterationsSpent}. Remaining before the hard cap: ${ctx.iterationsRemaining}.`,\n '',\n ctx.history.length === 0\n ? 'No attempts yet.'\n : `Attempts so far (index, agent, verdict, output):\\n${safeJson(summary)}`,\n '',\n 'Choose ONE move and emit it as a fenced JSON block:',\n ' - {\"kind\":\"refine\",\"tasks\":[<task>],\"rationale\":\"...\"} — one more attempt; omit tasks to replay the root task.',\n ' - {\"kind\":\"fanout\",\"tasks\":[<task>,<task>],\"rationale\":\"...\"} — N parallel branches (or \"n\": N for N copies of the root task).',\n ' - {\"kind\":\"stop\",\"rationale\":\"...\"} — a valid result exists or further attempts will not help.',\n '',\n 'Stop as soon as an attempt is valid. Prefer refine when an attempt is close; fan out when attempts disagree or the approach is uncertain.',\n 'Emit ONLY the JSON block.',\n ].join('\\n')\n}\n\nfunction defaultParseEnvelope(events: SandboxEvent[]): TopologyMoveEnvelope | undefined {\n // Structured payload on a terminal event wins — sandbox SDKs lift emitted\n // JSON onto data.result / data.output / data of a result|final event.\n for (let i = events.length - 1; i >= 0; i -= 1) {\n const event = events[i]\n if (!event) continue\n const type = String(event.type ?? '')\n const data = isRecord(event.data) ? event.data : undefined\n if (!data) continue\n if (type === 'result' || type === 'final' || type === 'planner.move') {\n const direct = coerceEnvelope(data.result ?? data.output ?? data)\n if (direct) return direct\n }\n }\n // Fall back to a fenced JSON block in the most recent text delta.\n for (let i = events.length - 1; i >= 0; i -= 1) {\n const event = events[i]\n if (!event) continue\n const data = isRecord(event.data) ? event.data : undefined\n if (!data) continue\n const text = pickString(data.text) ?? pickString(data.delta) ?? pickString(data.content)\n if (!text) continue\n const fenced = extractFencedJson(text)\n const coerced = coerceEnvelope(fenced)\n if (coerced) return coerced\n }\n return undefined\n}\n\nfunction coerceEnvelope(value: unknown): TopologyMoveEnvelope | undefined {\n if (!isRecord(value)) return undefined\n if (typeof value.kind !== 'string' || value.kind.length === 0) return undefined\n const out: TopologyMoveEnvelope = { kind: value.kind }\n if (Array.isArray(value.tasks)) out.tasks = value.tasks\n if (typeof value.n === 'number') out.n = value.n\n if (typeof value.rationale === 'string') out.rationale = value.rationale\n return out\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction pickString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined\n}\n\nfunction extractFencedJson(text: string): unknown | undefined {\n const match = text.match(/```(?:json)?\\s*([\\s\\S]*?)```/i)\n const body = (match?.[1] ?? text).trim()\n if (!body) return undefined\n try {\n return JSON.parse(body)\n } catch {\n return undefined\n }\n}\n\nfunction safeJson(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2) ?? String(value)\n } catch {\n return String(value)\n }\n}\n","/**\n * Bridge a finished `runLoop` into an agent-eval campaign / profile-matrix\n * dispatch.\n *\n * `runProfileMatrix` (and `runCampaign`) run the backend-integrity guard over\n * the token usage a dispatch reports through `ctx.cost`. A dispatch that wraps\n * `runLoop` must forward the loop's cost AND token usage, or the guard reads\n * the run as a stub and throws. `reportLoopUsage` is that one line:\n *\n * const dispatch: ProfileDispatchFn<S, A> = async (profile, scenario, ctx) => {\n * const result = await runLoop({ ...optsFor(profile, scenario), ctx: loopCtx })\n * reportLoopUsage(ctx, result)\n * return result.winner?.output as A\n * }\n *\n * Typed structurally against the campaign `DispatchContext.cost` so this module\n * stays free of an agent-eval import — it works with any cost meter exposing\n * `observe` + `observeTokens`.\n */\n\nimport type { LoopResult } from './types'\n\n/** The slice of an agent-eval campaign `DispatchContext.cost` this needs. */\nexport interface UsageSink {\n observe(amountUsd: number, source: string): void\n observeTokens(usage: { input: number; output: number }): void\n}\n\n/**\n * Forward a `LoopResult`'s aggregated cost + token usage into a campaign cost\n * meter so the backend-integrity guard sees real LLM activity. `source`\n * defaults to `'loop'`.\n */\nexport function reportLoopUsage<Task, Output, Decision>(\n cost: UsageSink,\n result: Pick<LoopResult<Task, Output, Decision>, 'costUsd' | 'tokenUsage'>,\n source = 'loop',\n): void {\n cost.observe(result.costUsd, source)\n cost.observeTokens({ input: result.tokenUsage.input, output: result.tokenUsage.output })\n}\n","/**\n * @experimental\n *\n * `runLoop` — the topology-agnostic kernel built atop the sandbox SDK.\n *\n * Each iteration:\n * 1. `driver.plan(task, history)` → N tasks (1 = refine, N = fanout, 0 = stop)\n * 2. For each task (parallel, bounded by `maxConcurrency`):\n * a. round-robin an `AgentRunSpec` from `agentRuns`\n * b. `sandboxClient.create({ backend: { profile }, ...overrides })`\n * c. emit `loop.iteration.dispatch` with the placement\n * (`{ sibling, sandboxId }` or `{ fleet, fleetId, machineId, sandboxId }`)\n * d. iterate `box.streamPrompt(taskToPrompt(task))` and collect events\n * 3. `output.parse(events)` → typed `Output`\n * 4. `validator?.validate(output)` → `DefaultVerdict`\n * 5. Append `Iteration` to history; emit `loop.iteration.ended`\n * 6. `driver.decide(history)` → if terminal, return result + winner\n *\n * The kernel owns: iteration accounting, per-iteration timing, error\n * capture, abort propagation, concurrency cap, cost aggregation, and trace\n * emission. The kernel does NOT own: what the agent runs (sandbox SDK +\n * profile), how outputs are decoded (output adapter), how outputs are\n * scored (validator), or topology (driver).\n */\n\nimport type {\n AgentProfile,\n CreateSandboxOptions,\n SandboxEvent,\n SandboxInstance,\n} from '@tangle-network/sandbox'\nimport { ValidationError } from '../errors'\nimport type { RuntimeStreamEvent } from '../types'\nimport type {\n AgentRunSpec,\n Driver,\n ExecCtx,\n Iteration,\n LoopResult,\n LoopSandboxClient,\n LoopSandboxPlacement,\n LoopTraceEmitter,\n LoopTraceEvent,\n LoopWinner,\n OutputAdapter,\n Validator,\n} from './types'\n\nconst DEFAULT_MAX_ITERATIONS = 10\nconst DEFAULT_MAX_CONCURRENCY = 4\n\n/** @experimental */\nexport interface RunLoopOptions<Task, Output, Decision> {\n driver: Driver<Task, Output, Decision>\n /**\n * Single agent spec — every iteration uses this profile. Mutually\n * exclusive with `agentRuns`.\n */\n agentRun?: AgentRunSpec<Task>\n /**\n * Multiple specs for heterogeneous fanout. The kernel round-robins\n * through them when the driver plans N tasks. Mutually exclusive with\n * `agentRun`.\n */\n agentRuns?: AgentRunSpec<Task>[]\n output: OutputAdapter<Output>\n validator?: Validator<Output>\n task: Task\n ctx: ExecCtx\n /** Default 10. Hard cap on total iterations across all `plan()` rounds. */\n maxIterations?: number\n /** Default 4. In-flight worker cap within a single `plan()` batch. */\n maxConcurrency?: number\n /**\n * Pre-allocated id for trace correlation. Default = `loop-${random}`.\n * Surfaces as `runId` on every emitted `LoopTraceEvent`.\n */\n runId?: string\n /**\n * Clock override; default `Date.now`. Deterministic tests pass a\n * monotonic counter to stabilize iteration timing fields.\n */\n now?: () => number\n /**\n * Override the default winner selector (highest-valid-score, ties broken\n * by earliest iteration).\n */\n selectWinner?: (iterations: Iteration<Task, Output>[]) => LoopWinner<Task, Output> | undefined\n}\n\n/** @experimental */\nexport async function runLoop<Task, Output, Decision>(\n options: RunLoopOptions<Task, Output, Decision>,\n): Promise<LoopResult<Task, Output, Decision>> {\n const specs = resolveAgentRuns(options)\n const maxIterations = options.maxIterations ?? DEFAULT_MAX_ITERATIONS\n if (!Number.isFinite(maxIterations) || maxIterations <= 0) {\n throw new ValidationError('runLoop: maxIterations must be > 0')\n }\n const maxConcurrency = options.maxConcurrency ?? DEFAULT_MAX_CONCURRENCY\n if (!Number.isFinite(maxConcurrency) || maxConcurrency <= 0) {\n throw new ValidationError('runLoop: maxConcurrency must be > 0')\n }\n if (!options.ctx?.sandboxClient || typeof options.ctx.sandboxClient.create !== 'function') {\n throw new ValidationError('runLoop: ctx.sandboxClient.create is required')\n }\n const now = options.now ?? Date.now\n const runId = options.runId ?? `loop-${randomSuffix()}`\n const loopStart = now()\n const driverName = options.driver.name ?? 'driver'\n const iterations: Iteration<Task, Output>[] = []\n let round = 0\n\n await emitTrace(options.ctx.traceEmitter, {\n kind: 'loop.started',\n runId,\n timestamp: now(),\n payload: {\n driver: driverName,\n agentRunNames: specs.map((spec) => spec.name ?? spec.profile.name ?? 'agent'),\n maxIterations,\n maxConcurrency,\n },\n })\n\n const controller = new AbortController()\n const onOuterAbort = () => controller.abort()\n if (options.ctx.signal) {\n if (options.ctx.signal.aborted) controller.abort()\n else options.ctx.signal.addEventListener('abort', onOuterAbort, { once: true })\n }\n\n try {\n while (iterations.length < maxIterations) {\n if (controller.signal.aborted) throwAbort()\n const planned = await options.driver.plan(options.task, iterations)\n const planDesc = options.driver.describePlan?.()\n const roundIndex = round\n const baseIndex = iterations.length\n const remaining = maxIterations - iterations.length\n const slice = planned.slice(0, remaining)\n // Edge lineage: a driver may DECLARE the branch source (planner-authored\n // topology); otherwise the kernel infers it — round 0 branches from root\n // (undefined), later rounds from the best-valid (else latest) iteration so\n // far. Either way it's emitted, not guessed by the viewer.\n const parentIndex =\n planDesc?.parentIndex ?? (roundIndex === 0 ? undefined : branchPoint(iterations))\n const childIndices = slice.map((_, i) => baseIndex + i)\n await emitTrace(options.ctx.traceEmitter, {\n kind: 'loop.plan',\n runId,\n timestamp: now(),\n payload: {\n roundIndex,\n plannedCount: planned.length,\n moveKind:\n planDesc?.kind ??\n (planned.length === 0 ? 'stop' : planned.length === 1 ? 'refine' : 'fanout'),\n rationale: planDesc?.rationale,\n parentIndex,\n childIndices,\n },\n })\n round += 1\n if (planned.length === 0) break\n\n // Reserve slots up front so concurrent workers may mutate by index.\n for (let i = 0; i < slice.length; i += 1) {\n const spec = specs[(baseIndex + i) % specs.length]!\n iterations.push({\n index: baseIndex + i,\n task: slice[i] as Task,\n agentRunName: spec.name ?? spec.profile.name ?? 'agent',\n events: [],\n startedAt: now(),\n endedAt: 0,\n costUsd: 0,\n tokenUsage: { input: 0, output: 0 },\n })\n }\n\n await runBatch({\n slice,\n baseIndex,\n iterations,\n specs,\n output: options.output,\n validator: options.validator,\n maxConcurrency,\n signal: controller.signal,\n ctx: options.ctx,\n runId,\n now,\n roundIndex,\n parentIndex,\n })\n\n if (controller.signal.aborted) throwAbort()\n\n const decision = await options.driver.decide(iterations)\n await emitTrace(options.ctx.traceEmitter, {\n kind: 'loop.decision',\n runId,\n timestamp: now(),\n payload: { decision: serializeDecision(decision), historyLength: iterations.length },\n })\n if (isTerminalDecision(decision)) {\n return finalize({\n options,\n decision,\n iterations,\n startMs: loopStart,\n now,\n runId,\n })\n }\n }\n\n if (iterations.length >= maxIterations) {\n // Cap reached without a terminal decision — ask the driver one more time\n // for its final state, then close out.\n const decision = await options.driver.decide(iterations)\n await emitTrace(options.ctx.traceEmitter, {\n kind: 'loop.decision',\n runId,\n timestamp: now(),\n payload: { decision: serializeDecision(decision), historyLength: iterations.length },\n })\n return finalize({ options, decision, iterations, startMs: loopStart, now, runId })\n }\n // `plan()` returned `[]` before `decide()` reached a terminal state.\n const decision = await options.driver.decide(iterations)\n await emitTrace(options.ctx.traceEmitter, {\n kind: 'loop.decision',\n runId,\n timestamp: now(),\n payload: { decision: serializeDecision(decision), historyLength: iterations.length },\n })\n return finalize({ options, decision, iterations, startMs: loopStart, now, runId })\n } finally {\n if (options.ctx.signal) options.ctx.signal.removeEventListener('abort', onOuterAbort)\n }\n}\n\ninterface RunBatchArgs<Task, Output> {\n slice: Task[]\n baseIndex: number\n iterations: Iteration<Task, Output>[]\n specs: AgentRunSpec<Task>[]\n output: OutputAdapter<Output>\n validator: Validator<Output> | undefined\n maxConcurrency: number\n signal: AbortSignal\n ctx: ExecCtx\n runId: string\n now: () => number\n /** Plan round these iterations belong to — stamped as `groupId`. */\n roundIndex: number\n /** Iteration this round branched from — stamped as `parentIndex`. */\n parentIndex?: number\n}\n\nasync function runBatch<Task, Output>(args: RunBatchArgs<Task, Output>) {\n const queue = args.slice.map((task, offset) => ({ task, index: args.baseIndex + offset }))\n const inflight = new Set<Promise<void>>()\n while (queue.length > 0 || inflight.size > 0) {\n while (inflight.size < args.maxConcurrency && queue.length > 0) {\n const item = queue.shift()!\n const p = executeIteration({ ...args, item }).finally(() => inflight.delete(p))\n inflight.add(p)\n }\n if (inflight.size === 0) break\n await Promise.race(inflight)\n }\n}\n\ninterface ExecuteIterationArgs<Task, Output> extends RunBatchArgs<Task, Output> {\n item: { task: Task; index: number }\n}\n\nasync function executeIteration<Task, Output>(args: ExecuteIterationArgs<Task, Output>) {\n const slot = args.iterations[args.item.index]\n if (!slot)\n throw new ValidationError(`runLoop: missing iteration slot at index ${args.item.index}`)\n const spec = args.specs[args.item.index % args.specs.length]\n if (!spec) throw new ValidationError('runLoop: no AgentRunSpec available for iteration')\n slot.startedAt = args.now()\n slot.agentRunName = spec.name ?? spec.profile.name ?? 'agent'\n\n await emitTrace(args.ctx.traceEmitter, {\n kind: 'loop.iteration.started',\n runId: args.runId,\n timestamp: args.now(),\n payload: {\n iterationIndex: args.item.index,\n agentRunName: slot.agentRunName,\n taskHash: hashJson(args.item.task),\n groupId: args.roundIndex,\n parentIndex: args.parentIndex,\n },\n })\n\n try {\n const box = await createSandboxForSpec(args.ctx.sandboxClient, spec, args.signal)\n const placement = describePlacementSafe(args.ctx.sandboxClient, box)\n await emitTrace(args.ctx.traceEmitter, {\n kind: 'loop.iteration.dispatch',\n runId: args.runId,\n timestamp: args.now(),\n payload: {\n iterationIndex: args.item.index,\n agentRunName: slot.agentRunName,\n placement: placement.kind,\n sandboxId: placement.sandboxId,\n fleetId: placement.fleetId,\n machineId: placement.machineId,\n groupId: args.roundIndex,\n parentIndex: args.parentIndex,\n },\n })\n const message = spec.taskToPrompt(args.item.task)\n const events: SandboxEvent[] = []\n for await (const event of box.streamPrompt(message, { signal: args.signal })) {\n events.push(event)\n const llmCall = extractLlmCallEvent(event, slot.agentRunName)\n if (llmCall) {\n slot.costUsd += llmCall.costUsd ?? 0\n slot.tokenUsage.input += llmCall.tokensIn ?? 0\n slot.tokenUsage.output += llmCall.tokensOut ?? 0\n args.ctx.runHandle?.observe(llmCall)\n }\n }\n slot.events = events\n slot.output = args.output.parse(events)\n if (args.validator) {\n slot.verdict = await args.validator.validate(slot.output, {\n iteration: args.item.index,\n signal: args.signal,\n traceEmitter: args.ctx.traceEmitter,\n })\n }\n } catch (err) {\n slot.error = err instanceof Error ? err : new Error(String(err))\n } finally {\n slot.endedAt = args.now()\n await emitTrace(args.ctx.traceEmitter, {\n kind: 'loop.iteration.ended',\n runId: args.runId,\n timestamp: args.now(),\n payload: {\n iterationIndex: args.item.index,\n agentRunName: slot.agentRunName,\n outputHash: slot.output !== undefined ? hashJson(slot.output) : undefined,\n verdict: slot.verdict,\n error: slot.error?.message,\n costUsd: slot.costUsd,\n durationMs: slot.endedAt - slot.startedAt,\n tokenUsage:\n slot.tokenUsage.input || slot.tokenUsage.output ? { ...slot.tokenUsage } : undefined,\n groupId: args.roundIndex,\n parentIndex: args.parentIndex,\n outputPreview: slot.output !== undefined ? previewOutput(slot.output) : undefined,\n },\n })\n }\n}\n\n/**\n * Branch point for a new round — the iteration a later round descends from.\n * Highest-valid-score iteration so far; ties + no-valid fall back to the latest\n * index. Inferred (not driver-declared), so refine renders as a chain and\n * fanout→refine chains off the fanout winner.\n */\nfunction branchPoint<Task, Output>(\n iterations: ReadonlyArray<Iteration<Task, Output>>,\n): number | undefined {\n if (iterations.length === 0) return undefined\n let best = iterations.length - 1\n let bestScore = -Infinity\n for (const iter of iterations) {\n if (iter.verdict?.valid !== true) continue\n const score = iter.verdict.score ?? 0\n if (score > bestScore) {\n bestScore = score\n best = iter.index\n }\n }\n return best\n}\n\n/** Bounded string preview of a parsed output for a viewer's drawer — never the\n * full payload. JSON when serializable, else `String()`, truncated to 280. */\nfunction previewOutput(output: unknown): string {\n let s: string\n try {\n s = typeof output === 'string' ? output : (JSON.stringify(output) ?? String(output))\n } catch {\n s = String(output)\n }\n return s.length > 280 ? `${s.slice(0, 280)}…` : s\n}\n\nfunction describePlacementSafe(\n client: LoopSandboxClient,\n box: SandboxInstance,\n): LoopSandboxPlacement {\n if (typeof client.describePlacement === 'function') {\n try {\n const result = client.describePlacement(box)\n if (\n result &&\n typeof result === 'object' &&\n (result.kind === 'sibling' || result.kind === 'fleet')\n ) {\n return {\n kind: result.kind,\n sandboxId: result.sandboxId ?? readSandboxId(box),\n fleetId: result.fleetId,\n machineId: result.machineId,\n }\n }\n } catch {\n // Adapter bug must not corrupt the iteration; fall through to default.\n }\n }\n return { kind: 'sibling', sandboxId: readSandboxId(box) }\n}\n\nfunction readSandboxId(box: SandboxInstance): string | undefined {\n const raw = (box as unknown as { id?: unknown }).id\n return typeof raw === 'string' && raw.length > 0 ? raw : undefined\n}\n\nasync function createSandboxForSpec<Task>(\n client: LoopSandboxClient,\n spec: AgentRunSpec<Task>,\n signal: AbortSignal,\n): Promise<SandboxInstance> {\n const overrides = spec.sandboxOverrides ?? {}\n const overrideBackend = overrides.backend\n const opts: CreateSandboxOptions = {\n ...overrides,\n backend: {\n type: overrideBackend?.type ?? inferBackendType(spec.profile),\n profile: spec.profile satisfies AgentProfile,\n ...(overrideBackend?.model ? { model: overrideBackend.model } : {}),\n ...(overrideBackend?.server ? { server: overrideBackend.server } : {}),\n },\n }\n // Cooperative cancellation: if the abort signal fires while .create is\n // pending, the promise itself is not abortable but the inflight prompt is.\n if (signal.aborted) throwAbort()\n return client.create(opts)\n}\n\nfunction inferBackendType(\n profile: AgentProfile,\n): CreateSandboxOptions['backend'] extends infer B\n ? B extends { type: infer T }\n ? T\n : never\n : never {\n // The sandbox SDK accepts profile-driven backend selection by name. When the\n // profile has no explicit hint we fall through to the SDK's default\n // ('opencode' on the platform side). Returning a literal here would lie\n // about provenance — let the SDK pick.\n type BackendType = NonNullable<CreateSandboxOptions['backend']>['type']\n const explicit = profile.metadata?.backendType\n if (typeof explicit === 'string') return explicit as BackendType\n return 'opencode' as BackendType\n}\n\ninterface FinalizeArgs<Task, Output, Decision> {\n options: RunLoopOptions<Task, Output, Decision>\n decision: Decision\n iterations: Iteration<Task, Output>[]\n startMs: number\n now: () => number\n runId: string\n}\n\nfunction finalize<Task, Output, Decision>(\n args: FinalizeArgs<Task, Output, Decision>,\n): LoopResult<Task, Output, Decision> {\n const winner = (args.options.selectWinner ?? defaultSelectWinner)(args.iterations)\n const costUsd = args.iterations.reduce((sum, iter) => sum + (iter.costUsd || 0), 0)\n const tokenUsage = args.iterations.reduce(\n (acc, iter) => {\n acc.input += iter.tokenUsage?.input ?? 0\n acc.output += iter.tokenUsage?.output ?? 0\n return acc\n },\n { input: 0, output: 0 },\n )\n const result: LoopResult<Task, Output, Decision> = {\n decision: args.decision,\n iterations: args.iterations,\n winner,\n durationMs: args.now() - args.startMs,\n costUsd,\n tokenUsage,\n }\n void emitTrace(args.options.ctx.traceEmitter, {\n kind: 'loop.ended',\n runId: args.runId,\n timestamp: args.now(),\n payload: {\n winnerIterationIndex: winner?.iterationIndex,\n totalCostUsd: costUsd,\n durationMs: result.durationMs,\n iterations: args.iterations.length,\n },\n })\n return result\n}\n\nfunction defaultSelectWinner<Task, Output>(\n iterations: Iteration<Task, Output>[],\n): LoopWinner<Task, Output> | undefined {\n const candidates = iterations.filter((iter) => iter.output !== undefined && !iter.error)\n if (candidates.length === 0) return undefined\n const valid = candidates.filter((iter) => iter.verdict?.valid === true)\n const pool = valid.length > 0 ? valid : candidates\n const sorted = [...pool].sort(\n (a, b) => (b.verdict?.score ?? 0) - (a.verdict?.score ?? 0) || a.index - b.index,\n )\n const top = sorted[0]\n if (!top || top.output === undefined) return undefined\n return {\n task: top.task,\n output: top.output,\n verdict: top.verdict,\n iterationIndex: top.index,\n agentRunName: top.agentRunName,\n }\n}\n\nfunction resolveAgentRuns<Task, Output, Decision>(\n options: RunLoopOptions<Task, Output, Decision>,\n): AgentRunSpec<Task>[] {\n if (options.agentRun && options.agentRuns) {\n throw new ValidationError('runLoop: pass exactly one of `agentRun` or `agentRuns`')\n }\n if (options.agentRun) return [options.agentRun]\n if (options.agentRuns && options.agentRuns.length > 0) return options.agentRuns\n throw new ValidationError('runLoop: `agentRun` or non-empty `agentRuns` is required')\n}\n\nfunction isTerminalDecision(decision: unknown): boolean {\n return (\n decision === 'stop' || decision === 'pick-winner' || decision === 'fail' || decision === 'done'\n )\n}\n\nfunction serializeDecision(decision: unknown): string {\n if (typeof decision === 'string') return decision\n if (decision === null || decision === undefined) return 'null'\n try {\n return JSON.stringify(decision)\n } catch {\n return String(decision)\n }\n}\n\nasync function emitTrace(\n emitter: LoopTraceEmitter | undefined,\n event: LoopTraceEvent,\n): Promise<void> {\n if (!emitter) return\n await emitter.emit(event)\n}\n\nfunction randomSuffix(len = 8): string {\n return Math.random()\n .toString(36)\n .slice(2, 2 + len)\n}\n\nfunction throwAbort(): never {\n const err = new Error('aborted')\n err.name = 'AbortError'\n throw err\n}\n\n/**\n * Extract a `RuntimeStreamEvent`-shaped `llm_call` from a sandbox event when\n * the event carries usage/cost data. Returns `undefined` for non-cost events\n * so the kernel can iterate the full stream without branching.\n *\n * Sandbox SDK emits a polymorphic `SandboxEvent = { type, data, id? }`. The\n * canonical cost-carrying types observed in the wild:\n * - `llm_call` — `data: { model, tokensIn, tokensOut, costUsd, ... }`\n * - `message.completed` / `result` — `data: { usage: { inputTokens,\n * outputTokens, totalCostUsd? } }`\n * - `cost.usage` — same shape under a dedicated type\n *\n * Numeric coercion is strict: `Number.isFinite` gates every accumulator\n * write so a sentinel `NaN` from a misbehaving backend cannot poison the\n * ledger.\n */\nfunction extractLlmCallEvent(\n event: SandboxEvent,\n agentRunName: string,\n): (RuntimeStreamEvent & { type: 'llm_call' }) | undefined {\n if (!event || typeof event !== 'object') return undefined\n const type = String(event.type ?? '')\n const data =\n event.data && typeof event.data === 'object'\n ? (event.data as Record<string, unknown>)\n : ({} as Record<string, unknown>)\n\n if (type === 'llm_call' || type === 'cost.usage' || type === 'usage') {\n return buildLlmCall(data, agentRunName)\n }\n if (type === 'message.completed' || type === 'result' || type === 'final') {\n const usage = data.usage as Record<string, unknown> | undefined\n if (!usage || typeof usage !== 'object') return undefined\n return buildLlmCall({ ...usage, model: data.model ?? usage.model }, agentRunName)\n }\n return undefined\n}\n\nfunction buildLlmCall(\n data: Record<string, unknown>,\n agentRunName: string,\n): (RuntimeStreamEvent & { type: 'llm_call' }) | undefined {\n const tokensIn = pickFiniteNumber(data, ['tokensIn', 'inputTokens', 'prompt_tokens'])\n const tokensOut = pickFiniteNumber(data, ['tokensOut', 'outputTokens', 'completion_tokens'])\n const costUsd = pickFiniteNumber(data, ['costUsd', 'totalCostUsd', 'cost_usd', 'cost'])\n if (tokensIn === undefined && tokensOut === undefined && costUsd === undefined) {\n return undefined\n }\n const model = typeof data.model === 'string' && data.model.length > 0 ? data.model : agentRunName\n const event: RuntimeStreamEvent & { type: 'llm_call' } = {\n type: 'llm_call',\n model,\n }\n if (tokensIn !== undefined) event.tokensIn = tokensIn\n if (tokensOut !== undefined) event.tokensOut = tokensOut\n if (costUsd !== undefined) event.costUsd = costUsd\n return event\n}\n\nfunction pickFiniteNumber(data: Record<string, unknown>, keys: string[]): number | undefined {\n for (const key of keys) {\n const value = data[key]\n if (typeof value === 'number' && Number.isFinite(value)) return value\n }\n return undefined\n}\n\n/**\n * Stable hash for the trace payload. Not cryptographic — only used so\n * downstream eval pipelines can group iterations whose task / output is the\n * same. Bare structural hash; non-JSON values stringify via their `toString`.\n */\nfunction hashJson(value: unknown): string {\n let str: string\n try {\n str = JSON.stringify(value) ?? String(value)\n } catch {\n str = String(value)\n }\n // FNV-1a 32-bit — branch-free, dependency-free, good enough for grouping.\n let h = 0x811c9dc5\n for (let i = 0; i < str.length; i += 1) {\n h ^= str.charCodeAt(i)\n h = Math.imul(h, 0x01000193)\n }\n return (h >>> 0).toString(16).padStart(8, '0')\n}\n","/**\n * `loopDispatch` — turn `runLoop` into an agent-eval campaign dispatch.\n *\n * Without this adapter a consumer wiring `runLoop` into `runProfileMatrix` /\n * `runCampaign` has to, by hand, every time: (a) build an `ExecCtx` with a\n * sandbox client, (b) adapt the campaign `DispatchContext.trace` into a\n * `LoopTraceEmitter` (or lose all loop trace correlation), and (c) remember to\n * forward the loop's cost + tokens via `ctx.cost` (forgetting it yields a\n * `{0,0}` cell the backend-integrity guard reads as a stub). Three foot-guns,\n * the third silent. The fleet's products skipped (c) and fell back to a\n * `workerRecords[]` side-channel — the exact anti-pattern the substrate exists\n * to kill.\n *\n * `loopDispatch` collapses all three into one typed call:\n *\n * const dispatch = loopDispatch({\n * sandboxClient,\n * toLoopOptions: (scenario, profile) => ({ driver, agentRun, output, validator, task }),\n * })\n * await runProfileMatrix({ profiles, scenarios, dispatch, judges, commitSha })\n *\n * Usage is reported automatically; trace events are forwarded automatically;\n * the ctx is built automatically. The seam becomes impossible to mis-wire.\n *\n * Typed structurally against the campaign `DispatchContext` (imported type-only\n * from `@tangle-network/agent-eval/campaign`) — a downward dependency, never an\n * inversion.\n */\n\n// agent-eval's AgentProfile (the eval-harness unit of variation, `model: string`)\n// — NOT sandbox's AgentProfile. ProfileDispatchFn is keyed on the former.\nimport type { AgentProfile } from '@tangle-network/agent-eval'\nimport type {\n CampaignTraceWriter,\n DispatchContext,\n DispatchFn,\n ProfileDispatchFn,\n Scenario,\n} from '@tangle-network/agent-eval/campaign'\nimport { reportLoopUsage } from './report-usage'\nimport { type RunLoopOptions, runLoop } from './run-loop'\nimport type { LoopResult, LoopSandboxClient, LoopTraceEmitter } from './types'\n\n/** runLoop options minus the `ctx` (loopDispatch builds the ctx). */\nexport type LoopOptionsForDispatch<Task, Output, Decision> = Omit<\n RunLoopOptions<Task, Output, Decision>,\n 'ctx'\n>\n\nexport interface LoopDispatchOptions<Task, Output, Decision, TScenario extends Scenario, TArtifact> {\n /** Sandbox client used for every cell's `runLoop`. Supplied once. */\n sandboxClient: LoopSandboxClient\n /** Build the per-cell runLoop options from the scenario (+ profile, when\n * used with `runProfileMatrix`). */\n toLoopOptions: (\n scenario: TScenario,\n profile: AgentProfile,\n ) => LoopOptionsForDispatch<Task, Output, Decision>\n /** Map the finished loop to the artifact the judges score. Default:\n * `result.winner?.output`. A loop with no winner yields `undefined` (judges\n * skip the cell) — but the loop's token usage is STILL reported, so the\n * integrity guard sees real activity. */\n toArtifact?: (result: LoopResult<Task, Output, Decision>) => TArtifact\n /** Forward `loop.*` trace events into the campaign's scoped trace so loop\n * spans correlate with the cell. Default true. */\n forwardTrace?: boolean\n /** Cost-meter source label for the loop's spend. Default `'loop'`. */\n costSource?: string\n}\n\n/** Bridge a campaign `DispatchContext.trace` to a `LoopTraceEmitter` so every\n * `loop.*` event lands as a span under the cell's scoped trace. */\nfunction campaignTraceToLoopEmitter(trace: CampaignTraceWriter): LoopTraceEmitter {\n return {\n emit(event) {\n trace\n .span(event.kind, { runId: event.runId, timestamp: event.timestamp, ...event.payload })\n .end()\n },\n }\n}\n\nasync function runLoopForCell<Task, Output, Decision, TScenario extends Scenario, TArtifact>(\n opts: LoopDispatchOptions<Task, Output, Decision, TScenario, TArtifact>,\n scenario: TScenario,\n profile: AgentProfile,\n ctx: DispatchContext,\n): Promise<TArtifact> {\n const loopOptions = opts.toLoopOptions(scenario, profile)\n const result = await runLoop<Task, Output, Decision>({\n ...loopOptions,\n ctx: {\n sandboxClient: opts.sandboxClient,\n signal: ctx.signal,\n traceEmitter:\n opts.forwardTrace === false ? undefined : campaignTraceToLoopEmitter(ctx.trace),\n },\n })\n reportLoopUsage(ctx.cost, result, opts.costSource ?? 'loop')\n const toArtifact =\n opts.toArtifact ?? ((r: LoopResult<Task, Output, Decision>) => r.winner?.output as TArtifact)\n return toArtifact(result)\n}\n\n/**\n * Adapter for `runProfileMatrix` (profile is an axis). Returns a\n * `ProfileDispatchFn` that runs `runLoop` per (profile, scenario) cell and\n * reports usage automatically.\n */\nexport function loopDispatch<Task, Output, Decision, TScenario extends Scenario, TArtifact>(\n opts: LoopDispatchOptions<Task, Output, Decision, TScenario, TArtifact>,\n): ProfileDispatchFn<TScenario, TArtifact> {\n return (profile, scenario, ctx) => runLoopForCell(opts, scenario, profile, ctx)\n}\n\n/**\n * Adapter for `runCampaign` (no profile axis). `toLoopOptions` receives only\n * the scenario; the `profile` passed to the shared core is a stable sentinel\n * so a single `runLoop` config is reused across cells.\n */\nexport function loopCampaignDispatch<Task, Output, Decision, TScenario extends Scenario, TArtifact>(\n opts: Omit<LoopDispatchOptions<Task, Output, Decision, TScenario, TArtifact>, 'toLoopOptions'> & {\n toLoopOptions: (scenario: TScenario) => LoopOptionsForDispatch<Task, Output, Decision>\n },\n): DispatchFn<TScenario, TArtifact> {\n const profileSentinel = { id: 'loop-campaign', model: 'n/a@loop-campaign' } as AgentProfile\n const profiled: LoopDispatchOptions<Task, Output, Decision, TScenario, TArtifact> = {\n ...opts,\n toLoopOptions: (scenario) => opts.toLoopOptions(scenario),\n }\n return (scenario, ctx) => runLoopForCell(profiled, scenario, profileSentinel, ctx)\n}\n"],"mappings":"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","names":["decision"]}
@@ -16,16 +16,18 @@ import {
16
16
  DELEGATION_STATUS_TOOL_NAME,
17
17
  DelegationTaskQueue,
18
18
  InMemoryFeedbackStore,
19
+ buildLoopOtelSpans,
19
20
  createDelegateCodeHandler,
20
21
  createDelegateFeedbackHandler,
21
22
  createDelegateResearchHandler,
22
23
  createDelegationHistoryHandler,
23
- createDelegationStatusHandler
24
- } from "./chunk-HSX6PFZR.js";
24
+ createDelegationStatusHandler,
25
+ createOtelExporter
26
+ } from "./chunk-HVYOHJHK.js";
25
27
  import {
26
28
  createFleetWorkspaceExecutor,
27
29
  createSiblingSandboxExecutor
28
- } from "./chunk-VLXRXMTF.js";
30
+ } from "./chunk-FJ4GDNVN.js";
29
31
  import {
30
32
  runLocalHarness
31
33
  } from "./chunk-GLR25NG7.js";
@@ -549,6 +551,47 @@ function createInProcessTransport() {
549
551
  };
550
552
  }
551
553
 
554
+ // src/mcp/trace-propagation.ts
555
+ function readTraceContextFromEnv() {
556
+ const traceId = process.env.TRACE_ID || generateTraceId();
557
+ const parentSpanId = process.env.PARENT_SPAN_ID || void 0;
558
+ return { traceId, parentSpanId };
559
+ }
560
+ function createPropagatingTraceEmitter(ctx) {
561
+ const exporter = createOtelExporter();
562
+ const buffers = /* @__PURE__ */ new Map();
563
+ const emitter = {
564
+ emit(event) {
565
+ if (!exporter) return;
566
+ const buf = buffers.get(event.runId);
567
+ if (buf) buf.push(event);
568
+ else buffers.set(event.runId, [event]);
569
+ if (event.kind === "loop.ended") {
570
+ const events = buffers.get(event.runId) ?? [event];
571
+ buffers.delete(event.runId);
572
+ for (const span of buildLoopOtelSpans(events, ctx.traceId, ctx.parentSpanId)) {
573
+ exporter.exportSpan(span);
574
+ }
575
+ }
576
+ }
577
+ };
578
+ return { emitter, exporter, context: ctx };
579
+ }
580
+ function traceContextToEnv(ctx) {
581
+ const env = { TRACE_ID: ctx.traceId };
582
+ if (ctx.parentSpanId) env.PARENT_SPAN_ID = ctx.parentSpanId;
583
+ return env;
584
+ }
585
+ function generateTraceId() {
586
+ const bytes = new Uint8Array(16);
587
+ if (typeof globalThis.crypto?.getRandomValues === "function") {
588
+ globalThis.crypto.getRandomValues(bytes);
589
+ } else {
590
+ for (let i = 0; i < 16; i++) bytes[i] = Math.floor(Math.random() * 256);
591
+ }
592
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
593
+ }
594
+
552
595
  export {
553
596
  createWorktree,
554
597
  captureWorktreeDiff,
@@ -556,6 +599,9 @@ export {
556
599
  createInProcessExecutor,
557
600
  detectExecutor,
558
601
  createMcpServer,
559
- createInProcessTransport
602
+ createInProcessTransport,
603
+ readTraceContextFromEnv,
604
+ createPropagatingTraceEmitter,
605
+ traceContextToEnv
560
606
  };
561
- //# sourceMappingURL=chunk-PK5DYSNO.js.map
607
+ //# sourceMappingURL=chunk-WSJJGSD3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp/worktree.ts","../src/mcp/in-process-executor.ts","../src/mcp/bin-helpers.ts","../src/mcp/server.ts","../src/mcp/trace-propagation.ts"],"sourcesContent":["/**\n * @experimental\n *\n * Git worktree helpers for the in-process delegation executor. Each\n * delegation runs in its own worktree so multiple parallel harness\n * subprocesses (claude / codex / opencode in a 3-way fanout) don't clobber\n * each other's edits on the shared workspace.\n *\n * Worktrees live under `<repoRoot>/.coder-variants/<runId>/`. After the\n * harness exits + the diff is captured, the worktree is removed.\n *\n * All operations spawn `git` via `child_process.spawn` synchronously\n * (via a `runGit` helper). Stays narrow on purpose: no working-tree\n * staging, no commits, no rebases.\n */\n\nimport { spawn } from 'node:child_process'\n\n/** @experimental */\nexport interface WorktreeHandle {\n /** Absolute path to the worktree directory. */\n path: string\n /** SHA the worktree was created at. */\n baseSha: string\n /** Branch name created for this worktree (typically `delegate/<runId>`). */\n branch: string\n}\n\n/** @experimental */\nexport interface CreateWorktreeOptions {\n /** Absolute path to the main git checkout. */\n repoRoot: string\n /** Unique id for the worktree path + branch. Use the delegation run id. */\n runId: string\n /** Parent directory the worktree lives under. Defaults to `.coder-variants`. */\n variantsDir?: string\n /** Override the base ref (default `HEAD`). */\n baseRef?: string\n /** Test seam — inject a custom git runner. */\n runGit?: GitRunner\n}\n\n/** @experimental */\nexport interface DiffOptions {\n /** Worktree to diff. */\n worktree: WorktreeHandle\n /** What to compare against. Default `worktree.baseSha`. */\n baseRef?: string\n /** Test seam. */\n runGit?: GitRunner\n}\n\n/** @experimental */\nexport interface DiffResult {\n patch: string\n stats: {\n filesChanged: number\n insertions: number\n deletions: number\n }\n}\n\n/** @experimental */\nexport interface RemoveWorktreeOptions {\n worktree: WorktreeHandle\n repoRoot: string\n /** Force removal even if dirty (default true; the loser of a fanout has uncommitted changes). */\n force?: boolean\n /** Test seam. */\n runGit?: GitRunner\n}\n\n/** Pluggable git runner (sync) — replaceable in tests. */\nexport type GitRunner = (\n args: ReadonlyArray<string>,\n opts: { cwd: string },\n) => { stdout: string; stderr: string; exitCode: number }\n\nasync function runGitAsync(\n args: ReadonlyArray<string>,\n cwd: string,\n runner?: GitRunner,\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n if (runner) return runner(args, { cwd })\n return new Promise((resolve, reject) => {\n const proc = spawn('git', args, { cwd, stdio: 'pipe' })\n let stdout = ''\n let stderr = ''\n proc.stdout?.on('data', (c) => {\n stdout += String(c)\n })\n proc.stderr?.on('data', (c) => {\n stderr += String(c)\n })\n proc.on('error', reject)\n proc.on('close', (code) => resolve({ stdout, stderr, exitCode: code ?? -1 }))\n })\n}\n\nfunction ensureGitOk(\n step: string,\n result: { stdout: string; stderr: string; exitCode: number },\n): void {\n if (result.exitCode !== 0) {\n throw new Error(\n `worktree: git ${step} failed (exit ${result.exitCode}): ${result.stderr.slice(0, 400)}`,\n )\n }\n}\n\n/** @experimental */\nexport async function createWorktree(options: CreateWorktreeOptions): Promise<WorktreeHandle> {\n const variants = options.variantsDir ?? '.coder-variants'\n const baseRef = options.baseRef ?? 'HEAD'\n const branch = `delegate/${options.runId}`\n const path = `${options.repoRoot.replace(/\\/+$/, '')}/${variants}/${options.runId}`\n\n const headSha = await runGitAsync(['rev-parse', baseRef], options.repoRoot, options.runGit)\n ensureGitOk(`rev-parse ${baseRef}`, headSha)\n\n const add = await runGitAsync(\n ['worktree', 'add', '-b', branch, path, baseRef],\n options.repoRoot,\n options.runGit,\n )\n ensureGitOk(`worktree add ${path}`, add)\n\n return { path, baseSha: headSha.stdout.trim(), branch }\n}\n\n/** @experimental */\nexport async function captureWorktreeDiff(options: DiffOptions): Promise<DiffResult> {\n const baseRef = options.baseRef ?? options.worktree.baseSha\n const patch = await runGitAsync(['diff', baseRef], options.worktree.path, options.runGit)\n // No `ensureGitOk` here — diff returns 0 even when there are no changes.\n\n // Stats: `git diff --shortstat` produces e.g. \" 3 files changed, 42 insertions(+), 10 deletions(-)\".\n const shortstat = await runGitAsync(\n ['diff', '--shortstat', baseRef],\n options.worktree.path,\n options.runGit,\n )\n const stats = parseShortstat(shortstat.stdout)\n return { patch: patch.stdout, stats }\n}\n\nfunction parseShortstat(text: string): DiffResult['stats'] {\n // `text` is the raw stdout of `git diff --shortstat`. Empty when no\n // changes. Parse defensively — the format is stable but we don't trust\n // it for type-safety.\n const out = { filesChanged: 0, insertions: 0, deletions: 0 }\n const filesMatch = text.match(/(\\d+)\\s+files?\\s+changed/)\n if (filesMatch?.[1]) out.filesChanged = Number(filesMatch[1])\n const insertMatch = text.match(/(\\d+)\\s+insertions?/)\n if (insertMatch?.[1]) out.insertions = Number(insertMatch[1])\n const deleteMatch = text.match(/(\\d+)\\s+deletions?/)\n if (deleteMatch?.[1]) out.deletions = Number(deleteMatch[1])\n return out\n}\n\n/** @experimental */\nexport async function removeWorktree(options: RemoveWorktreeOptions): Promise<void> {\n const force = options.force ?? true\n const args = ['worktree', 'remove']\n if (force) args.push('--force')\n args.push(options.worktree.path)\n const result = await runGitAsync(args, options.repoRoot, options.runGit)\n // Don't ensureGitOk — partial-removal scenarios are tolerable; the\n // worktree dir may already be gone (caller deleted it manually).\n if (result.exitCode !== 0 && !/not a working tree/.test(result.stderr)) {\n // Best-effort branch cleanup so the next run can reuse the runId.\n await runGitAsync(\n ['branch', '-D', options.worktree.branch],\n options.repoRoot,\n options.runGit,\n ).catch(() => undefined)\n }\n // Always attempt branch removal — the worktree-remove sometimes leaves\n // the branch behind even when the directory is gone.\n await runGitAsync(\n ['branch', '-D', options.worktree.branch],\n options.repoRoot,\n options.runGit,\n ).catch(() => undefined)\n}\n","/**\n * @experimental\n *\n * In-process delegation executor — when `agent-runtime-mcp` is running\n * inside a sandbox whose image carries the local coding-harness CLIs\n * (claude / codex / opencode), delegations spawn the harness AS A\n * SUBPROCESS against a git worktree on the SAME filesystem instead of\n * provisioning a sibling sandbox.\n *\n * Why: zero provisioning latency, worker diffs land in-place, multi-harness\n * fanout = N parallel subprocesses in N parallel worktrees.\n *\n * Selection:\n * - env `AGENT_RUNTIME_IN_SANDBOX=1` (set by the parent harness at MCP\n * server launch) → in-process executor\n * - env `TANGLE_FLEET_ID=...` → fleet executor (Phase 2.5)\n * - neither → sibling sandbox executor (default)\n *\n * Multi-harness rotation: pass `harnesses: ['claude', 'codex', 'opencode']`\n * to round-robin across calls. A `runLoop` + `FanoutVote(n: 3)` against this\n * executor produces three parallel iterations, each running a different\n * harness on its own worktree.\n *\n * Architecture:\n *\n * client.create() → returns a fake SandboxInstance whose streamPrompt:\n * 1. createWorktree() — git worktree add /workspace/.coder-variants/<id>\n * 2. runLocalHarness() — spawn claude/codex/opencode subprocess\n * 3. captureWorktreeDiff() — git diff HEAD → patch + stats\n * 4. run testCmd + typecheckCmd if specified (the executor doesn't\n * own these — caller wires via task-extractor callback)\n * 5. emit ONE SandboxEvent { type: 'result', data: { result: CoderOutput } }\n * 6. removeWorktree() in finally\n */\n\nimport { randomUUID } from 'node:crypto'\nimport type { CreateSandboxOptions, SandboxEvent, SandboxInstance } from '@tangle-network/sandbox'\nimport type { LoopSandboxClient, LoopSandboxPlacement } from '../loops'\nimport type { DelegationExecutor } from './executor'\nimport { type LocalHarness, runLocalHarness } from './local-harness'\nimport {\n captureWorktreeDiff,\n createWorktree,\n type GitRunner,\n removeWorktree,\n type WorktreeHandle,\n} from './worktree'\n\n/** @experimental */\nexport interface InProcessExecutorOptions {\n /**\n * Absolute path to the git repo (the workspace inside the sandbox). The\n * executor creates worktrees under `<repoRoot>/.coder-variants/`.\n */\n repoRoot: string\n /**\n * Harnesses to round-robin across calls. With one entry every delegation\n * uses that harness; with three you get fanout diversity for free.\n * Default `['claude']`.\n */\n harnesses?: ReadonlyArray<LocalHarness>\n /**\n * Optional per-delegation test command. Run with `cwd = worktree.path`\n * after the harness exits. The exit code populates\n * `CoderOutput.testResult.passed`.\n */\n testCmd?: string\n /**\n * Optional per-delegation typecheck command. Same shape as `testCmd`.\n */\n typecheckCmd?: string\n /** Wall-clock cap per harness subprocess (ms). Default 5min. */\n harnessTimeoutMs?: number\n /** Wall-clock cap per test/typecheck subprocess (ms). Default 2min. */\n postCheckTimeoutMs?: number\n /** Test seam — override the git runner used by the worktree helpers. */\n runGit?: GitRunner\n /**\n * Test seam — override the harness runner. Defaults to spawning the real\n * CLI via `runLocalHarness`. Tests inject a stub that returns a scripted\n * `LocalHarnessResult`.\n */\n runHarness?: typeof runLocalHarness\n /**\n * Test seam — override the post-check runner. Defaults to spawning the\n * configured `testCmd` / `typecheckCmd` via `child_process.spawn`.\n */\n runPostCheck?: (\n cmd: string,\n cwd: string,\n signal?: AbortSignal,\n ) => Promise<{ exitCode: number; stdout: string; stderr: string }>\n}\n\n/** @experimental */\nexport interface InProcessExecutorDescribePlacement extends LoopSandboxPlacement {\n /**\n * Worktree path in the parent sandbox's filesystem. Set so trace\n * consumers can correlate dispatch events with on-disk artifacts after\n * the worker exits.\n */\n worktreePath?: string\n /** Which harness handled this delegation. */\n harness?: LocalHarness\n}\n\ninterface VirtualSandbox extends SandboxInstance {\n __inProcess: {\n runId: string\n harness: LocalHarness\n worktree?: WorktreeHandle\n }\n}\n\nconst DEFAULT_HARNESS_TIMEOUT_MS = 5 * 60 * 1000\nconst DEFAULT_POSTCHECK_TIMEOUT_MS = 2 * 60 * 1000\n\n/**\n * Build an in-process executor.\n *\n * Returns a {@link DelegationExecutor} whose `client.create()` returns a\n * minimal \"virtual\" SandboxInstance — the kernel calls `streamPrompt(msg)`\n * on it, which runs the local harness on a worktree and emits one\n * `result` event whose `data.result` is a `CoderOutput`-shaped record.\n *\n * Pairs with `coderProfile`'s event parser (it walks the event list\n * back-to-front for the first `type === 'result'`).\n *\n * @experimental\n */\nexport function createInProcessExecutor(options: InProcessExecutorOptions): DelegationExecutor {\n const harnesses =\n options.harnesses && options.harnesses.length > 0\n ? [...options.harnesses]\n : (['claude'] as const)\n const runHarness = options.runHarness ?? runLocalHarness\n const runPostCheck = options.runPostCheck ?? defaultRunPostCheck\n\n let callIndex = 0\n\n const client: LoopSandboxClient = {\n async create(_opts?: CreateSandboxOptions): Promise<SandboxInstance> {\n const runId = randomUUID()\n const harness = harnesses[callIndex % harnesses.length] as LocalHarness\n callIndex += 1\n\n const virtual: VirtualSandbox = {\n // Synthesize the minimum SandboxInstance surface the kernel touches.\n // We CAST through unknown because SandboxInstance is a `declare class`\n // with private fields; we're producing a structural subtype that\n // satisfies the kernel's narrow usage (`box.id`, `box.streamPrompt`).\n id: `in-process-${runId}`,\n __inProcess: { runId, harness },\n // eslint-disable-next-line require-yield\n async *streamPrompt(\n this: VirtualSandbox,\n message: string | unknown[],\n promptOpts?: { signal?: AbortSignal },\n ): AsyncGenerator<SandboxEvent> {\n const taskPrompt =\n typeof message === 'string'\n ? message\n : message\n .map((p) =>\n typeof p === 'object' && p && 'text' in p\n ? String((p as { text: unknown }).text)\n : '',\n )\n .join('\\n')\n\n let worktree: WorktreeHandle | undefined\n try {\n worktree = await createWorktree({\n repoRoot: options.repoRoot,\n runId,\n runGit: options.runGit,\n })\n this.__inProcess.worktree = worktree\n\n // Yield a dispatch-equivalent event so traces see the placement.\n yield {\n type: 'in_process.harness.started',\n data: {\n runId,\n harness,\n worktreePath: worktree.path,\n command: harness,\n },\n }\n\n const harnessResult = await runHarness({\n harness,\n cwd: worktree.path,\n taskPrompt,\n timeoutMs: options.harnessTimeoutMs ?? DEFAULT_HARNESS_TIMEOUT_MS,\n signal: promptOpts?.signal,\n })\n\n yield {\n type: 'in_process.harness.ended',\n data: {\n runId,\n exitCode: harnessResult.exitCode,\n durationMs: harnessResult.durationMs,\n killedBySignal: harnessResult.killedBySignal,\n timedOut: harnessResult.timedOut,\n stdoutBytes: harnessResult.stdout.length,\n stderrBytes: harnessResult.stderr.length,\n },\n }\n\n // Capture diff regardless of exit code — a failed run can still\n // leave a partial diff worth inspecting.\n const diff = await captureWorktreeDiff({ worktree, runGit: options.runGit })\n\n // Optional post-checks. Each runs in the WORKTREE so it sees the\n // harness's edits.\n const testCheck = options.testCmd\n ? await runPostCheck(options.testCmd, worktree.path, promptOpts?.signal).catch(\n (err) => ({\n exitCode: -1,\n stdout: '',\n stderr: err instanceof Error ? err.message : String(err),\n }),\n )\n : { exitCode: 0, stdout: '', stderr: '' }\n const typecheckCheck = options.typecheckCmd\n ? await runPostCheck(options.typecheckCmd, worktree.path, promptOpts?.signal).catch(\n (err) => ({\n exitCode: -1,\n stdout: '',\n stderr: err instanceof Error ? err.message : String(err),\n }),\n )\n : { exitCode: 0, stdout: '', stderr: '' }\n\n const coderOutput = {\n branch: worktree.branch,\n patch: diff.patch,\n testResult: {\n passed: !options.testCmd || testCheck.exitCode === 0,\n output: tail(testCheck.stderr || testCheck.stdout, 4000),\n },\n typecheckResult: {\n passed: !options.typecheckCmd || typecheckCheck.exitCode === 0,\n output: tail(typecheckCheck.stderr || typecheckCheck.stdout, 4000),\n },\n diffStats: diff.stats,\n reviewerNotes:\n harnessResult.exitCode === 0\n ? undefined\n : `harness ${harness} exited ${harnessResult.exitCode}${harnessResult.timedOut ? ' (timed out)' : ''}`,\n }\n\n // The terminal event the coderProfile parser looks for.\n yield {\n type: 'result',\n data: {\n result: coderOutput,\n source: 'in-process-executor',\n harness,\n runId,\n },\n }\n } finally {\n if (worktree) {\n await removeWorktree({\n worktree,\n repoRoot: options.repoRoot,\n runGit: options.runGit,\n }).catch(() => undefined)\n }\n }\n },\n } as unknown as VirtualSandbox\n\n return virtual\n },\n describePlacement(box: SandboxInstance): InProcessExecutorDescribePlacement {\n const sandboxId = (box as unknown as { id?: string }).id\n const meta = (box as VirtualSandbox).__inProcess\n return {\n kind: 'sibling',\n sandboxId,\n worktreePath: meta?.worktree?.path,\n harness: meta?.harness,\n }\n },\n }\n\n return {\n client,\n describe(): string {\n return `in-process (repoRoot=${options.repoRoot}, harnesses=[${harnesses.join(',')}]${\n options.testCmd ? `, testCmd=\"${options.testCmd}\"` : ''\n }${options.typecheckCmd ? `, typecheckCmd=\"${options.typecheckCmd}\"` : ''})`\n },\n }\n}\n\nasync function defaultRunPostCheck(\n cmd: string,\n cwd: string,\n signal?: AbortSignal,\n): Promise<{ exitCode: number; stdout: string; stderr: string }> {\n const { spawn } = await import('node:child_process')\n return new Promise((resolve, reject) => {\n // Run via sh -c so multi-word commands (\"pnpm test\") and shell features work.\n const child = spawn('sh', ['-c', cmd], { cwd, stdio: 'pipe' })\n let stdout = ''\n let stderr = ''\n child.stdout?.on('data', (c) => {\n stdout += String(c)\n })\n child.stderr?.on('data', (c) => {\n stderr += String(c)\n })\n if (signal) {\n const onAbort = () => {\n if (!child.killed) child.kill('SIGTERM')\n }\n if (signal.aborted) onAbort()\n else signal.addEventListener('abort', onAbort, { once: true })\n }\n const killTimer = setTimeout(() => {\n if (!child.killed) child.kill('SIGTERM')\n }, DEFAULT_POSTCHECK_TIMEOUT_MS)\n if (typeof (killTimer as { unref?: () => void }).unref === 'function') {\n ;(killTimer as { unref: () => void }).unref()\n }\n child.on('error', (err) => {\n clearTimeout(killTimer)\n reject(err)\n })\n child.on('close', (code) => {\n clearTimeout(killTimer)\n resolve({ exitCode: code ?? -1, stdout, stderr })\n })\n })\n}\n\nfunction tail(text: string, max: number): string {\n if (text.length <= max) return text\n return text.slice(text.length - max)\n}\n","/**\n * @experimental\n *\n * Helpers extracted from `bin.ts` so the env-detection + executor-selection\n * logic is unit-testable without spawning a subprocess. The bin imports from\n * here; tests import from here directly.\n */\n\nimport type { LoopSandboxClient } from '../loops'\nimport {\n createFleetWorkspaceExecutor,\n createSiblingSandboxExecutor,\n type DelegationExecutor,\n type FleetHandle,\n} from './executor'\nimport { createInProcessExecutor } from './in-process-executor'\nimport type { LocalHarness } from './local-harness'\n\n/** @experimental */\nexport interface DetectExecutorArgs {\n sandboxClient: LoopSandboxClient\n /** Raw env (defaults to `process.env`). Pass an explicit map for tests. */\n env?: Record<string, string | undefined>\n /**\n * Override how a fleet handle is resolved from the client + fleet id. The\n * default reads `client.fleets.get(fleetId)` and validates the returned\n * shape against the structural `FleetHandle` contract.\n */\n resolveFleet?: (client: LoopSandboxClient, fleetId: string) => Promise<FleetHandle>\n}\n\n/**\n * Pick the right executor for an MCP server invocation based on env vars.\n *\n * - `TANGLE_FLEET_ID` set → fleet-workspace placement; resolves the handle\n * via `sandboxClient.fleets.get(...)`.\n * - Otherwise → sibling-sandbox placement; each delegation creates a fresh\n * sandbox via `sandboxClient.create(...)`.\n *\n * Fails loud (throws) when fleet mode is requested but the SDK shape is\n * incompatible — the operator chose fleet semantics, silently degrading to\n * sibling mode would lie about workspace topology.\n *\n * @experimental\n */\nexport async function detectExecutor(args: DetectExecutorArgs): Promise<DelegationExecutor> {\n const env = args.env ?? process.env\n\n // In-process (Phase 2.8): parent harness sets AGENT_RUNTIME_IN_SANDBOX=1\n // and points us at the workspace root. Highest-priority — when this is\n // set, delegations spawn local harness CLIs on git worktrees in the\n // SAME filesystem instead of provisioning sibling sandboxes.\n if (env.AGENT_RUNTIME_IN_SANDBOX === '1') {\n const repoRoot = env.AGENT_RUNTIME_REPO_ROOT?.trim()\n if (!repoRoot) {\n throw new Error(\n 'agent-runtime-mcp: AGENT_RUNTIME_IN_SANDBOX=1 requires AGENT_RUNTIME_REPO_ROOT to point at the workspace root',\n )\n }\n return createInProcessExecutor({\n repoRoot,\n harnesses: parseHarnesses(env.AGENT_RUNTIME_LOCAL_HARNESSES),\n testCmd: env.AGENT_RUNTIME_TEST_CMD?.trim() || undefined,\n typecheckCmd: env.AGENT_RUNTIME_TYPECHECK_CMD?.trim() || undefined,\n })\n }\n\n const fleetId = parseFleetId(env.TANGLE_FLEET_ID)\n if (!fleetId) {\n return createSiblingSandboxExecutor({ client: args.sandboxClient })\n }\n const resolveFleet = args.resolveFleet ?? defaultResolveFleet\n const fleet = await resolveFleet(args.sandboxClient, fleetId)\n const excludeMachineIds = parseList(env.TANGLE_FLEET_EXCLUDE_MACHINES)\n return createFleetWorkspaceExecutor({\n fleet,\n excludeMachineIds,\n })\n}\n\nconst KNOWN_HARNESSES: ReadonlyArray<LocalHarness> = ['claude', 'codex', 'opencode']\n\nfunction parseHarnesses(raw: string | undefined): ReadonlyArray<LocalHarness> | undefined {\n if (!raw) return undefined\n const parts = raw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n if (parts.length === 0) return undefined\n for (const part of parts) {\n if (!KNOWN_HARNESSES.includes(part as LocalHarness)) {\n throw new Error(\n `agent-runtime-mcp: AGENT_RUNTIME_LOCAL_HARNESSES contains unknown harness \"${part}\". Expected: ${KNOWN_HARNESSES.join(', ')}.`,\n )\n }\n }\n return parts as LocalHarness[]\n}\n\ninterface FleetsApi {\n get(fleetId: string): Promise<unknown>\n}\n\nasync function defaultResolveFleet(\n sandboxClient: LoopSandboxClient,\n fleetId: string,\n): Promise<FleetHandle> {\n const fleets = (sandboxClient as unknown as { fleets?: FleetsApi }).fleets\n if (!fleets || typeof fleets.get !== 'function') {\n throw new Error(\n 'agent-runtime-mcp: the configured sandbox client does not expose `.fleets.get`; upgrade @tangle-network/sandbox to >= 0.2.1 or unset TANGLE_FLEET_ID.',\n )\n }\n const raw = await fleets.get(fleetId)\n if (!raw || typeof raw !== 'object') {\n throw new Error(`agent-runtime-mcp: fleets.get(${fleetId}) returned no handle`)\n }\n const handle = raw as Partial<FleetHandle>\n if (typeof handle.fleetId !== 'string' || !Array.isArray(handle.ids)) {\n throw new Error(\n `agent-runtime-mcp: fleet handle for ${fleetId} is missing fleetId/ids — incompatible sandbox SDK shape`,\n )\n }\n if (typeof handle.sandbox !== 'function') {\n throw new Error(\n `agent-runtime-mcp: fleet handle for ${fleetId} is missing sandbox(machineId) — incompatible sandbox SDK shape`,\n )\n }\n return handle as FleetHandle\n}\n\nfunction parseFleetId(raw: string | undefined): string | undefined {\n if (typeof raw !== 'string') return undefined\n const trimmed = raw.trim()\n return trimmed.length > 0 ? trimmed : undefined\n}\n\nfunction parseList(raw: string | undefined): string[] | undefined {\n if (!raw) return undefined\n const list = raw\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean)\n return list.length > 0 ? list : undefined\n}\n","/**\n * @experimental\n *\n * Stdio JSON-RPC MCP server exposing the 5 delegation tools to sandbox\n * coding-harness agents (claude-code, codex, opencode, ...).\n *\n * The server is transport-bound but topology-free: tool execution is\n * delegated to handler functions composed from a queue, a feedback\n * store, and per-profile run delegates. Consumers wire those at\n * construction time. The `agent-runtime-mcp` bin spins up a default\n * configuration for the common case (real sandbox client + coder).\n *\n * Wire protocol: line-delimited JSON-RPC 2.0 over stdio. Each line is\n * one request; each response is one line. `tools/list` and `tools/call`\n * mirror the MCP 2024-11-05 spec; we do not pull in\n * `@modelcontextprotocol/sdk` to keep the dependency footprint zero.\n */\n\nimport { createInterface, type Interface as ReadlineInterface } from 'node:readline'\nimport { Readable, Writable } from 'node:stream'\nimport type { CoderDelegate, ResearcherDelegate } from './delegates'\nimport { type FeedbackStore, InMemoryFeedbackStore } from './feedback-store'\nimport { DelegationTaskQueue } from './task-queue'\nimport {\n createDelegateCodeHandler,\n DELEGATE_CODE_DESCRIPTION,\n DELEGATE_CODE_INPUT_SCHEMA,\n DELEGATE_CODE_TOOL_NAME,\n} from './tools/delegate-code'\nimport {\n createDelegateFeedbackHandler,\n DELEGATE_FEEDBACK_DESCRIPTION,\n DELEGATE_FEEDBACK_INPUT_SCHEMA,\n DELEGATE_FEEDBACK_TOOL_NAME,\n} from './tools/delegate-feedback'\nimport {\n createDelegateResearchHandler,\n DELEGATE_RESEARCH_DESCRIPTION,\n DELEGATE_RESEARCH_INPUT_SCHEMA,\n DELEGATE_RESEARCH_TOOL_NAME,\n} from './tools/delegate-research'\nimport {\n createDelegationHistoryHandler,\n DELEGATION_HISTORY_DESCRIPTION,\n DELEGATION_HISTORY_INPUT_SCHEMA,\n DELEGATION_HISTORY_TOOL_NAME,\n} from './tools/delegation-history'\nimport {\n createDelegationStatusHandler,\n DELEGATION_STATUS_DESCRIPTION,\n DELEGATION_STATUS_INPUT_SCHEMA,\n DELEGATION_STATUS_TOOL_NAME,\n} from './tools/delegation-status'\n\n/** @experimental */\nexport interface McpServerOptions {\n /** Required to enable delegate_code. */\n coderDelegate?: CoderDelegate\n /**\n * Required to enable delegate_research. The substrate cannot ship a\n * default — wire one that closes over your `runLoop` + a\n * researcher profile (typically `@tangle-network/agent-knowledge`'s\n * `researcherProfile` / `multiHarnessResearcherFanout`).\n */\n researcherDelegate?: ResearcherDelegate\n /** Override the default in-memory feedback store. */\n feedbackStore?: FeedbackStore\n /** Override the default in-memory task queue. */\n queue?: DelegationTaskQueue\n /** Server display name surfaced via `initialize`. Default `'agent-runtime-mcp'`. */\n serverName?: string\n /** Server version surfaced via `initialize`. Default = the package version baked at build time. */\n serverVersion?: string\n}\n\n/** @experimental */\nexport interface McpToolDescriptor {\n name: string\n description: string\n inputSchema: Record<string, unknown>\n handler: (raw: unknown) => Promise<unknown>\n}\n\n/** @experimental */\nexport interface McpServer {\n /** Tools currently registered (depend on which delegates were wired). */\n readonly tools: ReadonlyMap<string, McpToolDescriptor>\n /** The underlying queue — exposed so tests can introspect it. */\n readonly queue: DelegationTaskQueue\n /** The feedback store — exposed for the same reason. */\n readonly feedbackStore: FeedbackStore\n /** Handle a single parsed JSON-RPC message. Returns the response object (or `null` for notifications). */\n handle(message: JsonRpcMessage): Promise<JsonRpcResponse | null>\n /** Drive the server on a stdio-shaped transport until `stop()` is called. */\n serve(transport?: McpTransport): Promise<void>\n /** Stop a `serve` call. Subsequent requests are rejected. */\n stop(): void\n}\n\n/** @experimental */\nexport interface McpTransport {\n input: NodeJS.ReadableStream\n output: NodeJS.WritableStream\n}\n\n/** @experimental */\nexport interface JsonRpcMessage {\n jsonrpc: '2.0'\n id?: number | string | null\n method: string\n params?: unknown\n}\n\n/** @experimental */\nexport interface JsonRpcResponse {\n jsonrpc: '2.0'\n id: number | string | null\n result?: unknown\n error?: { code: number; message: string; data?: unknown }\n}\n\nconst PROTOCOL_VERSION = '2024-11-05'\nconst DEFAULT_SERVER_NAME = 'agent-runtime-mcp'\nconst DEFAULT_SERVER_VERSION = '0.22.0'\n\n/** @experimental */\nexport function createMcpServer(options: McpServerOptions = {}): McpServer {\n const queue = options.queue ?? new DelegationTaskQueue()\n const feedbackStore = options.feedbackStore ?? new InMemoryFeedbackStore()\n const serverName = options.serverName ?? DEFAULT_SERVER_NAME\n const serverVersion = options.serverVersion ?? DEFAULT_SERVER_VERSION\n\n const tools = new Map<string, McpToolDescriptor>()\n\n if (options.coderDelegate) {\n tools.set(DELEGATE_CODE_TOOL_NAME, {\n name: DELEGATE_CODE_TOOL_NAME,\n description: DELEGATE_CODE_DESCRIPTION,\n inputSchema: DELEGATE_CODE_INPUT_SCHEMA as unknown as Record<string, unknown>,\n handler: createDelegateCodeHandler({ queue, delegate: options.coderDelegate }),\n })\n }\n if (options.researcherDelegate) {\n tools.set(DELEGATE_RESEARCH_TOOL_NAME, {\n name: DELEGATE_RESEARCH_TOOL_NAME,\n description: DELEGATE_RESEARCH_DESCRIPTION,\n inputSchema: DELEGATE_RESEARCH_INPUT_SCHEMA as unknown as Record<string, unknown>,\n handler: createDelegateResearchHandler({ queue, delegate: options.researcherDelegate }),\n })\n }\n tools.set(DELEGATE_FEEDBACK_TOOL_NAME, {\n name: DELEGATE_FEEDBACK_TOOL_NAME,\n description: DELEGATE_FEEDBACK_DESCRIPTION,\n inputSchema: DELEGATE_FEEDBACK_INPUT_SCHEMA as unknown as Record<string, unknown>,\n handler: createDelegateFeedbackHandler({ queue, store: feedbackStore }),\n })\n tools.set(DELEGATION_STATUS_TOOL_NAME, {\n name: DELEGATION_STATUS_TOOL_NAME,\n description: DELEGATION_STATUS_DESCRIPTION,\n inputSchema: DELEGATION_STATUS_INPUT_SCHEMA as unknown as Record<string, unknown>,\n handler: createDelegationStatusHandler({ queue }),\n })\n tools.set(DELEGATION_HISTORY_TOOL_NAME, {\n name: DELEGATION_HISTORY_TOOL_NAME,\n description: DELEGATION_HISTORY_DESCRIPTION,\n inputSchema: DELEGATION_HISTORY_INPUT_SCHEMA as unknown as Record<string, unknown>,\n handler: createDelegationHistoryHandler({ queue }),\n })\n\n let stopped = false\n let activeReadline: ReadlineInterface | undefined\n\n async function handle(message: JsonRpcMessage): Promise<JsonRpcResponse | null> {\n if (stopped) {\n return rpcError(message.id ?? null, -32099, 'server stopped')\n }\n if (message.method === 'initialize') {\n return rpcResult(message.id ?? null, {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: { tools: {} },\n serverInfo: { name: serverName, version: serverVersion },\n })\n }\n if (message.method === 'notifications/initialized') {\n // MCP clients send this after the handshake; it has no id and expects\n // no response.\n return null\n }\n if (message.method === 'tools/list') {\n return rpcResult(message.id ?? null, {\n tools: [...tools.values()].map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n })),\n })\n }\n if (message.method === 'tools/call') {\n const params = (message.params ?? {}) as { name?: unknown; arguments?: unknown }\n const name = typeof params.name === 'string' ? params.name : ''\n const tool = tools.get(name)\n if (!tool) {\n return rpcError(message.id ?? null, -32601, `unknown tool: ${name}`)\n }\n try {\n const output = await tool.handler(params.arguments ?? {})\n return rpcResult(message.id ?? null, {\n content: [{ type: 'text', text: JSON.stringify(output) }],\n structuredContent: output,\n isError: false,\n })\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err)\n const code = err instanceof TypeError || err instanceof RangeError ? -32602 : -32000\n return rpcError(message.id ?? null, code, reason)\n }\n }\n if (message.id === undefined || message.id === null) return null\n return rpcError(message.id, -32601, `unknown method: ${message.method}`)\n }\n\n async function serve(transport?: McpTransport): Promise<void> {\n const input = transport?.input ?? process.stdin\n const output = transport?.output ?? process.stdout\n const rl = createInterface({ input, crlfDelay: Number.POSITIVE_INFINITY })\n activeReadline = rl\n return new Promise<void>((resolve, reject) => {\n rl.on('line', (line) => {\n const trimmed = line.trim()\n if (!trimmed) return\n let parsed: JsonRpcMessage | undefined\n try {\n parsed = JSON.parse(trimmed) as JsonRpcMessage\n } catch (err) {\n writeResponse(output, rpcError(null, -32700, `parse error: ${(err as Error).message}`))\n return\n }\n if (!parsed || parsed.jsonrpc !== '2.0' || typeof parsed.method !== 'string') {\n writeResponse(output, rpcError(parsed?.id ?? null, -32600, 'invalid request'))\n return\n }\n void handle(parsed).then((response) => {\n if (response) writeResponse(output, response)\n })\n })\n rl.on('close', () => resolve())\n rl.on('error', (err) => reject(err))\n if (stopped) {\n rl.close()\n resolve()\n }\n })\n }\n\n function stop(): void {\n stopped = true\n activeReadline?.close()\n activeReadline = undefined\n }\n\n return {\n tools,\n queue,\n feedbackStore,\n handle,\n serve,\n stop,\n }\n}\n\nfunction rpcResult(id: number | string | null, result: unknown): JsonRpcResponse {\n return { jsonrpc: '2.0', id, result }\n}\n\nfunction rpcError(\n id: number | string | null,\n code: number,\n message: string,\n data?: unknown,\n): JsonRpcResponse {\n return {\n jsonrpc: '2.0',\n id,\n error: data === undefined ? { code, message } : { code, message, data },\n }\n}\n\nfunction writeResponse(output: NodeJS.WritableStream, response: JsonRpcResponse): void {\n output.write(`${JSON.stringify(response)}\\n`)\n}\n\n/**\n * In-process pair of `Readable` + `Writable` streams suitable for driving\n * `server.serve(...)` from a test. Returns the agent-side stream (the\n * client writes to it) and the server-side stream (the test reads from it).\n *\n * @experimental\n */\nexport function createInProcessTransport(): {\n transport: McpTransport\n clientWrite(line: string): void\n clientClose(): void\n readServer(): Promise<JsonRpcResponse[]>\n} {\n const responses: JsonRpcResponse[] = []\n const input = new Readable({ read() {} })\n const output = new Writable({\n write(chunk, _enc, cb) {\n const text = chunk.toString('utf8')\n for (const line of text.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed) continue\n try {\n responses.push(JSON.parse(trimmed) as JsonRpcResponse)\n } catch {\n // Non-JSON output should never appear; drop it silently in the\n // test transport rather than crashing.\n }\n }\n cb()\n },\n })\n return {\n transport: { input, output },\n clientWrite(line: string) {\n input.push(`${line}\\n`)\n },\n clientClose() {\n input.push(null)\n },\n async readServer() {\n // Yield to the event loop a few times so async handlers drain.\n for (let i = 0; i < 5; i += 1) await new Promise((r) => setImmediate(r))\n return [...responses]\n },\n }\n}\n","/**\n * @experimental\n *\n * Trace context propagation for MCP subprocess.\n *\n * When the MCP server is launched as a child process by a sandbox harness,\n * the parent passes trace context via environment variables:\n *\n * TRACE_ID=<current-run-trace-id>\n * PARENT_SPAN_ID=<span-that-dispatched-the-delegation>\n *\n * The MCP server reads these at startup and uses them as the root of its\n * internal trace tree. All spans emitted by `runLoop` invocations inside\n * the MCP are children of the parent's delegation span.\n *\n * When these env vars are absent, the MCP generates a fresh trace root —\n * the server operates standalone without trace joining.\n */\n\nimport type { LoopTraceEmitter, LoopTraceEvent } from '../loops/types'\nimport type { OtelExporter } from '../otel-export'\nimport { buildLoopOtelSpans, createOtelExporter } from '../otel-export'\n\nexport interface TraceContext {\n /** Trace id inherited from the parent process, or a fresh one. */\n traceId: string\n /** Parent span id from the delegation that launched this MCP server. */\n parentSpanId?: string\n}\n\n/**\n * Read trace context from the process environment.\n * Returns a context with inherited ids or a freshly generated root.\n */\nexport function readTraceContextFromEnv(): TraceContext {\n const traceId = process.env.TRACE_ID || generateTraceId()\n const parentSpanId = process.env.PARENT_SPAN_ID || undefined\n return { traceId, parentSpanId }\n}\n\n/**\n * Create a LoopTraceEmitter that:\n * 1. Parents all spans under the inherited PARENT_SPAN_ID.\n * 2. Exports spans to OTEL when OTEL_EXPORTER_OTLP_ENDPOINT is set.\n *\n * Returns both the emitter and the optional exporter handle for shutdown.\n */\nexport function createPropagatingTraceEmitter(ctx: TraceContext): {\n emitter: LoopTraceEmitter\n exporter: OtelExporter | undefined\n context: TraceContext\n} {\n const exporter = createOtelExporter()\n\n // Buffer events per loop run, then emit the full nested span tree on\n // `loop.ended` so the topology hierarchy (loop → round → branch) reaches the\n // OTLP collector — not a flat list of zero-duration point spans. A run that\n // never reaches `loop.ended` (hard abort) drops its buffer; acceptable for\n // the short-lived MCP subprocess.\n const buffers = new Map<string, LoopTraceEvent[]>()\n\n const emitter: LoopTraceEmitter = {\n emit(event: LoopTraceEvent) {\n if (!exporter) return\n const buf = buffers.get(event.runId)\n if (buf) buf.push(event)\n else buffers.set(event.runId, [event])\n if (event.kind === 'loop.ended') {\n const events = buffers.get(event.runId) ?? [event]\n buffers.delete(event.runId)\n for (const span of buildLoopOtelSpans(events, ctx.traceId, ctx.parentSpanId)) {\n exporter.exportSpan(span)\n }\n }\n },\n }\n\n return { emitter, exporter, context: ctx }\n}\n\n/**\n * Build env vars to pass to a child MCP subprocess so it inherits the\n * current trace context.\n */\nexport function traceContextToEnv(ctx: TraceContext): Record<string, string> {\n const env: Record<string, string> = { TRACE_ID: ctx.traceId }\n if (ctx.parentSpanId) env.PARENT_SPAN_ID = ctx.parentSpanId\n return env\n}\n\nfunction generateTraceId(): string {\n const bytes = new Uint8Array(16)\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\n globalThis.crypto.getRandomValues(bytes)\n } else {\n for (let i = 0; i < 16; i++) bytes[i] = Math.floor(Math.random() * 256)\n }\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n"],"mappings":"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","names":["spawn"]}
@@ -1,4 +1,4 @@
1
- import { I as Iteration, D as Driver } from './types-B9O7l-ij.js';
1
+ import { I as Iteration, D as Driver } from './types-BrJKXXI8.js';
2
2
 
3
3
  /**
4
4
  * @experimental
@@ -41,10 +41,12 @@ type TopologyMove<Task> = {
41
41
  kind: 'refine';
42
42
  task: Task;
43
43
  rationale?: string;
44
+ parentIndex?: number;
44
45
  } | {
45
46
  kind: 'fanout';
46
47
  tasks: Task[];
47
48
  rationale?: string;
49
+ parentIndex?: number;
48
50
  } | {
49
51
  kind: 'stop';
50
52
  rationale?: string;
package/dist/index.d.ts CHANGED
@@ -2,14 +2,14 @@ import { AgentEvalError, KnowledgeReadinessReport, RunRecord, ControlEvalResult,
2
2
  export { AgentEvalError, AgentEvalErrorCode, ConfigError, ControlBudget, ControlDecision, ControlEvalResult, ControlRunResult, ControlStep, DataAcquisitionPlan, JudgeError, KnowledgeReadinessReport, KnowledgeRequirement, NotFoundError, RunRecord, ValidationError } from '@tangle-network/agent-eval';
3
3
  import { a as AgentBackendInput, b as AgentExecutionBackend, O as OpenAIChatTool, c as OpenAIChatToolChoice, d as AgentBackendContext, R as RuntimeStreamEvent, K as KnowledgeReadinessDecision, e as RunAgentTaskOptions, f as AgentTaskRunResult, g as RunAgentTaskStreamOptions, h as AgentRuntimeEvent, i as AgentTaskStatus, j as RuntimeSessionStore, k as RuntimeSession } from './types-CsCCryln.js';
4
4
  export { l as AgentAdapter, m as AgentKnowledgeProvider, n as AgentRuntimeEventSink, o as AgentTaskContext, A as AgentTaskSpec, B as BackendErrorDetail } from './types-CsCCryln.js';
5
- export { C as CoderLoopRunnerOptions, D as DELEGATED_LOOP_MODES, a as DelegatedLoopMode, b as DelegatedLoopRegistry, c as DelegatedLoopResult, d as DelegatedLoopRunner, e as DynamicLoopRunnerOptions, L as LoopRunnerCliArgs, f as LoopRunnerCliResult, R as ResearchLoopResult, g as ResearchLoopRunnerOptions, h as RunDelegatedLoopOptions, V as VetoedFact, i as auditLoopRunner, j as coderLoopRunner, k as dynamicLoopRunner, l as isDelegatedLoopMode, p as parseLoopRunnerArgv, r as researchLoopRunner, m as reviewLoopRunner, n as runDelegatedLoop, o as runLoopRunnerCli, s as selfImproveLoopRunner } from './loop-runner-bin-DgZj0zfJ.js';
5
+ export { C as CoderLoopRunnerOptions, D as DELEGATED_LOOP_MODES, a as DelegatedLoopMode, b as DelegatedLoopRegistry, c as DelegatedLoopResult, d as DelegatedLoopRunner, e as DynamicLoopRunnerOptions, L as LoopRunnerCliArgs, f as LoopRunnerCliResult, R as ResearchLoopResult, g as ResearchLoopRunnerOptions, h as RunDelegatedLoopOptions, V as VetoedFact, i as auditLoopRunner, j as coderLoopRunner, k as dynamicLoopRunner, l as isDelegatedLoopMode, p as parseLoopRunnerArgv, r as researchLoopRunner, m as reviewLoopRunner, n as runDelegatedLoop, o as runLoopRunnerCli, s as selfImproveLoopRunner } from './loop-runner-bin-DYRzk2cT.js';
6
6
  export { E as EvalRunEvent, b as EvalRunGeneration, c as EvalRunsExportConfig, d as EvalRunsExportResult, I as INTELLIGENCE_WIRE_VERSION, e as OtelAttribute, f as OtelExportConfig, O as OtelExporter, g as OtelSpan, h as buildLoopOtelSpans, i as createOtelExporter, j as exportEvalRuns, l as loopEventToOtelSpan, m as mcpToolsForRuntimeMcp, a as mcpToolsForRuntimeMcpSubset } from './otel-export-xgf4J6bo.js';
7
- export { R as RuntimeRunHandle, p as RuntimeRunPersistenceAdapter, q as RuntimeRunRow, s as startRuntimeRun } from './types-B9O7l-ij.js';
7
+ export { R as RuntimeRunHandle, p as RuntimeRunPersistenceAdapter, q as RuntimeRunRow, s as startRuntimeRun } from './types-BrJKXXI8.js';
8
8
  import '@tangle-network/agent-eval/campaign';
9
9
  import './types-p8dWBIXL.js';
10
10
  import './optimize-prompt-D-urF2wW.js';
11
- import './dynamic-DcrwVGuV.js';
12
- import './kb-gate-YdPNEagq.js';
11
+ import './dynamic-CazTl_Zp.js';
12
+ import './kb-gate-NzOJSnOk.js';
13
13
  import './profiles.js';
14
14
  import '@tangle-network/sandbox';
15
15
 
package/dist/index.js CHANGED
@@ -10,22 +10,23 @@ import {
10
10
  runDelegatedLoop,
11
11
  runLoopRunnerCli,
12
12
  selfImproveLoopRunner
13
- } from "./chunk-AXWGLYSF.js";
13
+ } from "./chunk-4GI7C36B.js";
14
14
  import "./chunk-XBUG326M.js";
15
15
  import "./chunk-VOX6Z3II.js";
16
+ import {
17
+ mcpToolsForRuntimeMcp,
18
+ mcpToolsForRuntimeMcpSubset
19
+ } from "./chunk-NRZOXCJK.js";
16
20
  import {
17
21
  INTELLIGENCE_WIRE_VERSION,
18
22
  buildLoopOtelSpans,
19
23
  createOtelExporter,
20
24
  exportEvalRuns,
21
- loopEventToOtelSpan,
22
- mcpToolsForRuntimeMcp,
23
- mcpToolsForRuntimeMcpSubset
24
- } from "./chunk-7ZECSZ3C.js";
25
- import "./chunk-HSX6PFZR.js";
25
+ loopEventToOtelSpan
26
+ } from "./chunk-HVYOHJHK.js";
26
27
  import "./chunk-FNMGYYSS.js";
27
- import "./chunk-VLXRXMTF.js";
28
- import "./chunk-7JBDJQLO.js";
28
+ import "./chunk-FJ4GDNVN.js";
29
+ import "./chunk-OISRXLWI.js";
29
30
  import "./chunk-3HMHSN22.js";
30
31
  import "./chunk-PY6NMZYX.js";
31
32
  import {