@tangle-network/agent-runtime 0.20.4 → 0.21.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp/executor.ts","../src/mcp/bin-helpers.ts","../src/mcp/delegates.ts","../src/mcp/feedback-store.ts","../src/mcp/task-queue.ts","../src/mcp/tools/delegate-code.ts","../src/mcp/tools/delegate-feedback.ts","../src/mcp/tools/delegate-research.ts","../src/mcp/tools/delegation-history.ts","../src/mcp/tools/delegation-status.ts","../src/mcp/server.ts"],"sourcesContent":["/**\n * @experimental\n *\n * Delegation executors — the layer between MCP delegates and the sandbox\n * substrate. Each executor exposes a {@link LoopSandboxClient} the kernel\n * consumes plus a placement tag so the trace pipeline can correlate workers\n * with their physical placement.\n *\n * Two implementations ship in-box:\n *\n * - {@link createSiblingSandboxExecutor} — every delegation spawns a fresh\n * sandbox sibling to the caller. Default when the MCP server runs as a\n * standalone CLI mounted outside a fleet.\n *\n * - {@link createFleetWorkspaceExecutor} — delegations dispatch onto machines\n * in the caller's existing fleet so worker diffs land directly on the\n * caller's filesystem (the fleet's shared workspace). Selected when the\n * parent sandbox passes `TANGLE_FLEET_ID` into the MCP server's env.\n */\n\nimport type { CreateSandboxOptions, SandboxInstance } from '@tangle-network/sandbox'\nimport type { LoopSandboxClient, LoopSandboxPlacement } from '../loops'\n\n/** @experimental */\nexport interface DelegationExecutor {\n /** Sandbox client the kernel calls. Returned with `describePlacement` set. */\n readonly client: LoopSandboxClient\n /** Best-effort one-liner used in stderr boot logs and diagnostics. */\n describe(): string\n}\n\n/** @experimental */\nexport interface SiblingSandboxExecutorOptions {\n client: LoopSandboxClient\n}\n\n/**\n * Wrap a raw sandbox SDK client so the kernel emits\n * `loop.iteration.dispatch` events with `{ placement: 'sibling', sandboxId }`.\n *\n * The returned client `.create()` delegates to the underlying client; the\n * only added behavior is a `describePlacement` tag the kernel reads.\n *\n * @experimental\n */\nexport function createSiblingSandboxExecutor(\n options: SiblingSandboxExecutorOptions,\n): DelegationExecutor {\n const underlying = options.client\n const client: LoopSandboxClient = {\n create(opts?: CreateSandboxOptions): Promise<SandboxInstance> {\n return underlying.create(opts)\n },\n describePlacement(box: SandboxInstance): LoopSandboxPlacement {\n return { kind: 'sibling', sandboxId: readId(box) }\n },\n }\n return {\n client,\n describe(): string {\n return 'sibling-sandbox (each delegation = fresh sandbox via client.create)'\n },\n }\n}\n\n/**\n * Minimal `SandboxFleet` surface the fleet executor calls. Declared\n * structurally so tests can pass an in-memory stub without instantiating the\n * sandbox SDK.\n *\n * @experimental\n */\nexport interface FleetHandle {\n readonly fleetId: string\n /** Machine ids in dispatch-eligible order. The executor round-robins. */\n readonly ids: ReadonlyArray<string>\n /** Resolve a machine id to its `SandboxInstance` — that machine is mounted\n * on the fleet's shared workspace, so any diff the worker writes lands on\n * every other fleet machine's filesystem too. */\n sandbox(machineId: string): Promise<SandboxInstance>\n}\n\n/** @experimental */\nexport interface FleetWorkspaceExecutorOptions {\n fleet: FleetHandle\n /**\n * Override the machine-selection policy. Default = round-robin across\n * `fleet.ids`, skipping the optional `excludeMachineIds` set (typically the\n * coordinator machine the MCP server is running on).\n */\n selectMachine?: (call: { callIndex: number; ids: ReadonlyArray<string> }) => string\n /**\n * Machine ids to skip during default round-robin. Set to the caller's own\n * machineId so workers don't compete with the orchestrator on the same VM.\n */\n excludeMachineIds?: ReadonlyArray<string>\n}\n\n/**\n * Build an executor that resolves each delegated iteration to an existing\n * machine in `fleet`. The fleet's shared-workspace policy means the worker\n * machine sees the caller's filesystem — diffs land in-place with no\n * cross-sandbox copy step.\n *\n * @experimental\n */\nexport function createFleetWorkspaceExecutor(\n options: FleetWorkspaceExecutorOptions,\n): DelegationExecutor {\n const fleet = options.fleet\n const exclude = new Set(options.excludeMachineIds ?? [])\n let callIndex = 0\n // machineId-by-sandboxId, populated as we resolve machines so\n // `describePlacement` can recover the assignment from the SandboxInstance\n // the kernel hands back.\n const placementBySandboxId = new Map<string, { machineId: string }>()\n\n const client: LoopSandboxClient = {\n async create(): Promise<SandboxInstance> {\n const ids = fleet.ids.filter((id) => !exclude.has(id))\n if (ids.length === 0) {\n throw new Error(\n `agent-runtime: fleet ${fleet.fleetId} has no eligible worker machines (ids=[${fleet.ids.join(',')}], excluded=[${[...exclude].join(',')}])`,\n )\n }\n const selector = options.selectMachine\n const machineId = selector ? selector({ callIndex, ids }) : ids[callIndex % ids.length]\n callIndex += 1\n if (typeof machineId !== 'string' || machineId.length === 0) {\n throw new Error('agent-runtime: fleet executor selectMachine returned an empty machine id')\n }\n const box = await fleet.sandbox(machineId)\n const sandboxId = readId(box)\n if (sandboxId) placementBySandboxId.set(sandboxId, { machineId })\n return box\n },\n describePlacement(box: SandboxInstance): LoopSandboxPlacement {\n const sandboxId = readId(box)\n const recorded = sandboxId ? placementBySandboxId.get(sandboxId) : undefined\n return {\n kind: 'fleet',\n sandboxId,\n fleetId: fleet.fleetId,\n machineId: recorded?.machineId,\n }\n },\n }\n\n return {\n client,\n describe(): string {\n const excluded = exclude.size > 0 ? ` (excluded=[${[...exclude].join(',')}])` : ''\n return `fleet-workspace (fleetId=${fleet.fleetId}, machines=[${fleet.ids.join(',')}]${excluded})`\n },\n }\n}\n\nfunction readId(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","/**\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'\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 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\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 * Delegate factories — the layer between MCP tool handlers and the\n * underlying `runLoop` runners.\n *\n * The MCP server is profile-agnostic: it owns the task queue + feedback\n * store + transport. Each `*Delegate` is the closure that the queue\n * invokes when a task runs. Consumers can override either delegate to\n * inject custom drivers, mocks, fleet-aware dispatchers, etc.\n *\n * The default coder delegate is wired here because we own\n * `coderProfile` / `multiHarnessCoderFanout`. The default researcher\n * delegate is **not** wired in this file — `agent-knowledge` cannot be\n * imported from `agent-runtime` without inducing a cycle. Consumers\n * pass `researcherDelegate` explicitly when constructing the server.\n */\n\nimport type { LoopSandboxClient } from '../loops'\nimport { runLoop } from '../loops'\nimport { coderProfile, multiHarnessCoderFanout } from '../profiles/coder'\nimport { createSiblingSandboxExecutor, type DelegationExecutor } from './executor'\nimport type {\n CoderTask,\n DelegateCodeArgs,\n DelegateResearchArgs,\n DelegationProgress,\n ResearchOutputShape,\n} from './types'\n\n/** @experimental */\nexport interface DelegateRunCtx {\n signal: AbortSignal\n report(progress: DelegationProgress): void\n}\n\n/** @experimental */\nexport type CoderDelegate = (\n args: DelegateCodeArgs,\n ctx: DelegateRunCtx,\n) => Promise<import('../profiles/coder').CoderOutput>\n\n/** @experimental */\nexport type ResearcherDelegate = (\n args: DelegateResearchArgs,\n ctx: DelegateRunCtx,\n) => Promise<ResearchOutputShape>\n\n/** @experimental */\nexport interface CreateDefaultCoderDelegateOptions {\n /**\n * Execution placement. Pass a {@link DelegationExecutor} (sibling or fleet)\n * to control where worker iterations land. `sandboxClient` is a\n * convenience shorthand that wraps the client in a sibling executor — pass\n * one or the other, not both.\n */\n executor?: DelegationExecutor\n /**\n * Convenience shorthand for sibling placement. Equivalent to\n * `executor: createSiblingSandboxExecutor({ client: sandboxClient })`.\n */\n sandboxClient?: LoopSandboxClient\n /** Default `['claude-code', 'codex', 'opencode/zai-coding-plan/glm-5.1']` when variants > 1. */\n fanoutHarnesses?: string[]\n /** Hard cap on the kernel's per-batch concurrency. Default 4. */\n maxConcurrency?: number\n}\n\n/**\n * Build a coder delegate that drives `runLoop` against the project's\n * sandbox client + coder profile. When `args.variants > 1` it switches\n * to the multi-harness fanout topology.\n *\n * @experimental\n */\nexport function createDefaultCoderDelegate(\n options: CreateDefaultCoderDelegateOptions,\n): CoderDelegate {\n const executor = resolveExecutor(options)\n const sandboxClient = executor.client\n const fanoutHarnesses = options.fanoutHarnesses\n const maxConcurrency = options.maxConcurrency ?? 4\n return async (args, ctx) => {\n const task: CoderTask = {\n goal: buildCoderGoal(args),\n repoRoot: args.repoRoot,\n testCmd: args.config?.testCmd,\n typecheckCmd: args.config?.typecheckCmd,\n forbiddenPaths: args.config?.forbiddenPaths,\n maxDiffLines: args.config?.maxDiffLines,\n }\n const variants = Math.max(1, Math.trunc(args.variants ?? 1))\n ctx.report({ iteration: 0, phase: 'starting' })\n if (variants <= 1) {\n const { agentRunSpec, output, validator } = coderProfile({ task })\n const result = await runLoop({\n driver: singleShotDriver,\n agentRun: agentRunSpec,\n output,\n validator,\n task,\n ctx: { sandboxClient, signal: ctx.signal },\n maxIterations: 1,\n maxConcurrency,\n })\n const winner = result.winner\n if (!winner) {\n throw new Error('coder delegate produced no winner')\n }\n ctx.report({ iteration: 1, phase: 'completed' })\n return winner.output\n }\n const fanout = multiHarnessCoderFanout(\n fanoutHarnesses && fanoutHarnesses.length > 0\n ? { harnesses: fanoutHarnesses.slice(0, variants) }\n : { harnesses: undefined },\n )\n const agentRuns = fanout.agentRuns.slice(0, variants)\n const result = await runLoop({\n driver: fanout.driver,\n agentRuns,\n output: fanout.output,\n validator: fanout.validator,\n task,\n ctx: { sandboxClient, signal: ctx.signal },\n maxIterations: variants,\n maxConcurrency: Math.min(maxConcurrency, variants),\n })\n const winner = result.winner\n if (!winner) {\n throw new Error('coder delegate fanout produced no winner')\n }\n ctx.report({ iteration: agentRuns.length, phase: 'completed' })\n return winner.output\n }\n}\n\nfunction buildCoderGoal(args: DelegateCodeArgs): string {\n if (!args.contextHint) return args.goal\n return [args.goal, '', '## Context', args.contextHint].join('\\n')\n}\n\nfunction resolveExecutor(options: CreateDefaultCoderDelegateOptions): DelegationExecutor {\n if (options.executor && options.sandboxClient) {\n throw new Error('createDefaultCoderDelegate: pass exactly one of `executor` or `sandboxClient`')\n }\n if (options.executor) return options.executor\n if (options.sandboxClient) {\n return createSiblingSandboxExecutor({ client: options.sandboxClient })\n }\n throw new Error('createDefaultCoderDelegate: `executor` or `sandboxClient` is required')\n}\n\n/**\n * Single-shot driver — plan one task on iteration 0, stop after one\n * iteration. Used by the coder delegate when `variants <= 1`. Keeps the\n * runLoop kernel-level accounting (timing, cost, trace emission) while\n * skipping fanout/refine topology overhead.\n */\nconst singleShotDriver = {\n name: 'mcp-single-shot',\n async plan<Task>(task: Task, history: ReadonlyArray<unknown>): Promise<Task[]> {\n return history.length === 0 ? [task] : []\n },\n decide(history: ReadonlyArray<unknown>): 'pick-winner' | 'fail' {\n return history.length > 0 ? 'pick-winner' : 'fail'\n },\n}\n","/**\n * @experimental\n *\n * Feedback persistence surface for the MCP layer.\n *\n * The substrate cannot import `@tangle-network/agent-knowledge` (it would\n * induce a dependency cycle), so the store is an abstract interface. The\n * default implementation is in-memory; consumers wire their own adapter\n * (a real KbStore-backed sink, an HTTP relay to gtm-agent's knowledge\n * service, etc.) via `createMcpServer({ feedbackStore })`.\n *\n * Feedback events are append-only: every rating is a new event with a\n * fresh id, even when the same delegation is rated multiple times. The\n * caller decides how to roll up scores downstream.\n */\n\nimport type { DelegateFeedbackArgs, DelegationFeedbackSnapshot } from './types'\n\n/** @experimental */\nexport interface FeedbackEvent {\n id: string\n refersTo: DelegateFeedbackArgs['refersTo']\n rating: DelegateFeedbackArgs['rating']\n by: DelegateFeedbackArgs['by']\n capturedAt: string\n namespace?: string\n}\n\n/** @experimental */\nexport interface FeedbackStore {\n /** Append a new event. Never dedupes — every rating is its own event. */\n put(event: FeedbackEvent): Promise<void>\n /**\n * List events filtered by `namespace`. When `namespace` is omitted, list\n * across all namespaces. Returns events in insertion order.\n */\n list(filter?: { namespace?: string; refersToRef?: string }): Promise<FeedbackEvent[]>\n}\n\n/** @experimental */\nexport class InMemoryFeedbackStore implements FeedbackStore {\n private readonly events: FeedbackEvent[] = []\n\n async put(event: FeedbackEvent): Promise<void> {\n this.events.push({ ...event })\n }\n\n async list(filter: { namespace?: string; refersToRef?: string } = {}): Promise<FeedbackEvent[]> {\n let out = this.events\n if (filter.namespace !== undefined) {\n out = out.filter((event) => event.namespace === filter.namespace)\n }\n if (filter.refersToRef !== undefined) {\n out = out.filter((event) => event.refersTo.ref === filter.refersToRef)\n }\n return out.map((event) => ({ ...event }))\n }\n}\n\n/**\n * Project a `FeedbackEvent` down to the snapshot shape carried on\n * `delegation_history` entries.\n *\n * @experimental\n */\nexport function eventToSnapshot(event: FeedbackEvent): DelegationFeedbackSnapshot {\n const snap: DelegationFeedbackSnapshot = {\n id: event.id,\n score: event.rating.score,\n by: event.by,\n notes: event.rating.notes,\n capturedAt: event.capturedAt,\n }\n if (event.rating.label) snap.label = event.rating.label\n return snap\n}\n","/**\n * @experimental\n *\n * In-memory state for async MCP delegations. State machine:\n *\n * pending → running → completed | failed\n * ↘ cancelled (from any non-terminal state via cancel())\n *\n * Each `submit` returns a `taskId` immediately and kicks the work off in the\n * background. The work function receives an `AbortSignal` the queue fires\n * when `cancel(taskId)` is called. The queue does NOT supervise runtime\n * timeouts — the underlying `runLoop` driver / sandbox imposes those.\n *\n * Idempotency: callers may supply an `idempotencyKey` (hash of the input).\n * A duplicate `submit` with a known key returns the existing task instead of\n * starting a new one. Mutated input → different key → different task.\n *\n * Persistent state (sqlite) is a Phase 2 follow-up. The README documents the\n * in-memory limitation explicitly so consumers know a worker restart drops\n * pending delegations.\n */\n\nimport type {\n DelegateCodeArgs,\n DelegateResearchArgs,\n DelegationError,\n DelegationFeedbackSnapshot,\n DelegationHistoryArgs,\n DelegationHistoryEntry,\n DelegationProfile,\n DelegationProgress,\n DelegationResultPayload,\n DelegationStatus,\n DelegationStatusResult,\n} from './types'\n\n/** @experimental */\nexport interface DelegationRecord {\n taskId: string\n profile: DelegationProfile\n namespace?: string\n args: DelegateCodeArgs | DelegateResearchArgs\n status: DelegationStatus\n progress?: DelegationProgress\n result?: DelegationResultPayload\n error?: DelegationError\n costUsd?: number\n startedAt: string\n completedAt?: string\n /** Sha-prefix hash of the canonical input — used for idempotency lookup. */\n idempotencyKey?: string\n /** Feedback events keyed by this delegation's taskId. */\n feedback: DelegationFeedbackSnapshot[]\n}\n\n/** @experimental */\nexport interface SubmitInput<Args extends DelegateCodeArgs | DelegateResearchArgs> {\n profile: DelegationProfile\n args: Args\n namespace?: string\n idempotencyKey?: string\n /**\n * Runs the underlying delegation. The queue passes a fresh `AbortSignal`\n * and a `report` channel for incremental progress updates. The function\n * MUST resolve with the typed `DelegationResultPayload['output']`; the\n * queue wraps it with the profile tag.\n */\n run: (ctx: {\n signal: AbortSignal\n report(progress: DelegationProgress): void\n }) => Promise<DelegationResultPayload['output']>\n}\n\n/** @experimental */\nexport interface SubmitOutput {\n taskId: string\n /** True when a prior matching `idempotencyKey` returned an existing record. */\n reused: boolean\n}\n\n/** @experimental */\nexport interface DelegationTaskQueueOptions {\n /** ID generator override; default `randomTaskId`. */\n generateId?: () => string\n /** Clock override; default `() => new Date().toISOString()`. */\n now?: () => string\n}\n\n/** @experimental */\nexport class DelegationTaskQueue {\n private readonly records = new Map<string, DelegationRecord>()\n private readonly controllers = new Map<string, AbortController>()\n private readonly byIdempotencyKey = new Map<string, string>()\n private readonly generateId: () => string\n private readonly now: () => string\n\n constructor(options: DelegationTaskQueueOptions = {}) {\n this.generateId = options.generateId ?? randomTaskId\n this.now = options.now ?? (() => new Date().toISOString())\n }\n\n /**\n * Kick off a delegation in the background. Returns immediately. The\n * `taskId` is queryable via `status` once this method returns.\n */\n submit<Args extends DelegateCodeArgs | DelegateResearchArgs>(\n input: SubmitInput<Args>,\n ): SubmitOutput {\n if (input.idempotencyKey) {\n const existing = this.byIdempotencyKey.get(input.idempotencyKey)\n if (existing && this.records.has(existing)) {\n return { taskId: existing, reused: true }\n }\n }\n const taskId = this.generateId()\n const controller = new AbortController()\n const record: DelegationRecord = {\n taskId,\n profile: input.profile,\n namespace: input.namespace,\n args: input.args,\n status: 'pending',\n startedAt: this.now(),\n feedback: [],\n idempotencyKey: input.idempotencyKey,\n }\n this.records.set(taskId, record)\n this.controllers.set(taskId, controller)\n if (input.idempotencyKey) this.byIdempotencyKey.set(input.idempotencyKey, taskId)\n\n // Fire-and-forget the run function. Errors flow into the record so the\n // status poll surfaces them; the promise itself is intentionally\n // unobserved by the queue.\n queueMicrotask(() => {\n this.execute(taskId, input, controller)\n })\n\n return { taskId, reused: false }\n }\n\n /**\n * Snapshot the current state of a delegation. Returns `undefined` for\n * unknown ids so callers can distinguish missing from terminal.\n */\n status(taskId: string): DelegationStatusResult | undefined {\n const record = this.records.get(taskId)\n if (!record) return undefined\n return toStatusResult(record)\n }\n\n /**\n * Abort an in-flight delegation. Returns `false` if the task is unknown\n * or already terminal. The underlying `run` function MUST honor the\n * abort signal for the cancel to take effect; the queue marks the\n * record `cancelled` regardless so a misbehaving runner cannot pin the\n * UI on `running` forever.\n */\n cancel(taskId: string): boolean {\n const record = this.records.get(taskId)\n if (!record) return false\n if (isTerminal(record.status)) return false\n const controller = this.controllers.get(taskId)\n controller?.abort()\n record.status = 'cancelled'\n record.completedAt = this.now()\n record.error = { message: 'cancelled by caller', kind: 'CancelledError' }\n return true\n }\n\n /**\n * Append a feedback event to the matching delegation. Returns `false`\n * when `ref` does not name a known taskId — the caller should still\n * record the feedback through a different surface (artifact/outcome\n * kinds are not queue-bound).\n */\n attachFeedback(taskId: string, snapshot: DelegationFeedbackSnapshot): boolean {\n const record = this.records.get(taskId)\n if (!record) return false\n record.feedback.push(snapshot)\n return true\n }\n\n /**\n * Query the recorded delegations. Returns entries newest-first (by\n * `startedAt`), truncated to `limit`.\n */\n history(args: DelegationHistoryArgs = {}): DelegationHistoryEntry[] {\n const limit = clampLimit(args.limit)\n const since = args.since ? Date.parse(args.since) : Number.NEGATIVE_INFINITY\n const out: DelegationHistoryEntry[] = []\n for (const record of this.records.values()) {\n if (args.namespace && record.namespace !== args.namespace) continue\n if (args.profile && record.profile !== args.profile) continue\n if (Number.isFinite(since) && Date.parse(record.startedAt) < since) continue\n out.push(toHistoryEntry(record))\n }\n out.sort((a, b) => b.startedAt.localeCompare(a.startedAt))\n return out.slice(0, limit)\n }\n\n /** Test-only — number of in-flight (non-terminal) records. */\n inflightCount(): number {\n let n = 0\n for (const record of this.records.values()) {\n if (!isTerminal(record.status)) n += 1\n }\n return n\n }\n\n private async execute<Args extends DelegateCodeArgs | DelegateResearchArgs>(\n taskId: string,\n input: SubmitInput<Args>,\n controller: AbortController,\n ): Promise<void> {\n const record = this.records.get(taskId)\n if (!record) return\n record.status = 'running'\n try {\n const output = await input.run({\n signal: controller.signal,\n report: (progress) => {\n if (record.status === 'running') record.progress = progress\n },\n })\n // `cancel()` may have flipped the status to `cancelled` while the\n // run promise was pending. Read the field through a widening\n // helper so the narrowed `'running'` type from the assignment\n // above does not exclude that case at compile time.\n if (currentStatus(record) === 'cancelled') return\n record.status = 'completed'\n record.completedAt = this.now()\n record.result = { profile: input.profile, output } as DelegationResultPayload\n } catch (err) {\n if (currentStatus(record) === 'cancelled') return\n record.status = 'failed'\n record.completedAt = this.now()\n record.error = errorToShape(err)\n } finally {\n this.controllers.delete(taskId)\n }\n }\n}\n\nfunction isTerminal(status: DelegationStatus): boolean {\n return status === 'completed' || status === 'failed' || status === 'cancelled'\n}\n\nfunction currentStatus(record: DelegationRecord): DelegationStatus {\n return record.status\n}\n\nfunction clampLimit(raw: number | undefined): number {\n if (!Number.isFinite(raw)) return 50\n const n = Math.trunc(raw as number)\n if (n <= 0) return 50\n return Math.min(n, 500)\n}\n\nfunction toStatusResult(record: DelegationRecord): DelegationStatusResult {\n const out: DelegationStatusResult = {\n taskId: record.taskId,\n profile: record.profile,\n status: record.status,\n startedAt: record.startedAt,\n }\n if (record.progress) out.progress = record.progress\n if (record.result) out.result = record.result\n if (record.error) out.error = record.error\n if (record.costUsd !== undefined) out.costUsd = record.costUsd\n if (record.completedAt) out.completedAt = record.completedAt\n return out\n}\n\nfunction toHistoryEntry(record: DelegationRecord): DelegationHistoryEntry {\n const entry: DelegationHistoryEntry = {\n taskId: record.taskId,\n profile: record.profile,\n args: record.args,\n status: record.status,\n startedAt: record.startedAt,\n }\n if (record.namespace) entry.namespace = record.namespace\n if (record.completedAt) entry.completedAt = record.completedAt\n if (record.costUsd !== undefined) entry.costUsd = record.costUsd\n if (record.feedback.length > 0) entry.feedback = [...record.feedback]\n return entry\n}\n\nfunction errorToShape(err: unknown): DelegationError {\n if (err instanceof Error) {\n return { message: err.message, kind: err.name || 'Error' }\n }\n return { message: String(err), kind: 'NonError' }\n}\n\nfunction randomTaskId(): string {\n // Caller-stable id: `dlg-${timestamp}-${random}`. The timestamp portion\n // makes lexicographic sort match chronological order in history queries\n // even when the system clock skews under the second.\n const t = Date.now().toString(36)\n const r = Math.random().toString(36).slice(2, 10)\n return `dlg-${t}-${r}`\n}\n\n/**\n * Best-effort stable hash for use as `idempotencyKey`. Not cryptographic;\n * collisions only affect dedupe, never correctness.\n *\n * @experimental\n */\nexport function hashIdempotencyInput(value: unknown): string {\n let str: string\n try {\n str = JSON.stringify(canonicalize(value))\n } catch {\n str = String(value)\n }\n // FNV-1a 32-bit\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\nfunction canonicalize(value: unknown): unknown {\n if (value === null || typeof value !== 'object') return value\n if (Array.isArray(value)) return value.map(canonicalize)\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => a.localeCompare(b))\n const out: Record<string, unknown> = {}\n for (const [k, v] of entries) out[k] = canonicalize(v)\n return out\n}\n\n// Re-exports re-used by the feedback-store + handler glue. Kept local so\n// consumers of the queue don't have to import from `./types` separately.\nexport type {\n DelegateCodeArgs,\n DelegateCodeResult,\n DelegateFeedbackArgs,\n DelegateFeedbackResult,\n DelegateResearchArgs,\n DelegateResearchResult,\n DelegationError,\n DelegationFeedbackSnapshot,\n DelegationHistoryArgs,\n DelegationHistoryEntry,\n DelegationHistoryResult,\n DelegationProfile,\n DelegationProgress,\n DelegationResultPayload,\n DelegationStatus,\n DelegationStatusArgs,\n DelegationStatusResult,\n} from './types'\n","/**\n * @experimental\n *\n * `delegate_code` MCP tool — async kickoff. The handler validates the\n * input, computes an idempotency key over the canonical fields, hands\n * the task to the queue, and returns `{ taskId, estimatedDurationMs }`.\n */\n\nimport type { CoderDelegate } from '../delegates'\nimport {\n type DelegateCodeArgs,\n type DelegateCodeResult,\n type DelegationTaskQueue,\n hashIdempotencyInput,\n} from '../task-queue'\n\n/** @experimental */\nexport const DELEGATE_CODE_TOOL_NAME = 'delegate_code'\n\n/** @experimental */\nexport const DELEGATE_CODE_DESCRIPTION = [\n 'Delegate a coding task to specialist coder agents that produce a validated patch.',\n '',\n 'Use when: you need code written, fixed, refactored, or extended to satisfy a',\n 'user goal that touches a real repository. The coder runs in an isolated',\n 'sandbox, opens a fresh branch, keeps the diff minimal, runs the supplied',\n 'test + typecheck commands, and emits a unified-diff patch.',\n '',\n 'Returns immediately with a taskId. Poll delegation_status to retrieve the',\n 'patch + validator verdict (typically minutes-to-hours, longer for large',\n 'changes). Identical inputs return the same taskId — safe to retry.',\n '',\n 'When variants > 1, multiple coder harnesses (claude-code, codex, opencode)',\n 'attempt the task in parallel and the highest-scoring patch wins (smallest',\n 'passing diff). Use variants for high-stakes changes; single variant for',\n 'routine ones.',\n '',\n 'Capability scope: the coder cannot modify paths outside repoRoot and cannot',\n 'touch paths in config.forbiddenPaths. The validator hard-fails on a',\n 'forbidden-path violation, diff above config.maxDiffLines, test failure, or',\n 'typecheck failure — none of those make it past the gate.',\n].join('\\n')\n\n/** @experimental */\nexport const DELEGATE_CODE_INPUT_SCHEMA = {\n type: 'object',\n properties: {\n goal: {\n type: 'string',\n description: 'Natural-language description of what the coder must accomplish.',\n },\n repoRoot: {\n type: 'string',\n description: 'Absolute path inside the sandbox where the repo lives.',\n },\n contextHint: {\n type: 'string',\n description: 'Optional free-form context the coder sees in the prompt prelude.',\n },\n variants: {\n type: 'integer',\n minimum: 1,\n maximum: 8,\n description: 'Number of parallel coder harnesses. Default 1.',\n },\n config: {\n type: 'object',\n properties: {\n testCmd: { type: 'string' },\n typecheckCmd: { type: 'string' },\n forbiddenPaths: { type: 'array', items: { type: 'string' } },\n maxDiffLines: { type: 'integer', minimum: 1 },\n },\n additionalProperties: false,\n },\n namespace: {\n type: 'string',\n description: 'Multi-tenant scope (customer-id, workspace-id).',\n },\n },\n required: ['goal', 'repoRoot'],\n additionalProperties: false,\n} as const\n\nconst SINGLE_VARIANT_ESTIMATE_MS = 6 * 60 * 1000 // 6 minutes — single coder\nconst FANOUT_PER_VARIANT_ESTIMATE_MS = 8 * 60 * 1000 // 8 minutes — fanout\n\n/** @experimental */\nexport function validateDelegateCodeArgs(raw: unknown): DelegateCodeArgs {\n if (raw === null || typeof raw !== 'object') {\n throw new TypeError('delegate_code: arguments must be an object')\n }\n const value = raw as Record<string, unknown>\n const goal = value.goal\n if (typeof goal !== 'string' || goal.trim().length === 0) {\n throw new TypeError('delegate_code: `goal` must be a non-empty string')\n }\n const repoRoot = value.repoRoot\n if (typeof repoRoot !== 'string' || repoRoot.trim().length === 0) {\n throw new TypeError('delegate_code: `repoRoot` must be a non-empty string')\n }\n const args: DelegateCodeArgs = { goal: goal.trim(), repoRoot: repoRoot.trim() }\n if (typeof value.contextHint === 'string') args.contextHint = value.contextHint\n if (value.variants !== undefined) {\n const variants = Number(value.variants)\n if (!Number.isFinite(variants) || variants < 1 || variants > 8) {\n throw new RangeError('delegate_code: `variants` must be an integer in [1, 8]')\n }\n args.variants = Math.trunc(variants)\n }\n if (value.config !== undefined) {\n args.config = validateConfig(value.config)\n }\n if (typeof value.namespace === 'string') args.namespace = value.namespace\n return args\n}\n\nfunction validateConfig(raw: unknown): DelegateCodeArgs['config'] {\n if (raw === null || typeof raw !== 'object') {\n throw new TypeError('delegate_code: `config` must be an object')\n }\n const value = raw as Record<string, unknown>\n const out: NonNullable<DelegateCodeArgs['config']> = {}\n if (value.testCmd !== undefined) {\n if (typeof value.testCmd !== 'string') {\n throw new TypeError('delegate_code: `config.testCmd` must be a string')\n }\n out.testCmd = value.testCmd\n }\n if (value.typecheckCmd !== undefined) {\n if (typeof value.typecheckCmd !== 'string') {\n throw new TypeError('delegate_code: `config.typecheckCmd` must be a string')\n }\n out.typecheckCmd = value.typecheckCmd\n }\n if (value.forbiddenPaths !== undefined) {\n if (!Array.isArray(value.forbiddenPaths)) {\n throw new TypeError('delegate_code: `config.forbiddenPaths` must be a string array')\n }\n out.forbiddenPaths = value.forbiddenPaths.map((entry, i) => {\n if (typeof entry !== 'string') {\n throw new TypeError(`delegate_code: forbiddenPaths[${i}] must be a string`)\n }\n return entry\n })\n }\n if (value.maxDiffLines !== undefined) {\n const n = Number(value.maxDiffLines)\n if (!Number.isFinite(n) || n < 1) {\n throw new RangeError('delegate_code: `config.maxDiffLines` must be a positive integer')\n }\n out.maxDiffLines = Math.trunc(n)\n }\n return out\n}\n\n/** @experimental */\nexport interface DelegateCodeHandlerOptions {\n queue: DelegationTaskQueue\n delegate: CoderDelegate\n /** Override the duration hint. */\n estimateDurationMs?: (args: DelegateCodeArgs) => number\n}\n\n/** @experimental */\nexport function createDelegateCodeHandler(\n options: DelegateCodeHandlerOptions,\n): (raw: unknown) => Promise<DelegateCodeResult> {\n const estimateDurationMs = options.estimateDurationMs ?? defaultEstimate\n return async (raw) => {\n const args = validateDelegateCodeArgs(raw)\n const idempotencyKey = hashIdempotencyInput({\n profile: 'coder',\n goal: args.goal,\n repoRoot: args.repoRoot,\n contextHint: args.contextHint,\n variants: args.variants ?? 1,\n config: args.config,\n namespace: args.namespace,\n })\n const submitted = options.queue.submit<DelegateCodeArgs>({\n profile: 'coder',\n args,\n namespace: args.namespace,\n idempotencyKey,\n run: async (ctx) => options.delegate(args, ctx),\n })\n return {\n taskId: submitted.taskId,\n estimatedDurationMs: estimateDurationMs(args),\n }\n }\n}\n\nfunction defaultEstimate(args: DelegateCodeArgs): number {\n const variants = Math.max(1, args.variants ?? 1)\n if (variants === 1) return SINGLE_VARIANT_ESTIMATE_MS\n return FANOUT_PER_VARIANT_ESTIMATE_MS\n}\n","/**\n * @experimental\n *\n * `delegate_feedback` MCP tool — synchronous record of agent / user /\n * downstream-judge feedback on a delegation, artifact, or outcome.\n *\n * The store is append-only. Every rating is its own event; no dedupe.\n * When `refersTo.kind === 'delegation'`, the snapshot is also attached\n * to the matching queue record so `delegation_history` surfaces it\n * inline without a join.\n */\n\nimport type { FeedbackStore } from '../feedback-store'\nimport { eventToSnapshot } from '../feedback-store'\nimport type { DelegationTaskQueue } from '../task-queue'\nimport type {\n DelegateFeedbackArgs,\n DelegateFeedbackResult,\n FeedbackRating,\n FeedbackRefersTo,\n} from '../types'\n\n/** @experimental */\nexport const DELEGATE_FEEDBACK_TOOL_NAME = 'delegate_feedback'\n\n/** @experimental */\nexport const DELEGATE_FEEDBACK_DESCRIPTION = [\n 'Record feedback on a delegation, artifact, or outcome. Synchronous — the',\n 'event is durably stored when this call returns.',\n '',\n 'Use when: you (the agent), the user, or a downstream judge has formed an',\n 'opinion about a piece of work and want it persisted for calibration,',\n 'pricing, or future routing. Every call is a new event — multiple ratings',\n 'on the same target are expected and never deduped.',\n '',\n '`refersTo.kind`:',\n ' - \"delegation\": ref is a taskId returned by delegate_code/delegate_research',\n ' - \"artifact\": ref is a URI/path/git-sha — anything you can dereference',\n ' - \"outcome\": ref is a free-form description of a downstream result',\n '',\n '`by`:',\n ' - \"agent\": the agent itself rated the work',\n ' - \"user\": the human user rated it',\n ' - \"downstream-judge\": an automated evaluator emitted the rating',\n '',\n 'When ref names a known taskId, the rating is also attached to the',\n 'delegation record so delegation_history surfaces it inline.',\n].join('\\n')\n\n/** @experimental */\nexport const DELEGATE_FEEDBACK_INPUT_SCHEMA = {\n type: 'object',\n properties: {\n refersTo: {\n type: 'object',\n properties: {\n kind: { type: 'string', enum: ['delegation', 'artifact', 'outcome'] },\n ref: { type: 'string' },\n },\n required: ['kind', 'ref'],\n additionalProperties: false,\n },\n rating: {\n type: 'object',\n properties: {\n score: { type: 'number', minimum: 0, maximum: 1 },\n label: { type: 'string', enum: ['good', 'bad', 'neutral', 'mixed'] },\n notes: { type: 'string' },\n },\n required: ['score', 'notes'],\n additionalProperties: false,\n },\n by: { type: 'string', enum: ['agent', 'user', 'downstream-judge'] },\n capturedAt: { type: 'string' },\n namespace: { type: 'string' },\n },\n required: ['refersTo', 'rating', 'by'],\n additionalProperties: false,\n} as const\n\n/** @experimental */\nexport function validateDelegateFeedbackArgs(raw: unknown): DelegateFeedbackArgs {\n if (raw === null || typeof raw !== 'object') {\n throw new TypeError('delegate_feedback: arguments must be an object')\n }\n const value = raw as Record<string, unknown>\n const refersTo = validateRefersTo(value.refersTo)\n const rating = validateRating(value.rating)\n const by = value.by\n if (by !== 'agent' && by !== 'user' && by !== 'downstream-judge') {\n throw new TypeError(\n 'delegate_feedback: `by` must be one of \"agent\" | \"user\" | \"downstream-judge\"',\n )\n }\n const args: DelegateFeedbackArgs = { refersTo, rating, by }\n if (value.capturedAt !== undefined) {\n if (typeof value.capturedAt !== 'string' || Number.isNaN(Date.parse(value.capturedAt))) {\n throw new TypeError('delegate_feedback: `capturedAt` must be an ISO datetime')\n }\n args.capturedAt = value.capturedAt\n }\n if (typeof value.namespace === 'string') args.namespace = value.namespace\n return args\n}\n\nfunction validateRefersTo(raw: unknown): FeedbackRefersTo {\n if (raw === null || typeof raw !== 'object') {\n throw new TypeError('delegate_feedback: `refersTo` must be an object')\n }\n const value = raw as Record<string, unknown>\n const kind = value.kind\n if (kind !== 'delegation' && kind !== 'artifact' && kind !== 'outcome') {\n throw new TypeError(\n 'delegate_feedback: `refersTo.kind` must be one of \"delegation\" | \"artifact\" | \"outcome\"',\n )\n }\n const ref = value.ref\n if (typeof ref !== 'string' || ref.trim().length === 0) {\n throw new TypeError('delegate_feedback: `refersTo.ref` must be a non-empty string')\n }\n return { kind, ref: ref.trim() }\n}\n\nfunction validateRating(raw: unknown): FeedbackRating {\n if (raw === null || typeof raw !== 'object') {\n throw new TypeError('delegate_feedback: `rating` must be an object')\n }\n const value = raw as Record<string, unknown>\n const score = Number(value.score)\n if (!Number.isFinite(score) || score < 0 || score > 1) {\n throw new RangeError('delegate_feedback: `rating.score` must be a number in [0, 1]')\n }\n const notes = value.notes\n if (typeof notes !== 'string') {\n throw new TypeError('delegate_feedback: `rating.notes` must be a string')\n }\n const rating: FeedbackRating = { score, notes }\n const label = value.label\n if (label !== undefined) {\n if (label !== 'good' && label !== 'bad' && label !== 'neutral' && label !== 'mixed') {\n throw new TypeError(\n 'delegate_feedback: `rating.label` must be one of \"good\" | \"bad\" | \"neutral\" | \"mixed\"',\n )\n }\n rating.label = label\n }\n return rating\n}\n\n/** @experimental */\nexport interface DelegateFeedbackHandlerOptions {\n queue: DelegationTaskQueue\n store: FeedbackStore\n generateId?: () => string\n now?: () => string\n}\n\n/** @experimental */\nexport function createDelegateFeedbackHandler(\n options: DelegateFeedbackHandlerOptions,\n): (raw: unknown) => Promise<DelegateFeedbackResult> {\n const generateId = options.generateId ?? randomFeedbackId\n const now = options.now ?? (() => new Date().toISOString())\n return async (raw) => {\n const args = validateDelegateFeedbackArgs(raw)\n const id = generateId()\n const event = {\n id,\n refersTo: args.refersTo,\n rating: args.rating,\n by: args.by,\n capturedAt: args.capturedAt ?? now(),\n namespace: args.namespace,\n }\n await options.store.put(event)\n if (args.refersTo.kind === 'delegation') {\n options.queue.attachFeedback(args.refersTo.ref, eventToSnapshot(event))\n }\n return { recorded: true, id }\n }\n}\n\nfunction randomFeedbackId(): string {\n const t = Date.now().toString(36)\n const r = Math.random().toString(36).slice(2, 10)\n return `fbk-${t}-${r}`\n}\n","/**\n * @experimental\n *\n * `delegate_research` MCP tool — async kickoff for source-grounded\n * research tasks. Same async semantics as `delegate_code`: returns a\n * taskId immediately, idempotent on canonical inputs.\n *\n * The handler does not import a researcher profile directly — consumers\n * inject a `ResearcherDelegate` via `createMcpServer({ researcherDelegate })`.\n * The substrate cannot depend on `@tangle-network/agent-knowledge`\n * without inducing a dependency cycle.\n */\n\nimport type { ResearcherDelegate } from '../delegates'\nimport {\n type DelegateResearchArgs,\n type DelegateResearchResult,\n type DelegationTaskQueue,\n hashIdempotencyInput,\n} from '../task-queue'\nimport type { ResearchSource } from '../types'\n\n/** @experimental */\nexport const DELEGATE_RESEARCH_TOOL_NAME = 'delegate_research'\n\n/** @experimental */\nexport const DELEGATE_RESEARCH_DESCRIPTION = [\n 'Delegate a research question to specialist researcher agents that produce',\n 'source-grounded, evidence-bearing knowledge items.',\n '',\n 'Use when: you need to answer a factual question with external evidence —',\n 'audience research, competitive intelligence, recency-bound web searches,',\n 'corpus / docs lookups. The researcher emits items[] with provenance, a',\n 'citations[] index, and proposedWrites[] you decide whether to persist.',\n '',\n 'Returns immediately with a taskId. Poll delegation_status to retrieve the',\n 'items + verdict. Identical inputs return the same taskId — safe to retry.',\n '',\n 'When variants > 1, multiple researcher harnesses run in parallel and the',\n 'highest-scoring valid output wins (citation density × source diversity ×',\n 'recency match × gap coverage). Use variants when answers might disagree.',\n '',\n 'Multi-tenant isolation: every item carries `namespace`. The validator',\n 'hard-fails when any item is scoped outside `namespace`. Never pass another',\n \"tenant's namespace.\",\n].join('\\n')\n\nconst VALID_SOURCES: readonly ResearchSource[] = ['web', 'corpus', 'twitter', 'github', 'docs']\n\n/** @experimental */\nexport const DELEGATE_RESEARCH_INPUT_SCHEMA = {\n type: 'object',\n properties: {\n question: {\n type: 'string',\n description: 'The research question to answer.',\n },\n namespace: {\n type: 'string',\n description: 'Multi-tenant scope (customer-id, workspace-id). REQUIRED.',\n },\n scope: { type: 'string', description: 'Bound, e.g. \"audience for cpg-founder ICP\".' },\n sources: {\n type: 'array',\n items: { type: 'string', enum: [...VALID_SOURCES] },\n },\n variants: { type: 'integer', minimum: 1, maximum: 8 },\n config: {\n type: 'object',\n properties: {\n recencyWindow: {\n type: 'object',\n properties: {\n since: { type: 'string', description: 'ISO datetime' },\n until: { type: 'string', description: 'ISO datetime' },\n },\n additionalProperties: false,\n },\n maxItems: { type: 'integer', minimum: 1 },\n minConfidence: { type: 'number', minimum: 0, maximum: 1 },\n },\n additionalProperties: false,\n },\n },\n required: ['question', 'namespace'],\n additionalProperties: false,\n} as const\n\nconst SINGLE_VARIANT_ESTIMATE_MS = 4 * 60 * 1000\nconst FANOUT_PER_VARIANT_ESTIMATE_MS = 6 * 60 * 1000\n\n/** @experimental */\nexport function validateDelegateResearchArgs(raw: unknown): DelegateResearchArgs {\n if (raw === null || typeof raw !== 'object') {\n throw new TypeError('delegate_research: arguments must be an object')\n }\n const value = raw as Record<string, unknown>\n const question = value.question\n if (typeof question !== 'string' || question.trim().length === 0) {\n throw new TypeError('delegate_research: `question` must be a non-empty string')\n }\n const namespace = value.namespace\n if (typeof namespace !== 'string' || namespace.trim().length === 0) {\n throw new TypeError('delegate_research: `namespace` is required')\n }\n const args: DelegateResearchArgs = { question: question.trim(), namespace: namespace.trim() }\n if (typeof value.scope === 'string') args.scope = value.scope\n if (value.sources !== undefined) {\n if (!Array.isArray(value.sources)) {\n throw new TypeError('delegate_research: `sources` must be a string array')\n }\n const sources: ResearchSource[] = value.sources.map((src, i) => {\n if (typeof src !== 'string' || !VALID_SOURCES.includes(src as ResearchSource)) {\n throw new TypeError(\n `delegate_research: sources[${i}] must be one of ${VALID_SOURCES.join('|')}`,\n )\n }\n return src as ResearchSource\n })\n args.sources = sources\n }\n if (value.variants !== undefined) {\n const variants = Number(value.variants)\n if (!Number.isFinite(variants) || variants < 1 || variants > 8) {\n throw new RangeError('delegate_research: `variants` must be an integer in [1, 8]')\n }\n args.variants = Math.trunc(variants)\n }\n if (value.config !== undefined) {\n args.config = validateConfig(value.config)\n }\n return args\n}\n\nfunction validateConfig(raw: unknown): DelegateResearchArgs['config'] {\n if (raw === null || typeof raw !== 'object') {\n throw new TypeError('delegate_research: `config` must be an object')\n }\n const value = raw as Record<string, unknown>\n const out: NonNullable<DelegateResearchArgs['config']> = {}\n if (value.recencyWindow !== undefined) {\n if (value.recencyWindow === null || typeof value.recencyWindow !== 'object') {\n throw new TypeError('delegate_research: `config.recencyWindow` must be an object')\n }\n const window = value.recencyWindow as Record<string, unknown>\n const windowOut: NonNullable<NonNullable<DelegateResearchArgs['config']>['recencyWindow']> = {}\n if (window.since !== undefined) {\n if (typeof window.since !== 'string' || Number.isNaN(Date.parse(window.since))) {\n throw new TypeError('delegate_research: `recencyWindow.since` must be an ISO datetime')\n }\n windowOut.since = window.since\n }\n if (window.until !== undefined) {\n if (typeof window.until !== 'string' || Number.isNaN(Date.parse(window.until))) {\n throw new TypeError('delegate_research: `recencyWindow.until` must be an ISO datetime')\n }\n windowOut.until = window.until\n }\n out.recencyWindow = windowOut\n }\n if (value.maxItems !== undefined) {\n const n = Number(value.maxItems)\n if (!Number.isFinite(n) || n < 1) {\n throw new RangeError('delegate_research: `config.maxItems` must be a positive integer')\n }\n out.maxItems = Math.trunc(n)\n }\n if (value.minConfidence !== undefined) {\n const n = Number(value.minConfidence)\n if (!Number.isFinite(n) || n < 0 || n > 1) {\n throw new RangeError('delegate_research: `config.minConfidence` must be in [0, 1]')\n }\n out.minConfidence = n\n }\n return out\n}\n\n/** @experimental */\nexport interface DelegateResearchHandlerOptions {\n queue: DelegationTaskQueue\n delegate: ResearcherDelegate\n estimateDurationMs?: (args: DelegateResearchArgs) => number\n}\n\n/** @experimental */\nexport function createDelegateResearchHandler(\n options: DelegateResearchHandlerOptions,\n): (raw: unknown) => Promise<DelegateResearchResult> {\n const estimateDurationMs = options.estimateDurationMs ?? defaultEstimate\n return async (raw) => {\n const args = validateDelegateResearchArgs(raw)\n const idempotencyKey = hashIdempotencyInput({\n profile: 'researcher',\n question: args.question,\n namespace: args.namespace,\n scope: args.scope,\n sources: args.sources,\n variants: args.variants ?? 1,\n config: args.config,\n })\n const submitted = options.queue.submit<DelegateResearchArgs>({\n profile: 'researcher',\n args,\n namespace: args.namespace,\n idempotencyKey,\n run: async (ctx) => options.delegate(args, ctx),\n })\n return {\n taskId: submitted.taskId,\n estimatedDurationMs: estimateDurationMs(args),\n }\n }\n}\n\nfunction defaultEstimate(args: DelegateResearchArgs): number {\n const variants = Math.max(1, args.variants ?? 1)\n if (variants === 1) return SINGLE_VARIANT_ESTIMATE_MS\n return FANOUT_PER_VARIANT_ESTIMATE_MS\n}\n","/**\n * @experimental\n *\n * `delegation_history` MCP tool — synchronous read of past delegations.\n * The agent uses this for self-introspection — \"have I delegated this\n * kind of task before? did it work?\" — and calibration.\n */\n\nimport type {\n DelegationHistoryArgs,\n DelegationHistoryResult,\n DelegationProfile,\n DelegationTaskQueue,\n} from '../task-queue'\n\n/** @experimental */\nexport const DELEGATION_HISTORY_TOOL_NAME = 'delegation_history'\n\n/** @experimental */\nexport const DELEGATION_HISTORY_DESCRIPTION = [\n 'Read past delegations newest-first. Each entry carries the original',\n 'arguments, current status, cost, and any feedback attached via',\n 'delegate_feedback.',\n '',\n 'Use when: you want to introspect prior decisions — \"have I asked this',\n 'question before?',\n 'did the last patch land?',\n \"what's the historical\",\n 'success rate of coder delegations on this repo?\". Feed the results back',\n 'into your own routing and calibration.',\n '',\n 'Filters: `namespace` (multi-tenant scope), `profile` (\"coder\" | \"researcher\"),',\n '`since` (ISO date — only delegations started at-or-after). `limit` defaults',\n 'to 50, capped at 500.',\n].join('\\n')\n\n/** @experimental */\nexport const DELEGATION_HISTORY_INPUT_SCHEMA = {\n type: 'object',\n properties: {\n namespace: { type: 'string' },\n profile: { type: 'string', enum: ['coder', 'researcher'] },\n since: { type: 'string', description: 'ISO datetime — earliest startedAt to include.' },\n limit: { type: 'integer', minimum: 1, maximum: 500 },\n },\n additionalProperties: false,\n} as const\n\n/** @experimental */\nexport function validateDelegationHistoryArgs(raw: unknown): DelegationHistoryArgs {\n if (raw === undefined || raw === null) return {}\n if (typeof raw !== 'object') {\n throw new TypeError('delegation_history: arguments must be an object')\n }\n const value = raw as Record<string, unknown>\n const out: DelegationHistoryArgs = {}\n if (value.namespace !== undefined) {\n if (typeof value.namespace !== 'string') {\n throw new TypeError('delegation_history: `namespace` must be a string')\n }\n out.namespace = value.namespace\n }\n if (value.profile !== undefined) {\n if (value.profile !== 'coder' && value.profile !== 'researcher') {\n throw new TypeError('delegation_history: `profile` must be \"coder\" or \"researcher\"')\n }\n out.profile = value.profile as DelegationProfile\n }\n if (value.since !== undefined) {\n if (typeof value.since !== 'string' || Number.isNaN(Date.parse(value.since))) {\n throw new TypeError('delegation_history: `since` must be an ISO datetime')\n }\n out.since = value.since\n }\n if (value.limit !== undefined) {\n const n = Number(value.limit)\n if (!Number.isFinite(n) || n < 1 || n > 500) {\n throw new RangeError('delegation_history: `limit` must be an integer in [1, 500]')\n }\n out.limit = Math.trunc(n)\n }\n return out\n}\n\n/** @experimental */\nexport interface DelegationHistoryHandlerOptions {\n queue: DelegationTaskQueue\n}\n\n/** @experimental */\nexport function createDelegationHistoryHandler(\n options: DelegationHistoryHandlerOptions,\n): (raw: unknown) => Promise<DelegationHistoryResult> {\n return async (raw) => {\n const args = validateDelegationHistoryArgs(raw)\n return { delegations: options.queue.history(args) }\n }\n}\n","/**\n * @experimental\n *\n * `delegation_status` MCP tool — synchronous poll. Returns the current\n * state machine + optional progress + final result (when terminal).\n */\n\nimport { NotFoundError } from '../../errors'\nimport type {\n DelegationStatusArgs,\n DelegationStatusResult,\n DelegationTaskQueue,\n} from '../task-queue'\n\n/** @experimental */\nexport const DELEGATION_STATUS_TOOL_NAME = 'delegation_status'\n\n/** @experimental */\nexport const DELEGATION_STATUS_DESCRIPTION = [\n 'Poll the status of an async delegation. Returns the current state',\n '(pending | running | completed | failed | cancelled), optional progress,',\n 'and the final result when status === \"completed\".',\n '',\n 'Use when: you previously called delegate_code or delegate_research and',\n \"need to know whether the work is done. The agent's right rhythm is to\",\n 'call this every minute or two while waiting; do not busy-poll.',\n '',\n 'For a completed coder task, `result.output` is a CoderOutput with branch,',\n 'patch, test/typecheck results, and diff stats. For a completed research',\n 'task, `result.output` is the items + citations + proposedWrites bundle.',\n '',\n 'Throws NotFoundError when taskId is unknown — never silently returns',\n '`pending` for a typo.',\n].join('\\n')\n\n/** @experimental */\nexport const DELEGATION_STATUS_INPUT_SCHEMA = {\n type: 'object',\n properties: {\n taskId: { type: 'string', description: 'Returned by delegate_code / delegate_research.' },\n },\n required: ['taskId'],\n additionalProperties: false,\n} as const\n\n/** @experimental */\nexport function validateDelegationStatusArgs(raw: unknown): DelegationStatusArgs {\n if (raw === null || typeof raw !== 'object') {\n throw new TypeError('delegation_status: arguments must be an object')\n }\n const value = raw as Record<string, unknown>\n const taskId = value.taskId\n if (typeof taskId !== 'string' || taskId.trim().length === 0) {\n throw new TypeError('delegation_status: `taskId` must be a non-empty string')\n }\n return { taskId: taskId.trim() }\n}\n\n/** @experimental */\nexport interface DelegationStatusHandlerOptions {\n queue: DelegationTaskQueue\n}\n\n/** @experimental */\nexport function createDelegationStatusHandler(\n options: DelegationStatusHandlerOptions,\n): (raw: unknown) => Promise<DelegationStatusResult> {\n return async (raw) => {\n const args = validateDelegationStatusArgs(raw)\n const status = options.queue.status(args.taskId)\n if (!status) {\n throw new NotFoundError(`delegation_status: unknown taskId \"${args.taskId}\"`)\n }\n return status\n }\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.21.1'\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"],"mappings":"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","names":["result","winner","SINGLE_VARIANT_ESTIMATE_MS","FANOUT_PER_VARIANT_ESTIMATE_MS","validateConfig","defaultEstimate"]}
package/dist/loops.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { AgentProfile, CreateSandboxOptions, SandboxEvent, SandboxInstance } from '@tangle-network/sandbox';
2
- import { D as DefaultVerdict, a as Driver, I as Iteration, A as AgentRunSpec, O as OutputAdapter, V as Validator, E as ExecCtx, L as LoopWinner, b as LoopResult } from './types-Bx-tArkc.js';
3
- export { c as LoopDecisionPayload, d as LoopEndedPayload, e as LoopIterationEndedPayload, f as LoopIterationStartedPayload, g as LoopSandboxClient, h as LoopStartedPayload, i as LoopTraceEmitter, j as LoopTraceEvent, k as ValidationCtx } from './types-Bx-tArkc.js';
2
+ import { D as DefaultVerdict, a as Driver, I as Iteration, A as AgentRunSpec, O as OutputAdapter, V as Validator, E as ExecCtx, L as LoopWinner, b as LoopResult } from './types-Cu-SkGa0.js';
3
+ export { c as LoopDecisionPayload, d as LoopEndedPayload, e as LoopIterationDispatchPayload, f as LoopIterationEndedPayload, g as LoopIterationStartedPayload, h as LoopSandboxClient, i as LoopSandboxPlacement, j as LoopStartedPayload, k as LoopTraceEmitter, l as LoopTraceEvent, m as ValidationCtx } from './types-Cu-SkGa0.js';
4
4
  import './runtime-run-B2j-hvBj.js';
5
5
  import './types-DvJIha6w.js';
6
6
  import '@tangle-network/agent-eval';
@@ -96,7 +96,9 @@ declare function refineWinnerIndex<Task, Output>(iterations: ReadonlyArray<Itera
96
96
  * 2. For each task (parallel, bounded by `maxConcurrency`):
97
97
  * a. round-robin an `AgentRunSpec` from `agentRuns`
98
98
  * b. `sandboxClient.create({ backend: { profile }, ...overrides })`
99
- * c. iterate `box.streamPrompt(taskToPrompt(task))` and collect events
99
+ * c. emit `loop.iteration.dispatch` with the placement
100
+ * (`{ sibling, sandboxId }` or `{ fleet, fleetId, machineId, sandboxId }`)
101
+ * d. iterate `box.streamPrompt(taskToPrompt(task))` and collect events
100
102
  * 3. `output.parse(events)` → typed `Output`
101
103
  * 4. `validator?.validate(output)` → `DefaultVerdict`
102
104
  * 5. Append `Iteration` to history; emit `loop.iteration.ended`
package/dist/loops.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  createRefineDriver,
3
3
  refineWinnerIndex,
4
4
  runLoop
5
- } from "./chunk-VFUEE6DF.js";
5
+ } from "./chunk-EDVCVFQB.js";
6
6
  import {
7
7
  createFanoutVoteDriver,
8
8
  scoreFanoutVoteIterations
package/dist/mcp/bin.js CHANGED
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createDefaultCoderDelegate,
4
- createMcpServer
5
- } from "../chunk-LPPM7EGS.js";
4
+ createMcpServer,
5
+ detectExecutor
6
+ } from "../chunk-QDNJLAEU.js";
6
7
  import {
7
8
  runLoop
8
- } from "../chunk-VFUEE6DF.js";
9
+ } from "../chunk-EDVCVFQB.js";
9
10
  import "../chunk-Z5LKAYAS.js";
10
11
  import "../chunk-XLWPTPRP.js";
11
12
  import "../chunk-RZAOYKCO.js";
@@ -17,8 +18,10 @@ async function main() {
17
18
  const maxConcurrency = parseConcurrency(process.env.MCP_MAX_CONCURRENT_SANDBOXES);
18
19
  const wantCoder = !process.env.MCP_DISABLE_CODER;
19
20
  const wantResearcher = !process.env.MCP_DISABLE_RESEARCHER;
21
+ const fleetId = parseFleetId(process.env.TANGLE_FLEET_ID);
20
22
  const needsSandbox = wantCoder || wantResearcher;
21
23
  let sandboxClient;
24
+ let executor;
22
25
  if (needsSandbox) {
23
26
  const apiKey = process.env.TANGLE_API_KEY;
24
27
  if (!apiKey && !process.env.AGENT_RUNTIME_MCP_ALLOW_NO_KEY) {
@@ -27,14 +30,27 @@ async function main() {
27
30
  );
28
31
  process.exit(2);
29
32
  }
33
+ if (fleetId && !apiKey) {
34
+ process.stderr.write(
35
+ "agent-runtime-mcp: TANGLE_FLEET_ID was set but TANGLE_API_KEY is missing; cannot resolve fleet handle. Provide an api key or unset TANGLE_FLEET_ID.\n"
36
+ );
37
+ process.exit(2);
38
+ }
30
39
  sandboxClient = await loadSandboxClient(apiKey);
40
+ executor = await detectExecutor({ sandboxClient });
41
+ if (fleetId) {
42
+ process.stderr.write(`agent-runtime-mcp: fleet-aware delegation: fleetId=${fleetId}
43
+ `);
44
+ }
45
+ process.stderr.write(`agent-runtime-mcp: delegation placement \u2192 ${executor.describe()}
46
+ `);
31
47
  }
32
- const coderDelegate = wantCoder && sandboxClient ? createDefaultCoderDelegate({
33
- sandboxClient,
48
+ const coderDelegate = wantCoder && executor ? createDefaultCoderDelegate({
49
+ executor,
34
50
  fanoutHarnesses,
35
51
  maxConcurrency
36
52
  }) : void 0;
37
- const researcherDelegate = wantResearcher && sandboxClient ? await loadResearcherDelegate(sandboxClient, maxConcurrency) : void 0;
53
+ const researcherDelegate = wantResearcher && executor ? await loadResearcherDelegate(executor.client, maxConcurrency) : void 0;
38
54
  const server = createMcpServer({ coderDelegate, researcherDelegate });
39
55
  process.on("SIGINT", () => {
40
56
  server.stop();
@@ -145,6 +161,11 @@ function parseHarnesses(raw) {
145
161
  const list = raw.split(",").map((entry) => entry.trim()).filter(Boolean);
146
162
  return list.length > 0 ? list : void 0;
147
163
  }
164
+ function parseFleetId(raw) {
165
+ if (typeof raw !== "string") return void 0;
166
+ const trimmed = raw.trim();
167
+ return trimmed.length > 0 ? trimmed : void 0;
168
+ }
148
169
  function parseConcurrency(raw) {
149
170
  if (!raw) return 4;
150
171
  const n = Number(raw);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/mcp/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * @experimental\n *\n * `agent-runtime-mcp` — stdio MCP server entry point.\n *\n * Spins up a server with the default coder delegate (wired against the\n * real `@tangle-network/sandbox` client) and, when the optional\n * `@tangle-network/agent-knowledge` peer is installed, a researcher\n * delegate against `multiHarnessResearcherFanout`.\n *\n * Environment variables:\n * TANGLE_API_KEY required — passed to `new Sandbox({ apiKey })`\n * SANDBOX_BASE_URL optional — sandbox-SDK base URL override\n * MCP_MAX_CONCURRENT_SANDBOXES default 4 — kernel maxConcurrency cap\n * MCP_CODER_FANOUT_HARNESSES comma-separated harness ids to use for variants > 1\n * MCP_DISABLE_CODER set to `1` to omit `delegate_code`\n * MCP_DISABLE_RESEARCHER set to `1` to omit `delegate_research` even when peer is present\n */\n\nimport type { LoopSandboxClient } from '../loops'\nimport { runLoop } from '../loops'\nimport { createDefaultCoderDelegate, type ResearcherDelegate } from './delegates'\nimport { createMcpServer } from './server'\nimport type { ResearchOutputShape } from './types'\n\nasync function main(): Promise<void> {\n const fanoutHarnesses = parseHarnesses(process.env.MCP_CODER_FANOUT_HARNESSES)\n const maxConcurrency = parseConcurrency(process.env.MCP_MAX_CONCURRENT_SANDBOXES)\n const wantCoder = !process.env.MCP_DISABLE_CODER\n const wantResearcher = !process.env.MCP_DISABLE_RESEARCHER\n\n // Skip the sandbox client load entirely when no profile delegate needs it —\n // the feedback + status + history tools are queue-bound and require no\n // sandbox. Useful for tooling that mounts the MCP server purely for\n // self-introspection.\n const needsSandbox = wantCoder || wantResearcher\n let sandboxClient: LoopSandboxClient | undefined\n if (needsSandbox) {\n const apiKey = process.env.TANGLE_API_KEY\n if (!apiKey && !process.env.AGENT_RUNTIME_MCP_ALLOW_NO_KEY) {\n process.stderr.write(\n 'agent-runtime-mcp: TANGLE_API_KEY is required. Set AGENT_RUNTIME_MCP_ALLOW_NO_KEY=1 to run without it for diagnostics, or MCP_DISABLE_CODER=1 MCP_DISABLE_RESEARCHER=1 to run the queue-only subset.\\n',\n )\n process.exit(2)\n }\n sandboxClient = await loadSandboxClient(apiKey)\n }\n\n const coderDelegate =\n wantCoder && sandboxClient\n ? createDefaultCoderDelegate({\n sandboxClient,\n fanoutHarnesses,\n maxConcurrency,\n })\n : undefined\n\n const researcherDelegate =\n wantResearcher && sandboxClient\n ? await loadResearcherDelegate(sandboxClient, maxConcurrency)\n : undefined\n\n const server = createMcpServer({ coderDelegate, researcherDelegate })\n\n process.on('SIGINT', () => {\n server.stop()\n process.exit(0)\n })\n process.on('SIGTERM', () => {\n server.stop()\n process.exit(0)\n })\n\n await server.serve()\n}\n\nasync function loadSandboxClient(apiKey: string | undefined): Promise<LoopSandboxClient> {\n // Diagnostic mode: AGENT_RUNTIME_MCP_ALLOW_NO_KEY=1 enables tools/list + the\n // queue-bound tools (status / history / feedback) without sandbox creds.\n // Coder + researcher delegations require a real client; the stub fails loud\n // at create() so the agent observes the cause instead of silent success.\n if (!apiKey) {\n return {\n async create() {\n throw new Error(\n 'agent-runtime-mcp: TANGLE_API_KEY is unset; coder/researcher delegations are disabled in diagnostic mode. Set TANGLE_API_KEY or use MCP_DISABLE_CODER=1 MCP_DISABLE_RESEARCHER=1 to remove the unsupported tools from the tool list.',\n )\n },\n } satisfies LoopSandboxClient\n }\n // Dynamic import keeps the bin importable in environments that haven't\n // installed `@tangle-network/sandbox` yet (the runtime package lists it\n // as a peer dep, not a hard dep).\n const mod = await import('@tangle-network/sandbox').catch((err) => {\n process.stderr.write(\n `agent-runtime-mcp: failed to load @tangle-network/sandbox (${err.message}); install the peer dependency\\n`,\n )\n process.exit(2)\n })\n const SandboxCtor = (mod as { Sandbox?: new (config: unknown) => LoopSandboxClient }).Sandbox\n if (!SandboxCtor) {\n process.stderr.write(\n 'agent-runtime-mcp: @tangle-network/sandbox does not export Sandbox; cannot construct client\\n',\n )\n process.exit(2)\n }\n const baseUrl = process.env.SANDBOX_BASE_URL\n return new SandboxCtor({\n apiKey,\n ...(baseUrl ? { baseUrl } : {}),\n })\n}\n\ninterface ResearcherProfilePreset {\n agentRunSpec: Parameters<typeof runLoop>[0]['agentRun'] extends infer T ? NonNullable<T> : never\n output: Parameters<typeof runLoop>[0]['output']\n validator: Parameters<typeof runLoop>[0]['validator']\n}\n\ninterface ResearcherFanoutPreset {\n agentRuns: NonNullable<Parameters<typeof runLoop>[0]['agentRuns']>\n output: Parameters<typeof runLoop>[0]['output']\n validator: Parameters<typeof runLoop>[0]['validator']\n driver: Parameters<typeof runLoop>[0]['driver']\n}\n\nasync function loadResearcherDelegate(\n sandboxClient: LoopSandboxClient,\n maxConcurrency: number,\n): Promise<ResearcherDelegate | undefined> {\n // Optional peer — when `@tangle-network/agent-knowledge` isn't installed,\n // we silently omit the researcher tool from the advertisement. The\n // dynamic-import path is resolved at runtime; TypeScript cannot see the\n // peer, so we type the module structurally rather than via its own\n // declaration file.\n const profilesSpecifier = '@tangle-network/agent-knowledge/profiles'\n const mod = await import(profilesSpecifier).catch(() => undefined)\n if (!mod) return undefined\n type SingleFactory = (opts: { task: unknown }) => ResearcherProfilePreset\n type FanoutFactory = (opts: { task: unknown }) => ResearcherFanoutPreset\n const fanoutFactory = (mod as { multiHarnessResearcherFanout?: FanoutFactory })\n .multiHarnessResearcherFanout\n const singleFactory = (mod as { researcherProfile?: SingleFactory }).researcherProfile\n if (!fanoutFactory || !singleFactory) return undefined\n\n return async (args, ctx) => {\n const task = {\n question: args.question,\n knowledgeNamespace: args.namespace,\n scope: args.scope,\n sources: args.sources,\n recencyWindow: args.config?.recencyWindow\n ? {\n since: args.config.recencyWindow.since\n ? new Date(args.config.recencyWindow.since)\n : undefined,\n until: args.config.recencyWindow.until\n ? new Date(args.config.recencyWindow.until)\n : undefined,\n }\n : undefined,\n maxItems: args.config?.maxItems,\n minConfidence: args.config?.minConfidence,\n }\n const variants = Math.max(1, Math.trunc(args.variants ?? 1))\n ctx.report({ iteration: 0, phase: 'starting' })\n if (variants <= 1) {\n const preset = singleFactory({ task })\n const result = await runLoop({\n driver: {\n name: 'mcp-researcher-single',\n async plan(t, history) {\n return history.length === 0 ? [t] : []\n },\n decide(history) {\n return history.length > 0 ? 'pick-winner' : 'fail'\n },\n },\n agentRun: preset.agentRunSpec,\n output: preset.output,\n validator: preset.validator,\n task,\n ctx: { sandboxClient, signal: ctx.signal },\n maxIterations: 1,\n maxConcurrency,\n })\n const output = result.winner?.output\n if (!output) throw new Error('researcher delegate produced no winner')\n ctx.report({ iteration: 1, phase: 'completed' })\n return output as ResearchOutputShape\n }\n const fanout = fanoutFactory({ task })\n const result = await runLoop({\n driver: fanout.driver,\n agentRuns: fanout.agentRuns.slice(0, variants),\n output: fanout.output,\n validator: fanout.validator,\n task,\n ctx: { sandboxClient, signal: ctx.signal },\n maxIterations: variants,\n maxConcurrency: Math.min(maxConcurrency, variants),\n })\n const output = result.winner?.output\n if (!output) throw new Error('researcher delegate fanout produced no winner')\n ctx.report({ iteration: result.iterations.length, phase: 'completed' })\n return output as ResearchOutputShape\n }\n}\n\nfunction parseHarnesses(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\nfunction parseConcurrency(raw: string | undefined): number {\n if (!raw) return 4\n const n = Number(raw)\n if (!Number.isFinite(n) || n < 1) return 4\n return Math.min(Math.trunc(n), 32)\n}\n\nmain().catch((err) => {\n process.stderr.write(`agent-runtime-mcp: ${err instanceof Error ? err.stack : String(err)}\\n`)\n process.exit(1)\n})\n"],"mappings":"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","names":["result","output"]}
1
+ {"version":3,"sources":["../../src/mcp/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * @experimental\n *\n * `agent-runtime-mcp` — stdio MCP server entry point.\n *\n * Spins up a server with the default coder delegate (wired against the\n * real `@tangle-network/sandbox` client) and, when the optional\n * `@tangle-network/agent-knowledge` peer is installed, a researcher\n * delegate against `multiHarnessResearcherFanout`.\n *\n * Environment variables:\n * TANGLE_API_KEY required — passed to `new Sandbox({ apiKey })`\n * SANDBOX_BASE_URL optional — sandbox-SDK base URL override\n * TANGLE_FLEET_ID optional — when set, delegations dispatch\n * INTO this fleet's shared workspace instead\n * of creating sibling sandboxes. Set by the\n * parent sandbox when launching this MCP\n * server so worker diffs land on the caller's\n * filesystem with no cross-sandbox boundary.\n * TANGLE_FLEET_EXCLUDE_MACHINES optional — comma-separated machine ids to\n * skip during fleet-mode round-robin\n * (typically the coordinator machine this\n * MCP server is running on).\n * MCP_MAX_CONCURRENT_SANDBOXES default 4 — kernel maxConcurrency cap\n * MCP_CODER_FANOUT_HARNESSES comma-separated harness ids to use for variants > 1\n * MCP_DISABLE_CODER set to `1` to omit `delegate_code`\n * MCP_DISABLE_RESEARCHER set to `1` to omit `delegate_research` even when peer is present\n */\n\nimport type { LoopSandboxClient } from '../loops'\nimport { runLoop } from '../loops'\nimport { detectExecutor } from './bin-helpers'\nimport { createDefaultCoderDelegate, type ResearcherDelegate } from './delegates'\nimport type { DelegationExecutor } from './executor'\nimport { createMcpServer } from './server'\nimport type { ResearchOutputShape } from './types'\n\nasync function main(): Promise<void> {\n const fanoutHarnesses = parseHarnesses(process.env.MCP_CODER_FANOUT_HARNESSES)\n const maxConcurrency = parseConcurrency(process.env.MCP_MAX_CONCURRENT_SANDBOXES)\n const wantCoder = !process.env.MCP_DISABLE_CODER\n const wantResearcher = !process.env.MCP_DISABLE_RESEARCHER\n const fleetId = parseFleetId(process.env.TANGLE_FLEET_ID)\n\n // Skip the sandbox client load entirely when no profile delegate needs it —\n // the feedback + status + history tools are queue-bound and require no\n // sandbox. Useful for tooling that mounts the MCP server purely for\n // self-introspection.\n const needsSandbox = wantCoder || wantResearcher\n let sandboxClient: LoopSandboxClient | undefined\n let executor: DelegationExecutor | undefined\n if (needsSandbox) {\n const apiKey = process.env.TANGLE_API_KEY\n if (!apiKey && !process.env.AGENT_RUNTIME_MCP_ALLOW_NO_KEY) {\n process.stderr.write(\n 'agent-runtime-mcp: TANGLE_API_KEY is required. Set AGENT_RUNTIME_MCP_ALLOW_NO_KEY=1 to run without it for diagnostics, or MCP_DISABLE_CODER=1 MCP_DISABLE_RESEARCHER=1 to run the queue-only subset.\\n',\n )\n process.exit(2)\n }\n // Fleet mode against a diagnostic stub is meaningless — the stub can't\n // resolve a real fleet handle. Refuse rather than silently degrading,\n // otherwise a fleet-mounted MCP would behave differently than configured.\n if (fleetId && !apiKey) {\n process.stderr.write(\n 'agent-runtime-mcp: TANGLE_FLEET_ID was set but TANGLE_API_KEY is missing; cannot resolve fleet handle. Provide an api key or unset TANGLE_FLEET_ID.\\n',\n )\n process.exit(2)\n }\n sandboxClient = await loadSandboxClient(apiKey)\n executor = await detectExecutor({ sandboxClient })\n if (fleetId) {\n process.stderr.write(`agent-runtime-mcp: fleet-aware delegation: fleetId=${fleetId}\\n`)\n }\n process.stderr.write(`agent-runtime-mcp: delegation placement → ${executor.describe()}\\n`)\n }\n\n const coderDelegate =\n wantCoder && executor\n ? createDefaultCoderDelegate({\n executor,\n fanoutHarnesses,\n maxConcurrency,\n })\n : undefined\n\n const researcherDelegate =\n wantResearcher && executor\n ? await loadResearcherDelegate(executor.client, maxConcurrency)\n : undefined\n\n const server = createMcpServer({ coderDelegate, researcherDelegate })\n\n process.on('SIGINT', () => {\n server.stop()\n process.exit(0)\n })\n process.on('SIGTERM', () => {\n server.stop()\n process.exit(0)\n })\n\n await server.serve()\n}\n\nasync function loadSandboxClient(apiKey: string | undefined): Promise<LoopSandboxClient> {\n // Diagnostic mode: AGENT_RUNTIME_MCP_ALLOW_NO_KEY=1 enables tools/list + the\n // queue-bound tools (status / history / feedback) without sandbox creds.\n // Coder + researcher delegations require a real client; the stub fails loud\n // at create() so the agent observes the cause instead of silent success.\n if (!apiKey) {\n return {\n async create() {\n throw new Error(\n 'agent-runtime-mcp: TANGLE_API_KEY is unset; coder/researcher delegations are disabled in diagnostic mode. Set TANGLE_API_KEY or use MCP_DISABLE_CODER=1 MCP_DISABLE_RESEARCHER=1 to remove the unsupported tools from the tool list.',\n )\n },\n } satisfies LoopSandboxClient\n }\n // Dynamic import keeps the bin importable in environments that haven't\n // installed `@tangle-network/sandbox` yet (the runtime package lists it\n // as a peer dep, not a hard dep).\n const mod = await import('@tangle-network/sandbox').catch((err) => {\n process.stderr.write(\n `agent-runtime-mcp: failed to load @tangle-network/sandbox (${err.message}); install the peer dependency\\n`,\n )\n process.exit(2)\n })\n const SandboxCtor = (mod as { Sandbox?: new (config: unknown) => LoopSandboxClient }).Sandbox\n if (!SandboxCtor) {\n process.stderr.write(\n 'agent-runtime-mcp: @tangle-network/sandbox does not export Sandbox; cannot construct client\\n',\n )\n process.exit(2)\n }\n const baseUrl = process.env.SANDBOX_BASE_URL\n return new SandboxCtor({\n apiKey,\n ...(baseUrl ? { baseUrl } : {}),\n })\n}\n\ninterface ResearcherProfilePreset {\n agentRunSpec: Parameters<typeof runLoop>[0]['agentRun'] extends infer T ? NonNullable<T> : never\n output: Parameters<typeof runLoop>[0]['output']\n validator: Parameters<typeof runLoop>[0]['validator']\n}\n\ninterface ResearcherFanoutPreset {\n agentRuns: NonNullable<Parameters<typeof runLoop>[0]['agentRuns']>\n output: Parameters<typeof runLoop>[0]['output']\n validator: Parameters<typeof runLoop>[0]['validator']\n driver: Parameters<typeof runLoop>[0]['driver']\n}\n\nasync function loadResearcherDelegate(\n sandboxClient: LoopSandboxClient,\n maxConcurrency: number,\n): Promise<ResearcherDelegate | undefined> {\n // Optional peer — when `@tangle-network/agent-knowledge` isn't installed,\n // we silently omit the researcher tool from the advertisement. The\n // dynamic-import path is resolved at runtime; TypeScript cannot see the\n // peer, so we type the module structurally rather than via its own\n // declaration file.\n const profilesSpecifier = '@tangle-network/agent-knowledge/profiles'\n const mod = await import(profilesSpecifier).catch(() => undefined)\n if (!mod) return undefined\n type SingleFactory = (opts: { task: unknown }) => ResearcherProfilePreset\n type FanoutFactory = (opts: { task: unknown }) => ResearcherFanoutPreset\n const fanoutFactory = (mod as { multiHarnessResearcherFanout?: FanoutFactory })\n .multiHarnessResearcherFanout\n const singleFactory = (mod as { researcherProfile?: SingleFactory }).researcherProfile\n if (!fanoutFactory || !singleFactory) return undefined\n\n return async (args, ctx) => {\n const task = {\n question: args.question,\n knowledgeNamespace: args.namespace,\n scope: args.scope,\n sources: args.sources,\n recencyWindow: args.config?.recencyWindow\n ? {\n since: args.config.recencyWindow.since\n ? new Date(args.config.recencyWindow.since)\n : undefined,\n until: args.config.recencyWindow.until\n ? new Date(args.config.recencyWindow.until)\n : undefined,\n }\n : undefined,\n maxItems: args.config?.maxItems,\n minConfidence: args.config?.minConfidence,\n }\n const variants = Math.max(1, Math.trunc(args.variants ?? 1))\n ctx.report({ iteration: 0, phase: 'starting' })\n if (variants <= 1) {\n const preset = singleFactory({ task })\n const result = await runLoop({\n driver: {\n name: 'mcp-researcher-single',\n async plan(t, history) {\n return history.length === 0 ? [t] : []\n },\n decide(history) {\n return history.length > 0 ? 'pick-winner' : 'fail'\n },\n },\n agentRun: preset.agentRunSpec,\n output: preset.output,\n validator: preset.validator,\n task,\n ctx: { sandboxClient, signal: ctx.signal },\n maxIterations: 1,\n maxConcurrency,\n })\n const output = result.winner?.output\n if (!output) throw new Error('researcher delegate produced no winner')\n ctx.report({ iteration: 1, phase: 'completed' })\n return output as ResearchOutputShape\n }\n const fanout = fanoutFactory({ task })\n const result = await runLoop({\n driver: fanout.driver,\n agentRuns: fanout.agentRuns.slice(0, variants),\n output: fanout.output,\n validator: fanout.validator,\n task,\n ctx: { sandboxClient, signal: ctx.signal },\n maxIterations: variants,\n maxConcurrency: Math.min(maxConcurrency, variants),\n })\n const output = result.winner?.output\n if (!output) throw new Error('researcher delegate fanout produced no winner')\n ctx.report({ iteration: result.iterations.length, phase: 'completed' })\n return output as ResearchOutputShape\n }\n}\n\nfunction parseHarnesses(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\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 parseConcurrency(raw: string | undefined): number {\n if (!raw) return 4\n const n = Number(raw)\n if (!Number.isFinite(n) || n < 1) return 4\n return Math.min(Math.trunc(n), 32)\n}\n\nmain().catch((err) => {\n process.stderr.write(`agent-runtime-mcp: ${err instanceof Error ? err.stack : String(err)}\\n`)\n process.exit(1)\n})\n"],"mappings":";;;;;;;;;;;;;;;AAuCA,eAAe,OAAsB;AACnC,QAAM,kBAAkB,eAAe,QAAQ,IAAI,0BAA0B;AAC7E,QAAM,iBAAiB,iBAAiB,QAAQ,IAAI,4BAA4B;AAChF,QAAM,YAAY,CAAC,QAAQ,IAAI;AAC/B,QAAM,iBAAiB,CAAC,QAAQ,IAAI;AACpC,QAAM,UAAU,aAAa,QAAQ,IAAI,eAAe;AAMxD,QAAM,eAAe,aAAa;AAClC,MAAI;AACJ,MAAI;AACJ,MAAI,cAAc;AAChB,UAAM,SAAS,QAAQ,IAAI;AAC3B,QAAI,CAAC,UAAU,CAAC,QAAQ,IAAI,gCAAgC;AAC1D,cAAQ,OAAO;AAAA,QACb;AAAA,MACF;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAIA,QAAI,WAAW,CAAC,QAAQ;AACtB,cAAQ,OAAO;AAAA,QACb;AAAA,MACF;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,oBAAgB,MAAM,kBAAkB,MAAM;AAC9C,eAAW,MAAM,eAAe,EAAE,cAAc,CAAC;AACjD,QAAI,SAAS;AACX,cAAQ,OAAO,MAAM,sDAAsD,OAAO;AAAA,CAAI;AAAA,IACxF;AACA,YAAQ,OAAO,MAAM,kDAA6C,SAAS,SAAS,CAAC;AAAA,CAAI;AAAA,EAC3F;AAEA,QAAM,gBACJ,aAAa,WACT,2BAA2B;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC,IACD;AAEN,QAAM,qBACJ,kBAAkB,WACd,MAAM,uBAAuB,SAAS,QAAQ,cAAc,IAC5D;AAEN,QAAM,SAAS,gBAAgB,EAAE,eAAe,mBAAmB,CAAC;AAEpE,UAAQ,GAAG,UAAU,MAAM;AACzB,WAAO,KAAK;AACZ,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACD,UAAQ,GAAG,WAAW,MAAM;AAC1B,WAAO,KAAK;AACZ,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAED,QAAM,OAAO,MAAM;AACrB;AAEA,eAAe,kBAAkB,QAAwD;AAKvF,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,MACL,MAAM,SAAS;AACb,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAIA,QAAM,MAAM,MAAM,OAAO,yBAAyB,EAAE,MAAM,CAAC,QAAQ;AACjE,YAAQ,OAAO;AAAA,MACb,8DAA8D,IAAI,OAAO;AAAA;AAAA,IAC3E;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACD,QAAM,cAAe,IAAiE;AACtF,MAAI,CAAC,aAAa;AAChB,YAAQ,OAAO;AAAA,MACb;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,UAAU,QAAQ,IAAI;AAC5B,SAAO,IAAI,YAAY;AAAA,IACrB;AAAA,IACA,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC/B,CAAC;AACH;AAeA,eAAe,uBACb,eACA,gBACyC;AAMzC,QAAM,oBAAoB;AAC1B,QAAM,MAAM,MAAM,OAAO,mBAAmB,MAAM,MAAM,MAAS;AACjE,MAAI,CAAC,IAAK,QAAO;AAGjB,QAAM,gBAAiB,IACpB;AACH,QAAM,gBAAiB,IAA8C;AACrE,MAAI,CAAC,iBAAiB,CAAC,cAAe,QAAO;AAE7C,SAAO,OAAO,MAAM,QAAQ;AAC1B,UAAM,OAAO;AAAA,MACX,UAAU,KAAK;AAAA,MACf,oBAAoB,KAAK;AAAA,MACzB,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK;AAAA,MACd,eAAe,KAAK,QAAQ,gBACxB;AAAA,QACE,OAAO,KAAK,OAAO,cAAc,QAC7B,IAAI,KAAK,KAAK,OAAO,cAAc,KAAK,IACxC;AAAA,QACJ,OAAO,KAAK,OAAO,cAAc,QAC7B,IAAI,KAAK,KAAK,OAAO,cAAc,KAAK,IACxC;AAAA,MACN,IACA;AAAA,MACJ,UAAU,KAAK,QAAQ;AAAA,MACvB,eAAe,KAAK,QAAQ;AAAA,IAC9B;AACA,UAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,YAAY,CAAC,CAAC;AAC3D,QAAI,OAAO,EAAE,WAAW,GAAG,OAAO,WAAW,CAAC;AAC9C,QAAI,YAAY,GAAG;AACjB,YAAM,SAAS,cAAc,EAAE,KAAK,CAAC;AACrC,YAAMA,UAAS,MAAM,QAAQ;AAAA,QAC3B,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,MAAM,KAAK,GAAG,SAAS;AACrB,mBAAO,QAAQ,WAAW,IAAI,CAAC,CAAC,IAAI,CAAC;AAAA,UACvC;AAAA,UACA,OAAO,SAAS;AACd,mBAAO,QAAQ,SAAS,IAAI,gBAAgB;AAAA,UAC9C;AAAA,QACF;AAAA,QACA,UAAU,OAAO;AAAA,QACjB,QAAQ,OAAO;AAAA,QACf,WAAW,OAAO;AAAA,QAClB;AAAA,QACA,KAAK,EAAE,eAAe,QAAQ,IAAI,OAAO;AAAA,QACzC,eAAe;AAAA,QACf;AAAA,MACF,CAAC;AACD,YAAMC,UAASD,QAAO,QAAQ;AAC9B,UAAI,CAACC,QAAQ,OAAM,IAAI,MAAM,wCAAwC;AACrE,UAAI,OAAO,EAAE,WAAW,GAAG,OAAO,YAAY,CAAC;AAC/C,aAAOA;AAAA,IACT;AACA,UAAM,SAAS,cAAc,EAAE,KAAK,CAAC;AACrC,UAAM,SAAS,MAAM,QAAQ;AAAA,MAC3B,QAAQ,OAAO;AAAA,MACf,WAAW,OAAO,UAAU,MAAM,GAAG,QAAQ;AAAA,MAC7C,QAAQ,OAAO;AAAA,MACf,WAAW,OAAO;AAAA,MAClB;AAAA,MACA,KAAK,EAAE,eAAe,QAAQ,IAAI,OAAO;AAAA,MACzC,eAAe;AAAA,MACf,gBAAgB,KAAK,IAAI,gBAAgB,QAAQ;AAAA,IACnD,CAAC;AACD,UAAM,SAAS,OAAO,QAAQ;AAC9B,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,+CAA+C;AAC5E,QAAI,OAAO,EAAE,WAAW,OAAO,WAAW,QAAQ,OAAO,YAAY,CAAC;AACtE,WAAO;AAAA,EACT;AACF;AAEA,SAAS,eAAe,KAA+C;AACrE,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,OAAO,IACV,MAAM,GAAG,EACT,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAC3B,OAAO,OAAO;AACjB,SAAO,KAAK,SAAS,IAAI,OAAO;AAClC;AAEA,SAAS,aAAa,KAA6C;AACjE,MAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,QAAM,UAAU,IAAI,KAAK;AACzB,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,SAAS,iBAAiB,KAAiC;AACzD,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,IAAI,OAAO,GAAG;AACpB,MAAI,CAAC,OAAO,SAAS,CAAC,KAAK,IAAI,EAAG,QAAO;AACzC,SAAO,KAAK,IAAI,KAAK,MAAM,CAAC,GAAG,EAAE;AACnC;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,OAAO,MAAM,sBAAsB,eAAe,QAAQ,IAAI,QAAQ,OAAO,GAAG,CAAC;AAAA,CAAI;AAC7F,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["result","output"]}
@@ -1,10 +1,131 @@
1
+ import { h as LoopSandboxClient } from '../types-Cu-SkGa0.js';
2
+ import { SandboxInstance } from '@tangle-network/sandbox';
1
3
  import { CoderOutput } from '../profiles.js';
2
- import { g as LoopSandboxClient } from '../types-Bx-tArkc.js';
3
- import '@tangle-network/sandbox';
4
4
  import '../runtime-run-B2j-hvBj.js';
5
5
  import '../types-DvJIha6w.js';
6
6
  import '@tangle-network/agent-eval';
7
7
 
8
+ /**
9
+ * @experimental
10
+ *
11
+ * Delegation executors — the layer between MCP delegates and the sandbox
12
+ * substrate. Each executor exposes a {@link LoopSandboxClient} the kernel
13
+ * consumes plus a placement tag so the trace pipeline can correlate workers
14
+ * with their physical placement.
15
+ *
16
+ * Two implementations ship in-box:
17
+ *
18
+ * - {@link createSiblingSandboxExecutor} — every delegation spawns a fresh
19
+ * sandbox sibling to the caller. Default when the MCP server runs as a
20
+ * standalone CLI mounted outside a fleet.
21
+ *
22
+ * - {@link createFleetWorkspaceExecutor} — delegations dispatch onto machines
23
+ * in the caller's existing fleet so worker diffs land directly on the
24
+ * caller's filesystem (the fleet's shared workspace). Selected when the
25
+ * parent sandbox passes `TANGLE_FLEET_ID` into the MCP server's env.
26
+ */
27
+
28
+ /** @experimental */
29
+ interface DelegationExecutor {
30
+ /** Sandbox client the kernel calls. Returned with `describePlacement` set. */
31
+ readonly client: LoopSandboxClient;
32
+ /** Best-effort one-liner used in stderr boot logs and diagnostics. */
33
+ describe(): string;
34
+ }
35
+ /** @experimental */
36
+ interface SiblingSandboxExecutorOptions {
37
+ client: LoopSandboxClient;
38
+ }
39
+ /**
40
+ * Wrap a raw sandbox SDK client so the kernel emits
41
+ * `loop.iteration.dispatch` events with `{ placement: 'sibling', sandboxId }`.
42
+ *
43
+ * The returned client `.create()` delegates to the underlying client; the
44
+ * only added behavior is a `describePlacement` tag the kernel reads.
45
+ *
46
+ * @experimental
47
+ */
48
+ declare function createSiblingSandboxExecutor(options: SiblingSandboxExecutorOptions): DelegationExecutor;
49
+ /**
50
+ * Minimal `SandboxFleet` surface the fleet executor calls. Declared
51
+ * structurally so tests can pass an in-memory stub without instantiating the
52
+ * sandbox SDK.
53
+ *
54
+ * @experimental
55
+ */
56
+ interface FleetHandle {
57
+ readonly fleetId: string;
58
+ /** Machine ids in dispatch-eligible order. The executor round-robins. */
59
+ readonly ids: ReadonlyArray<string>;
60
+ /** Resolve a machine id to its `SandboxInstance` — that machine is mounted
61
+ * on the fleet's shared workspace, so any diff the worker writes lands on
62
+ * every other fleet machine's filesystem too. */
63
+ sandbox(machineId: string): Promise<SandboxInstance>;
64
+ }
65
+ /** @experimental */
66
+ interface FleetWorkspaceExecutorOptions {
67
+ fleet: FleetHandle;
68
+ /**
69
+ * Override the machine-selection policy. Default = round-robin across
70
+ * `fleet.ids`, skipping the optional `excludeMachineIds` set (typically the
71
+ * coordinator machine the MCP server is running on).
72
+ */
73
+ selectMachine?: (call: {
74
+ callIndex: number;
75
+ ids: ReadonlyArray<string>;
76
+ }) => string;
77
+ /**
78
+ * Machine ids to skip during default round-robin. Set to the caller's own
79
+ * machineId so workers don't compete with the orchestrator on the same VM.
80
+ */
81
+ excludeMachineIds?: ReadonlyArray<string>;
82
+ }
83
+ /**
84
+ * Build an executor that resolves each delegated iteration to an existing
85
+ * machine in `fleet`. The fleet's shared-workspace policy means the worker
86
+ * machine sees the caller's filesystem — diffs land in-place with no
87
+ * cross-sandbox copy step.
88
+ *
89
+ * @experimental
90
+ */
91
+ declare function createFleetWorkspaceExecutor(options: FleetWorkspaceExecutorOptions): DelegationExecutor;
92
+
93
+ /**
94
+ * @experimental
95
+ *
96
+ * Helpers extracted from `bin.ts` so the env-detection + executor-selection
97
+ * logic is unit-testable without spawning a subprocess. The bin imports from
98
+ * here; tests import from here directly.
99
+ */
100
+
101
+ /** @experimental */
102
+ interface DetectExecutorArgs {
103
+ sandboxClient: LoopSandboxClient;
104
+ /** Raw env (defaults to `process.env`). Pass an explicit map for tests. */
105
+ env?: Record<string, string | undefined>;
106
+ /**
107
+ * Override how a fleet handle is resolved from the client + fleet id. The
108
+ * default reads `client.fleets.get(fleetId)` and validates the returned
109
+ * shape against the structural `FleetHandle` contract.
110
+ */
111
+ resolveFleet?: (client: LoopSandboxClient, fleetId: string) => Promise<FleetHandle>;
112
+ }
113
+ /**
114
+ * Pick the right executor for an MCP server invocation based on env vars.
115
+ *
116
+ * - `TANGLE_FLEET_ID` set → fleet-workspace placement; resolves the handle
117
+ * via `sandboxClient.fleets.get(...)`.
118
+ * - Otherwise → sibling-sandbox placement; each delegation creates a fresh
119
+ * sandbox via `sandboxClient.create(...)`.
120
+ *
121
+ * Fails loud (throws) when fleet mode is requested but the SDK shape is
122
+ * incompatible — the operator chose fleet semantics, silently degrading to
123
+ * sibling mode would lie about workspace topology.
124
+ *
125
+ * @experimental
126
+ */
127
+ declare function detectExecutor(args: DetectExecutorArgs): Promise<DelegationExecutor>;
128
+
8
129
  /**
9
130
  * @experimental
10
131
  *
@@ -215,7 +336,18 @@ type CoderDelegate = (args: DelegateCodeArgs, ctx: DelegateRunCtx) => Promise<Co
215
336
  type ResearcherDelegate = (args: DelegateResearchArgs, ctx: DelegateRunCtx) => Promise<ResearchOutputShape>;
216
337
  /** @experimental */
217
338
  interface CreateDefaultCoderDelegateOptions {
218
- sandboxClient: LoopSandboxClient;
339
+ /**
340
+ * Execution placement. Pass a {@link DelegationExecutor} (sibling or fleet)
341
+ * to control where worker iterations land. `sandboxClient` is a
342
+ * convenience shorthand that wraps the client in a sibling executor — pass
343
+ * one or the other, not both.
344
+ */
345
+ executor?: DelegationExecutor;
346
+ /**
347
+ * Convenience shorthand for sibling placement. Equivalent to
348
+ * `executor: createSiblingSandboxExecutor({ client: sandboxClient })`.
349
+ */
350
+ sandboxClient?: LoopSandboxClient;
219
351
  /** Default `['claude-code', 'codex', 'opencode/zai-coding-plan/glm-5.1']` when variants > 1. */
220
352
  fanoutHarnesses?: string[];
221
353
  /** Hard cap on the kernel's per-batch concurrency. Default 4. */
@@ -824,4 +956,4 @@ interface DelegationStatusHandlerOptions {
824
956
  /** @experimental */
825
957
  declare function createDelegationStatusHandler(options: DelegationStatusHandlerOptions): (raw: unknown) => Promise<DelegationStatusResult>;
826
958
 
827
- export { type CoderDelegate, type CreateDefaultCoderDelegateOptions, DELEGATE_CODE_DESCRIPTION, DELEGATE_CODE_INPUT_SCHEMA, DELEGATE_CODE_TOOL_NAME, DELEGATE_FEEDBACK_DESCRIPTION, DELEGATE_FEEDBACK_INPUT_SCHEMA, DELEGATE_FEEDBACK_TOOL_NAME, DELEGATE_RESEARCH_DESCRIPTION, DELEGATE_RESEARCH_INPUT_SCHEMA, DELEGATE_RESEARCH_TOOL_NAME, DELEGATION_HISTORY_DESCRIPTION, DELEGATION_HISTORY_INPUT_SCHEMA, DELEGATION_HISTORY_TOOL_NAME, DELEGATION_STATUS_DESCRIPTION, DELEGATION_STATUS_INPUT_SCHEMA, DELEGATION_STATUS_TOOL_NAME, type DelegateCodeArgs, type DelegateCodeConfig, type DelegateCodeResult, type DelegateFeedbackArgs, type DelegateFeedbackResult, type DelegateResearchArgs, type DelegateResearchConfig, type DelegateResearchResult, type DelegateRunCtx, type DelegationError, type DelegationFeedbackSnapshot, type DelegationHistoryArgs, type DelegationHistoryEntry, type DelegationHistoryResult, type DelegationProfile, type DelegationProgress, type DelegationRecord, type DelegationResultPayload, type DelegationStatus, type DelegationStatusArgs, type DelegationStatusResult, DelegationTaskQueue, type DelegationTaskQueueOptions, type FeedbackEvent, type FeedbackRating, type FeedbackRefersTo, type FeedbackStore, InMemoryFeedbackStore, type JsonRpcMessage, type JsonRpcResponse, type McpServer, type McpServerOptions, type McpToolDescriptor, type McpTransport, type ResearchOutputShape, type ResearchSource, type ResearcherDelegate, type SubmitInput, type SubmitOutput, createDefaultCoderDelegate, createDelegateCodeHandler, createDelegateFeedbackHandler, createDelegateResearchHandler, createDelegationHistoryHandler, createDelegationStatusHandler, createInProcessTransport, createMcpServer, eventToSnapshot, hashIdempotencyInput, validateDelegateCodeArgs, validateDelegateFeedbackArgs, validateDelegateResearchArgs, validateDelegationHistoryArgs, validateDelegationStatusArgs };
959
+ export { type CoderDelegate, type CreateDefaultCoderDelegateOptions, DELEGATE_CODE_DESCRIPTION, DELEGATE_CODE_INPUT_SCHEMA, DELEGATE_CODE_TOOL_NAME, DELEGATE_FEEDBACK_DESCRIPTION, DELEGATE_FEEDBACK_INPUT_SCHEMA, DELEGATE_FEEDBACK_TOOL_NAME, DELEGATE_RESEARCH_DESCRIPTION, DELEGATE_RESEARCH_INPUT_SCHEMA, DELEGATE_RESEARCH_TOOL_NAME, DELEGATION_HISTORY_DESCRIPTION, DELEGATION_HISTORY_INPUT_SCHEMA, DELEGATION_HISTORY_TOOL_NAME, DELEGATION_STATUS_DESCRIPTION, DELEGATION_STATUS_INPUT_SCHEMA, DELEGATION_STATUS_TOOL_NAME, type DelegateCodeArgs, type DelegateCodeConfig, type DelegateCodeResult, type DelegateFeedbackArgs, type DelegateFeedbackResult, type DelegateResearchArgs, type DelegateResearchConfig, type DelegateResearchResult, type DelegateRunCtx, type DelegationError, type DelegationExecutor, type DelegationFeedbackSnapshot, type DelegationHistoryArgs, type DelegationHistoryEntry, type DelegationHistoryResult, type DelegationProfile, type DelegationProgress, type DelegationRecord, type DelegationResultPayload, type DelegationStatus, type DelegationStatusArgs, type DelegationStatusResult, DelegationTaskQueue, type DelegationTaskQueueOptions, type DetectExecutorArgs, type FeedbackEvent, type FeedbackRating, type FeedbackRefersTo, type FeedbackStore, type FleetHandle, type FleetWorkspaceExecutorOptions, InMemoryFeedbackStore, type JsonRpcMessage, type JsonRpcResponse, type McpServer, type McpServerOptions, type McpToolDescriptor, type McpTransport, type ResearchOutputShape, type ResearchSource, type ResearcherDelegate, type SiblingSandboxExecutorOptions, type SubmitInput, type SubmitOutput, createDefaultCoderDelegate, createDelegateCodeHandler, createDelegateFeedbackHandler, createDelegateResearchHandler, createDelegationHistoryHandler, createDelegationStatusHandler, createFleetWorkspaceExecutor, createInProcessTransport, createMcpServer, createSiblingSandboxExecutor, detectExecutor, eventToSnapshot, hashIdempotencyInput, validateDelegateCodeArgs, validateDelegateFeedbackArgs, validateDelegateResearchArgs, validateDelegationHistoryArgs, validateDelegationStatusArgs };
package/dist/mcp/index.js CHANGED
@@ -22,8 +22,11 @@ import {
22
22
  createDelegateResearchHandler,
23
23
  createDelegationHistoryHandler,
24
24
  createDelegationStatusHandler,
25
+ createFleetWorkspaceExecutor,
25
26
  createInProcessTransport,
26
27
  createMcpServer,
28
+ createSiblingSandboxExecutor,
29
+ detectExecutor,
27
30
  eventToSnapshot,
28
31
  hashIdempotencyInput,
29
32
  validateDelegateCodeArgs,
@@ -31,8 +34,8 @@ import {
31
34
  validateDelegateResearchArgs,
32
35
  validateDelegationHistoryArgs,
33
36
  validateDelegationStatusArgs
34
- } from "../chunk-LPPM7EGS.js";
35
- import "../chunk-VFUEE6DF.js";
37
+ } from "../chunk-QDNJLAEU.js";
38
+ import "../chunk-EDVCVFQB.js";
36
39
  import "../chunk-Z5LKAYAS.js";
37
40
  import "../chunk-XLWPTPRP.js";
38
41
  import "../chunk-RZAOYKCO.js";
@@ -61,8 +64,11 @@ export {
61
64
  createDelegateResearchHandler,
62
65
  createDelegationHistoryHandler,
63
66
  createDelegationStatusHandler,
67
+ createFleetWorkspaceExecutor,
64
68
  createInProcessTransport,
65
69
  createMcpServer,
70
+ createSiblingSandboxExecutor,
71
+ detectExecutor,
66
72
  eventToSnapshot,
67
73
  hashIdempotencyInput,
68
74
  validateDelegateCodeArgs,
@@ -1,5 +1,5 @@
1
1
  import { AgentProfile } from '@tangle-network/sandbox';
2
- import { O as OutputAdapter, V as Validator, A as AgentRunSpec, a as Driver } from './types-Bx-tArkc.js';
2
+ import { O as OutputAdapter, V as Validator, A as AgentRunSpec, a as Driver } from './types-Cu-SkGa0.js';
3
3
  import './runtime-run-B2j-hvBj.js';
4
4
  import './types-DvJIha6w.js';
5
5
  import '@tangle-network/agent-eval';