@tangle-network/agent-runtime 0.94.11 → 0.94.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +65 -1
  2. package/dist/agent.d.ts +2 -1
  3. package/dist/agent.js +2 -1
  4. package/dist/agent.js.map +1 -1
  5. package/dist/{agentic-generator-JT47GnAp.d.ts → agentic-generator-DDMM45kZ.d.ts} +2 -2
  6. package/dist/analyst-loop.d.ts +2 -1
  7. package/dist/backends-BO4Jqoe2.d.ts +134 -0
  8. package/dist/candidate-execution/index.d.ts +2 -2
  9. package/dist/candidate-execution/index.js +2 -2
  10. package/dist/chunk-AEG3NGJ2.js +639 -0
  11. package/dist/chunk-AEG3NGJ2.js.map +1 -0
  12. package/dist/{chunk-37V4KQDC.js → chunk-CNH7DF7Z.js} +173 -84
  13. package/dist/chunk-CNH7DF7Z.js.map +1 -0
  14. package/dist/{chunk-OLZ6ZZQ2.js → chunk-D3H7F6L2.js} +11 -8
  15. package/dist/chunk-D3H7F6L2.js.map +1 -0
  16. package/dist/{chunk-5LIOH5DR.js → chunk-PCURO3DL.js} +4 -4
  17. package/dist/chunk-PCURO3DL.js.map +1 -0
  18. package/dist/{chunk-FTXM7Q7P.js → chunk-TVJQAYQM.js} +13 -21
  19. package/dist/chunk-TVJQAYQM.js.map +1 -0
  20. package/dist/{chunk-YP6B7RZ2.js → chunk-U33YZ7B2.js} +6 -635
  21. package/dist/chunk-U33YZ7B2.js.map +1 -0
  22. package/dist/chunk-VYA2YEKA.js +1187 -0
  23. package/dist/chunk-VYA2YEKA.js.map +1 -0
  24. package/dist/{chunk-MXBQNVFE.js → chunk-XP5KDM3R.js} +5 -5
  25. package/dist/{completion-gate-Bn4AZ_Kw.d.ts → completion-gate-D1gX1-hg.d.ts} +1 -1
  26. package/dist/conversation.d.ts +793 -0
  27. package/dist/conversation.js +56 -0
  28. package/dist/conversation.js.map +1 -0
  29. package/dist/{coordination-DzwagV_s.d.ts → coordination-Dr_axlAf.d.ts} +5 -4
  30. package/dist/environment-provider.d.ts +3 -2
  31. package/dist/{improve-BucbjddC.d.ts → improve-BN3HyXIO.d.ts} +1 -1
  32. package/dist/index.d.ts +29 -943
  33. package/dist/index.js +60 -1161
  34. package/dist/index.js.map +1 -1
  35. package/dist/intelligence.d.ts +6 -5
  36. package/dist/intelligence.js +6 -6
  37. package/dist/knowledge.d.ts +7 -6
  38. package/dist/lifecycle.d.ts +2 -2
  39. package/dist/lifecycle.js +1 -1
  40. package/dist/{loop-runner-bin-D6K_C6op.d.ts → loop-runner-bin-BRQSQdHa.d.ts} +2 -2
  41. package/dist/loop-runner-bin.d.ts +6 -5
  42. package/dist/loop-runner-bin.js +4 -3
  43. package/dist/loops.d.ts +15 -14
  44. package/dist/loops.js +2 -1
  45. package/dist/mcp/index.d.ts +9 -8
  46. package/dist/mcp/index.js +2 -1
  47. package/dist/mcp/index.js.map +1 -1
  48. package/dist/{mcp-serve-verifier-i6nTNSnu.d.ts → mcp-serve-verifier-DQQDbuyz.d.ts} +1 -1
  49. package/dist/{openai-tools-0wACz8f8.d.ts → openai-tools-fnj6SRVg.d.ts} +1 -1
  50. package/dist/{prepare-DIeVgQG3.d.ts → prepare-CtdtsFNG.d.ts} +18 -14
  51. package/dist/primeintellect/index.d.ts +214 -0
  52. package/dist/primeintellect/index.js +1120 -0
  53. package/dist/primeintellect/index.js.map +1 -0
  54. package/dist/profiles.d.ts +2 -1
  55. package/dist/{sanitize-Dcbjp0tU.d.ts → sanitize-BTSsdBXw.d.ts} +1 -1
  56. package/dist/{supervise-CzyytS-o.d.ts → supervise-DmYOug5f.d.ts} +4 -4
  57. package/dist/{types-CogNCaw7.d.ts → types-1d5QGK3t.d.ts} +1 -1
  58. package/dist/types-BwoZWq-i.d.ts +510 -0
  59. package/dist/{types-CKmyZ9TP.d.ts → types-ByAYqlVb.d.ts} +3 -509
  60. package/dist/{worktree-fanout-Bn7w_1bM.d.ts → worktree-fanout-CPprU-qI.d.ts} +3 -3
  61. package/package.json +17 -5
  62. package/dist/chunk-37V4KQDC.js.map +0 -1
  63. package/dist/chunk-5LIOH5DR.js.map +0 -1
  64. package/dist/chunk-FTXM7Q7P.js.map +0 -1
  65. package/dist/chunk-OLZ6ZZQ2.js.map +0 -1
  66. package/dist/chunk-YP6B7RZ2.js.map +0 -1
  67. /package/dist/{chunk-MXBQNVFE.js.map → chunk-XP5KDM3R.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sessions.ts","../src/backends.ts"],"sourcesContent":["/**\n *\n * Session helpers + an in-memory `RuntimeSessionStore` implementation suitable\n * for tests, scratch processes, and per-request scratch storage in serverless\n * runtimes. Durable stores (D1, postgres, Durable Objects) implement the same\n * interface from `./types`.\n *\n * @stable\n */\n\nimport type { RuntimeSession, RuntimeSessionStore, RuntimeStreamEvent } from './types'\n\n/** @internal */\nexport function newRuntimeSession(\n backend: string,\n requestedId?: string,\n metadata?: Record<string, unknown>,\n): RuntimeSession {\n const now = nowIso()\n return {\n id: requestedId || crypto.randomUUID(),\n backend,\n status: 'active',\n createdAt: now,\n updatedAt: now,\n metadata,\n }\n}\n\n/** @internal */\nexport function touchSession(session: RuntimeSession): RuntimeSession {\n return { ...session, updatedAt: nowIso() }\n}\n\n/** @internal */\nexport function nowIso(): string {\n return new Date().toISOString()\n}\n\n/** In-memory `RuntimeSessionStore` for single-process use and tests. @stable */\nexport class InMemoryRuntimeSessionStore implements RuntimeSessionStore {\n private readonly sessions = new Map<string, RuntimeSession>()\n private readonly events = new Map<string, RuntimeStreamEvent[]>()\n\n get(sessionId: string): RuntimeSession | undefined {\n return this.sessions.get(sessionId)\n }\n\n put(session: RuntimeSession): void {\n this.sessions.set(session.id, session)\n }\n\n appendEvent(sessionId: string, event: RuntimeStreamEvent): void {\n const existing = this.events.get(sessionId) ?? []\n existing.push(event)\n this.events.set(sessionId, existing)\n }\n\n listEvents(sessionId: string): RuntimeStreamEvent[] {\n return [...(this.events.get(sessionId) ?? [])]\n }\n}\n","/**\n *\n * Backend factories for `runAgentTaskStream`. Three shapes ship in core:\n *\n * - `createIterableBackend` — wrap any custom async iterable into a backend\n * - `createSandboxPromptBackend` — sandbox / sidecar `streamPrompt` clients\n * - `createOpenAICompatibleBackend` — OpenAI-style chat completions endpoints\n *\n * Adapters stay thin: domain repos own auth, model selection, and the concrete\n * tool surface. The factories handle session creation, stream normalization,\n * and graceful end-of-stream signalling.\n *\n * @stable\n */\n\nimport { BackendTransportError } from './errors'\nimport { newRuntimeSession, nowIso, touchSession } from './sessions'\nimport type {\n AgentBackendContext,\n AgentBackendInput,\n AgentExecutionBackend,\n OpenAIChatResponseFormat,\n OpenAIChatTool,\n OpenAIChatToolChoice,\n RuntimeSession,\n RuntimeStreamEvent,\n} from './types'\n\n/** Wrap any custom async-iterable stream into a typed `AgentExecutionBackend`. @stable */\nexport function createIterableBackend<TInput extends AgentBackendInput>(options: {\n kind: string\n start?: AgentExecutionBackend<TInput>['start']\n resume?: AgentExecutionBackend<TInput>['resume']\n stream: AgentExecutionBackend<TInput>['stream']\n stop?: AgentExecutionBackend<TInput>['stop']\n}): AgentExecutionBackend<TInput> {\n return options\n}\n\n/** Build an `AgentExecutionBackend` backed by a sandbox/sidecar `streamPrompt` call. @stable */\nexport function createSandboxPromptBackend<\n TBox,\n TInput extends AgentBackendInput = AgentBackendInput,\n>(options: {\n kind?: string\n getBox(input: TInput, context: Omit<AgentBackendContext, 'session'>): Promise<TBox> | TBox\n streamPrompt(box: TBox, message: string, context: AgentBackendContext): AsyncIterable<unknown>\n mapEvent?: (event: unknown, context: AgentBackendContext) => RuntimeStreamEvent | undefined\n getSessionId?: (box: TBox, input: TInput) => string | undefined\n}): AgentExecutionBackend<TInput> {\n const kind = options.kind ?? 'sandbox'\n return {\n kind,\n async start(input, context) {\n const box = await options.getBox(input, context)\n return newRuntimeSession(\n kind,\n options.getSessionId?.(box, input) ?? context.requestedSessionId,\n { resumable: true },\n )\n },\n resume(session) {\n return touchSession({ ...session, status: 'active' })\n },\n async *stream(input, context) {\n const box = await options.getBox(input, context)\n const message = input.message ?? input.messages?.at(-1)?.content ?? context.task.intent\n for await (const event of options.streamPrompt(box, message, context)) {\n const mapped = options.mapEvent?.(event, context) ?? mapCommonBackendEvent(event, context)\n if (mapped) yield mapped\n }\n },\n }\n}\n\n/** @stable */\n/**\n * Retry policy for transient transport errors (rate limits, upstream\n * timeouts). Defaults to 5 attempts with exponential backoff starting at\n * 1s, ±25% jitter, capped at 30s. Set `maxAttempts: 1` to disable retries.\n *\n * Retried status codes:\n * - 408 Request Timeout\n * - 425 Too Early\n * - 429 Too Many Requests\n * - 500 / 502 / 503 / 504 — upstream transient failures\n *\n * Hard failures (401, 403, 4xx other than the above) propagate immediately.\n */\nexport interface BackendRetryPolicy {\n /** Total attempts including the first try. Default 5. */\n maxAttempts?: number\n /** Initial backoff in ms before the second attempt. Default 1000. */\n initialBackoffMs?: number\n /** Hard ceiling on backoff in ms. Default 30000. */\n maxBackoffMs?: number\n /** Jitter fraction in [0, 1]. Default 0.25 (±25%). */\n jitter?: number\n /** Status codes that trigger a retry. Default: 408, 425, 429, 500, 502, 503, 504. */\n retryStatuses?: ReadonlyArray<number>\n /**\n * Per-attempt wall-clock deadline in ms. If a single fetch attempt does\n * not return headers within this window the attempt is aborted and\n * retried. Default 120000 (2 min). Without this a hung upstream blocks\n * the attempt indefinitely — observed in production as a 15-minute\n * `fetch failed` that burned an entire eval persona. Set to 0 to disable.\n */\n requestTimeoutMs?: number\n}\n\nconst DEFAULT_RETRY_STATUSES = [408, 425, 429, 500, 502, 503, 504] as const\n\nfunction pickRetryDelayMs(attempt: number, policy: Required<BackendRetryPolicy>): number {\n const exp = policy.initialBackoffMs * 2 ** (attempt - 1)\n const capped = Math.min(exp, policy.maxBackoffMs)\n const jitter = capped * policy.jitter * (Math.random() * 2 - 1)\n return Math.max(0, Math.round(capped + jitter))\n}\n\n/**\n * Derive a per-attempt AbortSignal that fires when EITHER the caller's\n * signal aborts OR `timeoutMs` elapses. `dispose()` clears the timer so a\n * completed attempt doesn't leak a pending timeout. `timeoutMs <= 0`\n * disables the deadline (caller signal still propagates).\n */\nfunction withTimeout(\n callerSignal: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; dispose: () => void } {\n if (timeoutMs <= 0) {\n return { signal: callerSignal ?? new AbortController().signal, dispose: () => undefined }\n }\n const controller = new AbortController()\n const timer = setTimeout(\n () => controller.abort(new Error(`request timed out after ${timeoutMs}ms`)),\n timeoutMs,\n )\n if (typeof (timer as { unref?: () => void }).unref === 'function') {\n ;(timer as { unref: () => void }).unref()\n }\n const onCallerAbort = () => controller.abort(callerSignal?.reason ?? new Error('aborted'))\n if (callerSignal) {\n if (callerSignal.aborted) onCallerAbort()\n else callerSignal.addEventListener('abort', onCallerAbort, { once: true })\n }\n return {\n signal: controller.signal,\n dispose: () => {\n clearTimeout(timer)\n callerSignal?.removeEventListener('abort', onCallerAbort)\n },\n }\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason ?? new Error('aborted'))\n return\n }\n const t = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n const onAbort = () => {\n clearTimeout(t)\n reject(signal?.reason ?? new Error('aborted'))\n }\n signal?.addEventListener('abort', onAbort, { once: true })\n })\n}\n\n/**\n *\n * OpenAI-compat streaming backend. Routes `runAgentTaskStream` through any\n * `POST /chat/completions` endpoint that speaks OpenAI's SSE protocol —\n * Tangle Router, OpenAI direct, OpenRouter, Groq, DeepSeek, Together. The\n * router also fronts Anthropic models in Anthropic-native SSE shape; this\n * backend handles both.\n *\n * ### Tool calls\n *\n * Pass `tools` (and optionally `toolChoice`) to forward an OpenAI Chat\n * Completions `tools[]` array on every request. Streamed `tool_call` chunks\n * are buffered until the model finalizes them (either `finish_reason:\n * 'tool_calls'` for OpenAI shape or a `content_block_stop` for Anthropic\n * `tool_use` blocks proxied through the router), then emitted as a single\n * `tool_call` RuntimeStreamEvent with the assembled `args`.\n *\n * The backend does NOT execute tools — it surfaces calls for the caller's\n * own dispatcher (typically the product's MCP / sandbox runtime) to fulfill\n * and feed back as a subsequent `messages` turn. This keeps the transport\n * thin and lets the agent host own tool dispatch policy.\n *\n * ### Fail-loud errors\n *\n * Non-success HTTP responses (4xx/5xx) and exhausted retry budgets throw\n * `BackendTransportError` from inside the `stream()` generator. The runtime\n * catches the throw, yields a `backend_error` with a typed `error` field\n * (`kind`, `status`, truncated `body`) and a terminal `final` event with\n * `status: 'failed'` carrying the same detail. Consumers MUST map\n * `final.error` onto their `RunRecord.error` — silently treating an empty\n * `finalText` as \"agent produced nothing\" hides credit exhaustion, auth\n * failure, and upstream outages.\n *\n * @stable\n */\nexport function createOpenAICompatibleBackend<\n TInput extends AgentBackendInput = AgentBackendInput,\n>(options: {\n apiKey: string\n baseUrl: string\n model: string\n kind?: string\n /**\n * OpenAI Chat Completions `tools[]` definitions surfaced to the model on\n * every request. Omit to send a tool-free request (existing behavior).\n * The runtime makes no assumption about the dispatcher — calls stream out\n * as `tool_call` events and the caller is responsible for executing them\n * and feeding `tool_result` messages back on a follow-up turn.\n */\n tools?: ReadonlyArray<OpenAIChatTool>\n /**\n * OpenAI Chat Completions `tool_choice`. Default `undefined` (request\n * omits the field; provider falls back to its own default — typically\n * `'auto'`).\n */\n toolChoice?: OpenAIChatToolChoice\n /**\n * OpenAI Chat Completions `response_format`. Omit for provider default text.\n */\n responseFormat?: OpenAIChatResponseFormat\n /** OpenAI Chat Completions `temperature`. Omit for provider default. */\n temperature?: number\n /** Maximum completion tokens, sent as OpenAI-compatible `max_tokens`. Omit for provider default. */\n maxTokens?: number\n fetchImpl?: typeof fetch\n retry?: BackendRetryPolicy\n}): AgentExecutionBackend<TInput> {\n const fetcher = options.fetchImpl ?? fetch\n const kind = options.kind ?? 'tcloud'\n const retryPolicy: Required<BackendRetryPolicy> = {\n maxAttempts: options.retry?.maxAttempts ?? 5,\n initialBackoffMs: options.retry?.initialBackoffMs ?? 1000,\n maxBackoffMs: options.retry?.maxBackoffMs ?? 30000,\n jitter: options.retry?.jitter ?? 0.25,\n retryStatuses: options.retry?.retryStatuses ?? DEFAULT_RETRY_STATUSES,\n requestTimeoutMs: options.retry?.requestTimeoutMs ?? 120_000,\n }\n return {\n kind,\n start(_input, context) {\n return newRuntimeSession(kind, context.requestedSessionId)\n },\n async *stream(input, context) {\n const url = `${options.baseUrl.replace(/\\/$/, '')}/chat/completions`\n // `stream_options.include_usage` instructs OpenAI-compatible providers\n // (and the Tangle Router) to emit a final usage chunk in the SSE stream.\n // Without this the response carries no token counts and every downstream\n // ledger reads zero. Providers that don't recognize the field ignore it.\n const bodyPayload: Record<string, unknown> = {\n model: options.model,\n stream: true,\n stream_options: { include_usage: true },\n messages: input.messages ?? [\n { role: 'user', content: input.message ?? context.task.intent },\n ],\n }\n if (options.tools && options.tools.length > 0) {\n bodyPayload.tools = options.tools\n if (options.toolChoice !== undefined) bodyPayload.tool_choice = options.toolChoice\n }\n if (options.responseFormat !== undefined) {\n bodyPayload.response_format = options.responseFormat\n }\n if (options.temperature !== undefined) {\n bodyPayload.temperature = options.temperature\n }\n if (options.maxTokens !== undefined) {\n bodyPayload.max_tokens = options.maxTokens\n }\n const requestBody = JSON.stringify(bodyPayload)\n let response: Response | undefined\n let lastStatus = 0\n // The last thrown transport error (timeout abort, DNS / connection\n // failure). Network throws are retryable just like 5xx — without this\n // a `fetch failed` propagated immediately and burned the attempt.\n let lastThrown: unknown\n for (let attempt = 1; attempt <= retryPolicy.maxAttempts; attempt++) {\n lastThrown = undefined\n // Per-attempt deadline: abort a hung upstream instead of waiting\n // forever. Linked to context.signal so a caller cancel still wins.\n const attemptSignal = withTimeout(context.signal, retryPolicy.requestTimeoutMs)\n try {\n response = await fetcher(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${options.apiKey}`,\n 'Content-Type': 'application/json',\n // Cross-gateway forwarding: when this call is part of a\n // multi-agent conversation, the runner stamps run/turn/\n // depth/forwarded-auth headers onto the context. They flow\n // through to the downstream gateway verbatim so the original\n // user gets billed, the recursion depth stays bounded, and\n // the trace correlates across hops.\n ...(context.propagatedHeaders ?? {}),\n },\n body: requestBody,\n signal: attemptSignal.signal,\n })\n } catch (err) {\n attemptSignal.dispose()\n // A caller-initiated abort is terminal — do not retry it.\n if (context.signal?.aborted) throw err\n lastThrown = err\n response = undefined\n if (attempt === retryPolicy.maxAttempts) break\n await sleep(pickRetryDelayMs(attempt, retryPolicy), context.signal)\n continue\n }\n attemptSignal.dispose()\n if (response.ok) break\n lastStatus = response.status\n if (!retryPolicy.retryStatuses.includes(response.status)) break\n if (attempt === retryPolicy.maxAttempts) break\n // Drain the failed body so the connection can be reused.\n try {\n await response.body?.cancel()\n } catch {\n // Best-effort — some runtimes don't expose cancel.\n }\n const delayMs = pickRetryDelayMs(attempt, retryPolicy)\n await sleep(delayMs, context.signal)\n }\n if (!response) {\n const reason = lastThrown instanceof Error ? lastThrown.message : String(lastThrown)\n throw new BackendTransportError(\n kind,\n `chat backend unreachable after ${retryPolicy.maxAttempts} attempts: ${reason}`,\n { status: 0 },\n )\n }\n if (!response.ok) {\n // Capture the upstream body so the operator sees *why* the call\n // failed (e.g. `free_tier_limit`, `invalid_api_key`,\n // `model_not_found`). Truncate aggressively — HTML error pages from a\n // misconfigured proxy can be megabytes and would otherwise bloat\n // every persisted event. Best-effort: if body reading throws we\n // still surface the status code.\n let body: string | undefined\n try {\n const raw = await response.text()\n body = raw.length > MAX_ERROR_BODY_BYTES ? `${raw.slice(0, MAX_ERROR_BODY_BYTES)}…` : raw\n } catch {\n body = undefined\n }\n throw new BackendTransportError(kind, `chat backend returned ${lastStatus || 'unknown'}`, {\n status: lastStatus || 0,\n body,\n })\n }\n yield* streamResponseEvents(response, context, options.model)\n },\n }\n}\n\n/**\n * Cap the captured error body. 2 KiB is enough to carry a JSON error envelope\n * with a structured `code`/`message` payload (the router returns ~150 bytes\n * for a free-tier denial; OpenAI returns ~300 bytes for invalid auth) without\n * letting an HTML error page balloon persisted events.\n */\nconst MAX_ERROR_BODY_BYTES = 2048\n\n/**\n * Token usage accumulated across an SSE stream. OpenAI emits a single final\n * `usage` chunk; Anthropic emits `input_tokens` on `message_start` and\n * `output_tokens` on the terminal `message_delta`. We accept both — and the\n * router proxy may forward either shape depending on which upstream answered.\n */\ninterface StreamUsageAccumulator {\n tokensIn?: number\n tokensOut?: number\n model?: string\n finishReason?: string\n saw: boolean\n}\n\n/** @internal */\nexport function normalizeBackendStreamEvent(\n event: RuntimeStreamEvent,\n task: AgentBackendContext['task'],\n session: RuntimeSession,\n): RuntimeStreamEvent {\n if (\n 'task' in event &&\n event.task &&\n 'session' in event &&\n event.session &&\n 'timestamp' in event &&\n event.timestamp\n ) {\n return event\n }\n return {\n ...event,\n task: 'task' in event && event.task ? event.task : task,\n session: 'session' in event && event.session ? event.session : session,\n timestamp: 'timestamp' in event && event.timestamp ? event.timestamp : nowIso(),\n } as RuntimeStreamEvent\n}\n\nfunction mapCommonBackendEvent(\n event: unknown,\n context: AgentBackendContext,\n): RuntimeStreamEvent | undefined {\n if (!event || typeof event !== 'object') return undefined\n const record = event as Record<string, unknown>\n const type = String(record.type ?? '')\n const data =\n record.data && typeof record.data === 'object'\n ? (record.data as Record<string, unknown>)\n : record\n if (type === 'message.part.updated' || type === 'text_delta' || type === 'delta') {\n // `@tangle-network/sandbox` `box.streamTask` emits `message.part.updated`\n // with a nested part: `{ type: 'message.part.updated', data: { part:\n // { type: 'text', text: '…' } } }`. Walk into `data.part.text` so the\n // canonical sandbox-SDK shape produces a `text_delta` natively — no\n // per-product `mapEvent` shim required. Tool parts are picked up by\n // the `tool_call` / `tool_result` branches below; non-text parts here\n // fall through to `undefined` (the consumer can opt in via `mapEvent`).\n const part = data.part as Record<string, unknown> | undefined\n const partText =\n part !== undefined &&\n typeof part === 'object' &&\n (part.type === 'text' || part.type === undefined)\n ? stringValue(part.text)\n : undefined\n const text =\n stringValue(data.text) ?? stringValue(data.delta) ?? stringValue(record.text) ?? partText\n return text\n ? {\n type: 'text_delta',\n task: context.task,\n session: context.session,\n text,\n timestamp: nowIso(),\n }\n : undefined\n }\n if (type === 'reasoning_delta') {\n const text = stringValue(data.text) ?? stringValue(record.text)\n return text\n ? {\n type: 'reasoning_delta',\n task: context.task,\n session: context.session,\n text,\n timestamp: nowIso(),\n }\n : undefined\n }\n if (type === 'tool_call') {\n return {\n type: 'tool_call',\n task: context.task,\n session: context.session,\n toolName: stringValue(data.name) ?? stringValue(record.toolName) ?? 'tool',\n toolCallId: stringValue(data.id) ?? stringValue(record.toolCallId),\n args: data.args ?? data.input ?? record.args,\n timestamp: nowIso(),\n }\n }\n if (type === 'tool_result') {\n return {\n type: 'tool_result',\n task: context.task,\n session: context.session,\n toolName: stringValue(data.name) ?? stringValue(record.toolName) ?? 'tool',\n toolCallId: stringValue(data.id) ?? stringValue(record.toolCallId),\n result: data.result ?? data.output ?? record.result,\n timestamp: nowIso(),\n }\n }\n if (type === 'artifact') {\n const artifactId =\n stringValue(data.artifactId) ?? stringValue(data.id) ?? stringValue(record.artifactId)\n if (!artifactId) return undefined\n return {\n type: 'artifact',\n task: context.task,\n session: context.session,\n artifactId,\n name: stringValue(data.name) ?? stringValue(record.name),\n mimeType: stringValue(data.mimeType) ?? stringValue(record.mimeType),\n uri: stringValue(data.uri) ?? stringValue(record.uri),\n content: stringValue(data.content) ?? stringValue(data.body) ?? stringValue(record.content),\n metadata:\n data.metadata && typeof data.metadata === 'object'\n ? (data.metadata as Record<string, unknown>)\n : undefined,\n timestamp: nowIso(),\n }\n }\n if (type === 'proposal_created' || type === 'proposal' || type === 'filing') {\n const proposalId =\n stringValue(data.proposalId) ?? stringValue(data.id) ?? stringValue(record.proposalId)\n if (!proposalId) return undefined\n const status = stringValue(data.status) ?? stringValue(record.status)\n return {\n type: 'proposal_created',\n task: context.task,\n session: context.session,\n proposalId,\n title: stringValue(data.title) ?? stringValue(record.title) ?? proposalId,\n status:\n status === 'pending' || status === 'approved' || status === 'rejected' ? status : undefined,\n content: stringValue(data.content) ?? stringValue(data.body) ?? stringValue(record.content),\n timestamp: nowIso(),\n }\n }\n if (type === 'result' || type === 'final') {\n const text = stringValue(data.finalText) ?? stringValue(data.text) ?? stringValue(record.text)\n return text\n ? {\n type: 'text_delta',\n task: context.task,\n session: context.session,\n text,\n timestamp: nowIso(),\n }\n : undefined\n }\n return undefined\n}\n\nasync function* streamResponseEvents(\n response: Response,\n context: AgentBackendContext,\n requestedModel: string,\n): AsyncIterable<RuntimeStreamEvent> {\n const body = response.body\n if (!body) return\n const reader = body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n const usage: StreamUsageAccumulator = { saw: false }\n // Tool-call assembly is stateful across SSE chunks: both OpenAI and\n // Anthropic streamed `arguments`/`partial_json` incrementally and the\n // final event is only safe to emit once we see a `finish_reason:\n // 'tool_calls'` or `content_block_stop` for the relevant index.\n const toolCalls: ToolCallAccumulator = new Map()\n const startedAt = Date.now()\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n buffer += decoder.decode(value, { stream: true }).replace(/\\r\\n/g, '\\n')\n for (const event of drainStreamBuffer(false)) yield event\n }\n buffer += decoder.decode().replace(/\\r\\n/g, '\\n')\n for (const event of drainStreamBuffer(true)) yield event\n if (buffer.trim()) {\n for (const event of parseStreamChunk(buffer, context, usage, toolCalls)) yield event\n }\n // Flush any tool calls the model never closed via `finish_reason` — the\n // upstream may have terminated the stream without a terminal chunk (e.g.\n // when the proxy proactively forwards `[DONE]`). Emitting these here is\n // strictly safer than silently dropping a tool call the agent intended.\n for (const event of flushPendingToolCalls(toolCalls, context)) yield event\n // Synthesize a single `llm_call` event from accumulated usage. We only emit\n // when the upstream actually reported tokens — silent zeros would corrupt\n // every cost ledger that observes the stream. Consumers that need to detect\n // missing usage can check `tokensIn === undefined`.\n if (usage.saw) {\n yield {\n type: 'llm_call',\n task: context.task,\n session: context.session,\n model: usage.model ?? requestedModel,\n tokensIn: usage.tokensIn,\n tokensOut: usage.tokensOut,\n // `costUsd` is intentionally absent — pricing tables live in consumers\n // (agent-eval's `estimateCost`, MetricsCollector). Emitting a wrong\n // number here is worse than emitting none.\n latencyMs: Date.now() - startedAt,\n finishReason: usage.finishReason,\n timestamp: nowIso(),\n }\n }\n\n function* drainStreamBuffer(flush: boolean): Iterable<RuntimeStreamEvent> {\n for (;;) {\n const sseBoundary = buffer.indexOf('\\n\\n')\n if (sseBoundary >= 0) {\n const chunk = buffer.slice(0, sseBoundary)\n buffer = buffer.slice(sseBoundary + 2)\n for (const event of parseStreamChunk(chunk, context, usage, toolCalls)) yield event\n continue\n }\n\n const newline = buffer.indexOf('\\n')\n if (newline >= 0 && !buffer.slice(0, newline).startsWith('data:')) {\n const line = buffer.slice(0, newline)\n buffer = buffer.slice(newline + 1)\n for (const event of parseStreamChunk(line, context, usage, toolCalls)) yield event\n continue\n }\n\n if (flush && buffer.trim() && !buffer.trimStart().startsWith('data:')) {\n const line = buffer\n buffer = ''\n for (const event of parseStreamChunk(line, context, usage, toolCalls)) yield event\n continue\n }\n\n break\n }\n }\n}\n\n/**\n * Per-tool-call accumulator. Keyed by either OpenAI `index` (cast to string)\n * or Anthropic `content_block` `index`. Holds the streamed identifier, name,\n * and string-form `arguments` so we can emit a single typed `tool_call`\n * event once the stream signals the call is finalized.\n */\ntype ToolCallAccumulator = Map<\n string,\n {\n id?: string\n name?: string\n /** Accumulated JSON-string `arguments` / `input` payload. */\n argsRaw: string\n /** Source format: OpenAI delta vs Anthropic `tool_use` block. */\n source: 'openai' | 'anthropic'\n /** Set true once the model signals this call is complete. */\n finalized: boolean\n }\n>\n\nfunction* parseStreamChunk(\n chunk: string,\n context: AgentBackendContext,\n usage: StreamUsageAccumulator,\n toolCalls: ToolCallAccumulator,\n): Iterable<RuntimeStreamEvent> {\n const lines = chunk.split(/\\r?\\n/)\n const dataLines = lines.filter((line) => line.startsWith('data:'))\n if (\n dataLines.length === 0 &&\n lines.every((line) => {\n const trimmed = line.trim()\n return trimmed.length === 0 || trimmed.startsWith(':')\n })\n ) {\n return\n }\n const data =\n dataLines.length > 0\n ? dataLines.map((line) => line.slice(5).trimStart()).join('\\n')\n : chunk.trim()\n if (!data || data === '[DONE]') return\n let parsed: Record<string, unknown>\n try {\n parsed = JSON.parse(data) as Record<string, unknown>\n } catch {\n yield {\n type: 'text_delta',\n task: context.task,\n session: context.session,\n text: data,\n timestamp: nowIso(),\n }\n return\n }\n captureStreamUsage(parsed, usage)\n const choices = parsed.choices\n const choice = Array.isArray(choices)\n ? (choices[0] as Record<string, unknown> | undefined)\n : undefined\n const delta = choice?.delta as Record<string, unknown> | undefined\n const message = choice?.message as Record<string, unknown> | undefined\n\n // ── OpenAI streamed `tool_calls` deltas ─────────────────────────────\n const deltaToolCalls = delta?.tool_calls\n if (Array.isArray(deltaToolCalls)) {\n for (const tc of deltaToolCalls) {\n if (!tc || typeof tc !== 'object') continue\n const rec = tc as Record<string, unknown>\n const idx = numberValue(rec.index) ?? 0\n const key = `openai:${idx}`\n const acc = toolCalls.get(key) ?? { argsRaw: '', source: 'openai' as const, finalized: false }\n const id = stringValue(rec.id)\n if (id) acc.id = id\n const fn = rec.function as Record<string, unknown> | undefined\n const name = stringValue(fn?.name)\n if (name) acc.name = name\n const args = stringValue(fn?.arguments)\n if (args) acc.argsRaw += args\n toolCalls.set(key, acc)\n }\n }\n // `message.tool_calls` is the non-streamed shape — the model returned a\n // complete tool call in one chunk. Treat the whole array as terminal.\n const messageToolCalls = message?.tool_calls\n if (Array.isArray(messageToolCalls)) {\n for (const tc of messageToolCalls) {\n if (!tc || typeof tc !== 'object') continue\n const rec = tc as Record<string, unknown>\n const fn = rec.function as Record<string, unknown> | undefined\n const idx = numberValue(rec.index) ?? messageToolCalls.indexOf(tc)\n const key = `openai:${idx}`\n const acc = toolCalls.get(key) ?? { argsRaw: '', source: 'openai' as const, finalized: false }\n const id = stringValue(rec.id)\n if (id) acc.id = id\n const name = stringValue(fn?.name)\n if (name) acc.name = name\n const args = stringValue(fn?.arguments)\n if (args) acc.argsRaw += args\n acc.finalized = true\n toolCalls.set(key, acc)\n }\n }\n\n const finishReason = stringValue(choice?.finish_reason)\n if (finishReason === 'tool_calls') {\n // Model signaled it's done streaming tool calls — flush every OpenAI-\n // sourced pending entry. Subsequent chunks (usage, [DONE]) won't add\n // more.\n for (const [key, acc] of toolCalls) {\n if (acc.source === 'openai' && !acc.finalized) acc.finalized = true\n toolCalls.set(key, acc)\n }\n }\n\n // ── Anthropic shape (proxied through router) ────────────────────────\n const eventType = stringValue(parsed.type)\n if (eventType === 'content_block_start') {\n const block = parsed.content_block as Record<string, unknown> | undefined\n if (block && stringValue(block.type) === 'tool_use') {\n const idx = numberValue(parsed.index) ?? 0\n const key = `anthropic:${idx}`\n toolCalls.set(key, {\n id: stringValue(block.id),\n name: stringValue(block.name),\n argsRaw: '',\n source: 'anthropic',\n finalized: false,\n })\n }\n }\n if (eventType === 'content_block_delta') {\n const d = parsed.delta as Record<string, unknown> | undefined\n const dType = stringValue(d?.type)\n if (dType === 'input_json_delta') {\n const idx = numberValue(parsed.index) ?? 0\n const key = `anthropic:${idx}`\n const acc = toolCalls.get(key)\n if (acc) {\n const partial = stringValue(d?.partial_json) ?? ''\n acc.argsRaw += partial\n toolCalls.set(key, acc)\n }\n } else {\n const text = stringValue(d?.text)\n if (text) {\n yield {\n type: 'text_delta',\n task: context.task,\n session: context.session,\n text,\n timestamp: nowIso(),\n }\n }\n }\n }\n if (eventType === 'content_block_stop') {\n const idx = numberValue(parsed.index) ?? 0\n const key = `anthropic:${idx}`\n const acc = toolCalls.get(key)\n if (acc) {\n acc.finalized = true\n toolCalls.set(key, acc)\n }\n }\n\n // Emit any tool calls that just became finalized. Done eagerly per-chunk so\n // consumers see the call as soon as it's safe — the analyst loop watches\n // `tool_call` events for delegation-pattern detection.\n for (const event of drainFinalizedToolCalls(toolCalls, context)) yield event\n\n // ── Text deltas ──────────────────────────────────────────────────────\n const text =\n stringValue(delta?.content) ?? stringValue(message?.content) ?? stringValue(parsed.text)\n if (text) {\n yield {\n type: 'text_delta',\n task: context.task,\n session: context.session,\n text,\n timestamp: nowIso(),\n }\n return\n }\n const mapped = mapCommonBackendEvent(parsed, context)\n if (mapped) yield mapped\n}\n\nfunction* drainFinalizedToolCalls(\n toolCalls: ToolCallAccumulator,\n context: AgentBackendContext,\n): Iterable<RuntimeStreamEvent> {\n for (const [key, acc] of toolCalls) {\n if (!acc.finalized) continue\n toolCalls.delete(key)\n yield buildToolCallEvent(acc, context)\n }\n}\n\nfunction* flushPendingToolCalls(\n toolCalls: ToolCallAccumulator,\n context: AgentBackendContext,\n): Iterable<RuntimeStreamEvent> {\n for (const [key, acc] of toolCalls) {\n toolCalls.delete(key)\n yield buildToolCallEvent(acc, context)\n }\n}\n\nfunction buildToolCallEvent(\n acc: { id?: string; name?: string; argsRaw: string; source: 'openai' | 'anthropic' },\n context: AgentBackendContext,\n): RuntimeStreamEvent {\n // `argsRaw` is JSON-string by the provider contract (OpenAI streams an\n // escaped JSON string; Anthropic streams `partial_json` chunks). Parse\n // best-effort — surface the raw string if parsing fails so downstream\n // doesn't lose the call entirely.\n let args: unknown = acc.argsRaw\n if (acc.argsRaw.length > 0) {\n try {\n args = JSON.parse(acc.argsRaw)\n } catch {\n args = acc.argsRaw\n }\n } else {\n args = {}\n }\n return {\n type: 'tool_call',\n task: context.task,\n session: context.session,\n toolName: acc.name ?? 'tool',\n toolCallId: acc.id,\n args,\n timestamp: nowIso(),\n }\n}\n\n/**\n * Accumulate token usage from any SSE chunk shape the router may emit.\n *\n * - OpenAI: a final chunk before `[DONE]` with `{ usage: { prompt_tokens,\n * completion_tokens, total_tokens } }` and (often) empty `choices`. The\n * `model` field is on every chunk and the last `choices[0].finish_reason`\n * carries the stop reason.\n * - Anthropic: `message_start` carries `message.model` and\n * `message.usage.input_tokens`. The terminal `message_delta` carries\n * `usage.output_tokens` and `delta.stop_reason`.\n */\nfunction captureStreamUsage(parsed: Record<string, unknown>, usage: StreamUsageAccumulator): void {\n const model = stringValue(parsed.model)\n if (model && !usage.model) usage.model = model\n\n const openAiUsage = parsed.usage as Record<string, unknown> | undefined\n if (openAiUsage && typeof openAiUsage === 'object') {\n const promptTokens = numberValue(openAiUsage.prompt_tokens)\n const completionTokens = numberValue(openAiUsage.completion_tokens)\n const inputTokens = numberValue(openAiUsage.input_tokens)\n const outputTokens = numberValue(openAiUsage.output_tokens)\n if (promptTokens !== undefined) {\n usage.tokensIn = promptTokens\n usage.saw = true\n } else if (inputTokens !== undefined) {\n usage.tokensIn = (usage.tokensIn ?? 0) + inputTokens\n usage.saw = true\n }\n if (completionTokens !== undefined) {\n usage.tokensOut = completionTokens\n usage.saw = true\n } else if (outputTokens !== undefined) {\n usage.tokensOut = (usage.tokensOut ?? 0) + outputTokens\n usage.saw = true\n }\n }\n\n const type = stringValue(parsed.type)\n if (type === 'message_start') {\n const message = parsed.message as Record<string, unknown> | undefined\n const messageModel = stringValue(message?.model)\n if (messageModel && !usage.model) usage.model = messageModel\n const messageUsage = message?.usage as Record<string, unknown> | undefined\n const inputTokens = numberValue(messageUsage?.input_tokens)\n if (inputTokens !== undefined) {\n usage.tokensIn = inputTokens\n usage.saw = true\n }\n const outputTokens = numberValue(messageUsage?.output_tokens)\n if (outputTokens !== undefined) {\n usage.tokensOut = (usage.tokensOut ?? 0) + outputTokens\n usage.saw = true\n }\n }\n if (type === 'message_delta') {\n const delta = parsed.delta as Record<string, unknown> | undefined\n const stopReason = stringValue(delta?.stop_reason)\n if (stopReason) usage.finishReason = stopReason\n }\n\n const choices = parsed.choices\n if (Array.isArray(choices)) {\n const finishReason = stringValue(\n (choices[0] as Record<string, unknown> | undefined)?.finish_reason,\n )\n if (finishReason) usage.finishReason = finishReason\n }\n}\n\nfunction numberValue(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined\n}\n"],"mappings":"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","names":["text"]}
@@ -1464,6 +1464,18 @@ async function readMaterializedWorkspaceFiles(root, expected, options = {}) {
1464
1464
  (file) => Object.freeze({ path: file.path, mode: file.mode, bytes: Uint8Array.from(file.bytes) })
1465
1465
  );
1466
1466
  }
1467
+ function candidateWorkspaceManifest(files) {
1468
+ return {
1469
+ schemaVersion: 2,
1470
+ kind: "agent-candidate-workspace-manifest",
1471
+ files: files.map((file) => ({
1472
+ path: file.path,
1473
+ mode: file.mode,
1474
+ sha256: sha256Bytes(file.bytes),
1475
+ byteLength: file.bytes.byteLength
1476
+ })).sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0)
1477
+ };
1478
+ }
1467
1479
  function assertWorkspaceManifest(observed, expected) {
1468
1480
  if (!Buffer.from(canonicalCandidateBytes(observed)).equals(canonicalCandidateBytes(expected))) {
1469
1481
  throw new Error(
@@ -1493,7 +1505,6 @@ async function scanWorkspace(root, ignoredProtectedRootEntries, limits) {
1493
1505
  if (await realpath(absoluteRoot) !== absoluteRoot) {
1494
1506
  throw new Error("workspace root has a symlinked path component");
1495
1507
  }
1496
- const files = [];
1497
1508
  const capturedFiles = [];
1498
1509
  let totalBytes = 0;
1499
1510
  async function visit(directory) {
@@ -1519,7 +1530,7 @@ async function scanWorkspace(root, ignoredProtectedRootEntries, limits) {
1519
1530
  if (!stats.isFile()) {
1520
1531
  throw new Error(`workspace contains a non-regular entry: ${relPath}`);
1521
1532
  }
1522
- if (limits && files.length >= limits.maxFiles) {
1533
+ if (limits && capturedFiles.length >= limits.maxFiles) {
1523
1534
  throw new Error("workspace exceeds maxFiles");
1524
1535
  }
1525
1536
  const descriptor = await open(
@@ -1535,9 +1546,6 @@ async function scanWorkspace(root, ignoredProtectedRootEntries, limits) {
1535
1546
  throw new Error(`workspace contains a hard-linked file: ${relPath}`);
1536
1547
  }
1537
1548
  const mode = openedStats.mode & 511;
1538
- if (mode !== 420 && mode !== 493) {
1539
- throw new Error(`workspace file has unsupported mode ${mode.toString(8)}: ${relPath}`);
1540
- }
1541
1549
  if (limits && openedStats.size > limits.maxFileBytes) {
1542
1550
  throw new Error(`workspace file exceeds maxFileBytes: ${relPath}`);
1543
1551
  }
@@ -1551,28 +1559,15 @@ async function scanWorkspace(root, ignoredProtectedRootEntries, limits) {
1551
1559
  relPath
1552
1560
  );
1553
1561
  totalBytes += bytes.byteLength;
1554
- const supportedMode = mode;
1555
- files.push({
1556
- path: relPath,
1557
- mode: supportedMode,
1558
- sha256: sha256Bytes(bytes),
1559
- byteLength: bytes.byteLength
1560
- });
1561
- capturedFiles.push({ path: relPath, mode: supportedMode, bytes: Uint8Array.from(bytes) });
1562
+ capturedFiles.push({ path: relPath, mode, bytes: Uint8Array.from(bytes) });
1562
1563
  } finally {
1563
1564
  await descriptor.close();
1564
1565
  }
1565
1566
  }
1566
1567
  }
1567
1568
  await visit(absoluteRoot);
1568
- files.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
1569
- capturedFiles.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
1570
1569
  return {
1571
- manifest: {
1572
- schemaVersion: 1,
1573
- kind: "agent-candidate-workspace-manifest",
1574
- files
1575
- },
1570
+ manifest: candidateWorkspaceManifest(capturedFiles),
1576
1571
  files: capturedFiles
1577
1572
  };
1578
1573
  }
@@ -1797,19 +1792,9 @@ async function assertSafeTree(repositoryRoot, tree, environment = {}) {
1797
1792
  }
1798
1793
  }
1799
1794
  async function workspaceManifestFromGitTree(repositoryRoot, tree, environment) {
1800
- const files = (await readCandidateGitTreeFiles(repositoryRoot, tree, environment)).map(
1801
- ({ path, mode, bytes }) => ({
1802
- path,
1803
- mode,
1804
- sha256: sha256Bytes(bytes),
1805
- byteLength: bytes.byteLength
1806
- })
1795
+ return candidateWorkspaceManifest(
1796
+ await readCandidateGitTreeFiles(repositoryRoot, tree, environment)
1807
1797
  );
1808
- return {
1809
- schemaVersion: 1,
1810
- kind: "agent-candidate-workspace-manifest",
1811
- files
1812
- };
1813
1798
  }
1814
1799
  async function readCandidateGitTreeFiles(repositoryRoot, tree, environment = {}, limits) {
1815
1800
  const listing = (await runCandidateGit(
@@ -1951,6 +1936,14 @@ function isNoEntry(error) {
1951
1936
  return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
1952
1937
  }
1953
1938
 
1939
+ // src/candidate-execution/workspace-task.ts
1940
+ function workspaceTaskRepository(task) {
1941
+ if (task.outcome.kind !== "workspace" || !task.repository) {
1942
+ throw new Error("candidate runtime requires a workspace outcome with repository provenance");
1943
+ }
1944
+ return task.repository;
1945
+ }
1946
+
1954
1947
  // src/candidate-execution/prepared-state.ts
1955
1948
  var stateByExecution = /* @__PURE__ */ new WeakMap();
1956
1949
  var lifecycleByExecution = /* @__PURE__ */ new WeakMap();
@@ -2058,7 +2051,7 @@ async function assertPreparedCandidateWorkspaces(state) {
2058
2051
  await verifyMaterializedWorkspace(state.roots.staging.taskRoot, plan.task.workspace.material, {
2059
2052
  ignoredProtectedRootEntries: [".git", ".sidecar"]
2060
2053
  });
2061
- await verifyTaskCheckout(state.roots.staging.taskRoot, plan.task.repository);
2054
+ await verifyTaskCheckout(state.roots.staging.taskRoot, workspaceTaskRepository(plan.task));
2062
2055
  await verifyMaterializedProfileWorkspace(
2063
2056
  state.roots.staging.profileRoot,
2064
2057
  state.profilePlan.value.material
@@ -2125,9 +2118,10 @@ function detachPreparedCandidateState(input) {
2125
2118
  ...input.memoryReservation ? { memoryReservation: immutableCandidateValue(input.memoryReservation) } : {},
2126
2119
  ...input.knowledge ? {
2127
2120
  knowledge: Object.freeze({
2128
- snapshotId: input.knowledge.snapshotId,
2129
- manifestDigest: input.knowledge.manifestDigest,
2130
- manifest: Uint8Array.from(input.knowledge.manifest)
2121
+ candidate: immutableCandidateValue(input.knowledge.candidate),
2122
+ snapshot: immutableCandidateValue(input.knowledge.snapshot),
2123
+ files: immutableExecutorFiles(input.knowledge.files),
2124
+ ...input.knowledge.retrievalConfig ? { retrievalConfig: Uint8Array.from(input.knowledge.retrievalConfig) } : {}
2131
2125
  })
2132
2126
  } : {},
2133
2127
  trace: immutableCandidateValue(input.trace),
@@ -2157,6 +2151,7 @@ function assertPrivateCandidateIntegrity(state) {
2157
2151
  throw new Error("prepared model access no longer matches the signed execution plan");
2158
2152
  }
2159
2153
  assertExecutorInputs(state);
2154
+ assertPreparedKnowledge(state);
2160
2155
  if (state.memory.mode === "isolated" && !state.memoryReservation || state.memory.mode === "disabled" && state.memoryReservation) {
2161
2156
  throw new Error("prepared memory reservation does not match the signed execution plan");
2162
2157
  }
@@ -2210,13 +2205,16 @@ function bytesView(value, key) {
2210
2205
  });
2211
2206
  }
2212
2207
  function knowledgeView(knowledge) {
2213
- const manifest = Uint8Array.from(knowledge.manifest);
2208
+ const retrievalConfig = knowledge.retrievalConfig ? Uint8Array.from(knowledge.retrievalConfig) : void 0;
2214
2209
  return Object.freeze({
2215
- snapshotId: knowledge.snapshotId,
2216
- manifestDigest: knowledge.manifestDigest,
2217
- get manifest() {
2218
- return Uint8Array.from(manifest);
2219
- }
2210
+ candidate: knowledge.candidate,
2211
+ snapshot: knowledge.snapshot,
2212
+ files: Object.freeze(knowledge.files.map((file) => profileFileView(file))),
2213
+ ...retrievalConfig ? {
2214
+ get retrievalConfig() {
2215
+ return Uint8Array.from(retrievalConfig);
2216
+ }
2217
+ } : {}
2220
2218
  });
2221
2219
  }
2222
2220
  function workspaceInputView(snapshot, sourceFiles) {
@@ -2261,6 +2259,28 @@ function assertExecutorInputs(state) {
2261
2259
  }
2262
2260
  }
2263
2261
  }
2262
+ function assertPreparedKnowledge(state) {
2263
+ const expected = state.bundle.knowledge;
2264
+ const actual = state.knowledge;
2265
+ if (!expected || !actual) {
2266
+ if (expected || actual)
2267
+ throw new Error("prepared knowledge does not match the candidate bundle");
2268
+ return;
2269
+ }
2270
+ if (canonicalCandidateDigest(actual.candidate) !== canonicalCandidateDigest(expected.candidate) || canonicalCandidateDigest(actual.snapshot) !== canonicalCandidateDigest(expected.snapshot) || state.executionPlan.value.material.knowledgeManifestDigest !== expected.snapshot.digest) {
2271
+ throw new Error("prepared knowledge identity does not match the candidate bundle");
2272
+ }
2273
+ assertWorkspaceExecutorFiles(actual.files, expected.snapshot.material);
2274
+ if (!expected.retrievalConfig || !actual.retrievalConfig) {
2275
+ if (expected.retrievalConfig || actual.retrievalConfig) {
2276
+ throw new Error("prepared knowledge retrieval config does not match the candidate bundle");
2277
+ }
2278
+ return;
2279
+ }
2280
+ if (actual.retrievalConfig.byteLength !== expected.retrievalConfig.byteLength || sha256Bytes(actual.retrievalConfig) !== expected.retrievalConfig.sha256) {
2281
+ throw new Error("prepared knowledge retrieval config does not match the candidate bundle");
2282
+ }
2283
+ }
2264
2284
  function assertWorkspaceExecutorFiles(actualFiles, expected) {
2265
2285
  if (actualFiles.length !== expected.files.length) {
2266
2286
  throw new Error("prepared workspace executor files do not match the signed manifest");
@@ -2452,6 +2472,18 @@ function sealAgentCandidateExecutorFinalCapture(value) {
2452
2472
  ...memoryAfter ? { memoryAfter: Object.freeze(memoryAfter) } : {}
2453
2473
  });
2454
2474
  }
2475
+ function encodeAgentCandidateExecutorCapture(input) {
2476
+ return canonicalCandidateBytes({
2477
+ schemaVersion: 1,
2478
+ kind: "agent-candidate-executor-capture",
2479
+ executionId: input.executionId,
2480
+ executionPlanDigest: input.executionPlanDigest,
2481
+ termination: input.termination,
2482
+ stopped: true,
2483
+ taskOutcome: input.taskOutcome,
2484
+ ...input.memoryAfter ? { memoryAfter: input.memoryAfter } : {}
2485
+ });
2486
+ }
2455
2487
  function sealMemoryCapture(value) {
2456
2488
  const capture = requireRecord(value, "candidate memory capture");
2457
2489
  assertExactObjectKeys(capture, ["afterState", "archive"], "candidate memory capture");
@@ -2498,7 +2530,7 @@ import { mkdtemp as mkdtemp2, rm as rm2 } from "fs/promises";
2498
2530
  import { tmpdir as tmpdir2 } from "os";
2499
2531
  import { join as join2 } from "path";
2500
2532
  import { isLlmSpan as isLlmSpan2, REDACTION_VERSION as REDACTION_VERSION2 } from "@tangle-network/agent-eval";
2501
- import { agentCandidateRunReceiptV2Schema } from "@tangle-network/agent-interface";
2533
+ import { agentCandidateRunReceiptSchema } from "@tangle-network/agent-interface";
2502
2534
 
2503
2535
  // src/candidate-execution/model-settlement.ts
2504
2536
  import { isLlmSpan } from "@tangle-network/agent-eval";
@@ -2883,7 +2915,7 @@ function provisionalCandidateWorkspaceSnapshot(materialInput, archive) {
2883
2915
  );
2884
2916
  const manifestBytes = canonicalCandidateBytes(material);
2885
2917
  const snapshot = Object.freeze({
2886
- schemaVersion: 1,
2918
+ schemaVersion: 2,
2887
2919
  kind: "agent-candidate-workspace-snapshot",
2888
2920
  digest: sha256Bytes(manifestBytes),
2889
2921
  material,
@@ -2912,7 +2944,7 @@ async function persistCandidateWorkspaceSnapshot(port, input) {
2912
2944
  ]);
2913
2945
  return immutableCandidateValue(
2914
2946
  agentCandidateWorkspaceSnapshotEvidenceSchema.parse({
2915
- schemaVersion: 1,
2947
+ schemaVersion: 2,
2916
2948
  kind: "agent-candidate-workspace-snapshot",
2917
2949
  digest: sha256Bytes(manifestBytes),
2918
2950
  material,
@@ -2961,7 +2993,6 @@ async function finalizeAgentCandidateRun(state, capture, traceStore, settlement,
2961
2993
  );
2962
2994
  const modelSpans = orderedSpans.filter(isLlmSpan2);
2963
2995
  assertTraceMatchesModelSettlement(modelSpans, settlement);
2964
- const usage = settlement.usage;
2965
2996
  enforceLimits(state, run.startedAt, run.endedAt, orderedSpans, settlement);
2966
2997
  const finalCapture = sealAgentCandidateExecutorFinalCapture(evidence.finalCapture);
2967
2998
  const memory = await memoryReceipt(
@@ -2971,6 +3002,20 @@ async function finalizeAgentCandidateRun(state, capture, traceStore, settlement,
2971
3002
  protectedValues,
2972
3003
  signal
2973
3004
  );
3005
+ const executorCaptureBytes = encodeAgentCandidateExecutorCapture({
3006
+ executionId: protectedCapture.executionId,
3007
+ executionPlanDigest: state.executionPlan.value.digest,
3008
+ termination: protectedCapture.termination,
3009
+ taskOutcome: evidence.taskOutcome.evidence,
3010
+ ...memory.mode === "isolated" ? { memoryAfter: memory.afterState } : {}
3011
+ });
3012
+ assertNoProtectedBytes(executorCaptureBytes, protectedValues);
3013
+ const executorCapture = await persistCandidateOutputArtifact(evidence.outputArtifacts, {
3014
+ executionId: state.executionId,
3015
+ purpose: "executor-capture",
3016
+ bytes: executorCaptureBytes,
3017
+ signal
3018
+ });
2974
3019
  const redacted = redactProtectedValue(
2975
3020
  {
2976
3021
  schemaVersion: 1,
@@ -3010,23 +3055,21 @@ async function finalizeAgentCandidateRun(state, capture, traceStore, settlement,
3010
3055
  modelCallCount: modelSpans.length
3011
3056
  };
3012
3057
  const document = canonicalCandidateDocument({
3013
- schemaVersion: 2,
3058
+ schemaVersion: 3,
3014
3059
  kind: "agent-candidate-run",
3015
3060
  digestAlgorithm: "rfc8785-sha256",
3016
3061
  bundleDigest: state.bundle.digest,
3017
3062
  materializationReceiptDigest: state.materializationReceipt.digest,
3018
3063
  executionPlanDigest: state.executionPlan.value.digest,
3019
3064
  memory,
3020
- usage,
3021
- modelUsage: { resolved: state.resolvedModel, usage },
3022
3065
  trace,
3023
3066
  termination,
3024
- fixedUsage: settlement.fixedUsage,
3067
+ executorCapture,
3025
3068
  modelSettlement: evidence.modelSettlement,
3026
3069
  taskOutcome: evidence.taskOutcome.evidence,
3027
3070
  benchmarkResult: evidence.benchmarkResult
3028
3071
  });
3029
- agentCandidateRunReceiptV2Schema.parse(document.value);
3072
+ agentCandidateRunReceiptSchema.parse(document.value);
3030
3073
  const runReceipt = await persistCandidateOutputArtifact(evidence.outputArtifacts, {
3031
3074
  executionId: state.executionId,
3032
3075
  purpose: "run-receipt",
@@ -3037,6 +3080,7 @@ async function finalizeAgentCandidateRun(state, capture, traceStore, settlement,
3037
3080
  succeeded: true,
3038
3081
  receipt: document,
3039
3082
  artifacts: {
3083
+ executorCapture,
3040
3084
  modelSettlement: evidence.modelSettlement.artifact,
3041
3085
  taskOutcome: evidence.taskOutcome.evidence.artifact,
3042
3086
  benchmarkResult: evidence.benchmarkResult.artifact,
@@ -3288,7 +3332,7 @@ async function persistCandidateModelSettlementEvidence(identity, settlement, out
3288
3332
  });
3289
3333
  return immutableCandidateValue(
3290
3334
  agentCandidateModelSettlementEvidenceSchema.parse({
3291
- schemaVersion: 1,
3335
+ schemaVersion: 2,
3292
3336
  kind: "agent-candidate-model-settlement",
3293
3337
  digest,
3294
3338
  material,
@@ -3305,7 +3349,7 @@ async function persistVerifiedCandidateTaskOutcome(state, capture, outputArtifac
3305
3349
  assertNoProtectedBytes(archive, protectedValues);
3306
3350
  const provisional = provisionalCandidateWorkspaceSnapshot(capture.afterState, archive);
3307
3351
  const afterState = provisional.material;
3308
- const repository = state.executionPlan.value.material.task.repository;
3352
+ const repository = workspaceTaskRepository(state.executionPlan.value.material.task);
3309
3353
  const verified = await verifyTaskOutcomePatch({
3310
3354
  repositoryRoot: state.roots.staging.taskRoot,
3311
3355
  baseCommit: repository.baseCommit,
@@ -3332,25 +3376,28 @@ async function persistVerifiedCandidateTaskOutcome(state, capture, outputArtifac
3332
3376
  signal
3333
3377
  });
3334
3378
  const material = {
3335
- schemaVersion: 1,
3379
+ schemaVersion: 2,
3336
3380
  kind: "agent-candidate-task-outcome-material",
3337
3381
  executionPlanDigest: state.executionPlan.value.digest,
3338
- baseRepository: {
3339
- identity: repository.identity,
3340
- rootIdentity: repository.rootIdentity,
3341
- commit: repository.baseCommit,
3342
- tree: repository.baseTree
3343
- },
3344
- resultRepository: {
3345
- identity: repository.identity,
3346
- rootIdentity: repository.rootIdentity,
3347
- commit: verified.resultCommit,
3348
- tree: verified.resultTree
3349
- },
3350
- afterState: snapshot,
3351
- gitDiff: {
3352
- format: "git-diff-binary",
3353
- artifact: gitDiff
3382
+ outcome: {
3383
+ kind: "workspace",
3384
+ baseRepository: {
3385
+ identity: repository.identity,
3386
+ rootIdentity: repository.rootIdentity,
3387
+ commit: repository.baseCommit,
3388
+ tree: repository.baseTree
3389
+ },
3390
+ resultRepository: {
3391
+ identity: repository.identity,
3392
+ rootIdentity: repository.rootIdentity,
3393
+ commit: verified.resultCommit,
3394
+ tree: verified.resultTree
3395
+ },
3396
+ afterState: snapshot,
3397
+ gitDiff: {
3398
+ format: "git-diff-binary",
3399
+ artifact: gitDiff
3400
+ }
3354
3401
  }
3355
3402
  };
3356
3403
  const bytes = canonicalCandidateBytes(material);
@@ -3363,7 +3410,7 @@ async function persistVerifiedCandidateTaskOutcome(state, capture, outputArtifac
3363
3410
  });
3364
3411
  const evidence = immutableCandidateValue(
3365
3412
  agentCandidateTaskOutcomeEvidenceSchema.parse({
3366
- schemaVersion: 1,
3413
+ schemaVersion: 2,
3367
3414
  kind: "agent-candidate-task-outcome",
3368
3415
  digest,
3369
3416
  material,
@@ -4345,7 +4392,16 @@ async function verifyAgentCandidateBundle(input, ports) {
4345
4392
  artifactBytes.set(artifactCacheKey(parsed.execution.workspace.manifest), workspace.manifest);
4346
4393
  artifactBytes.set(artifactCacheKey(parsed.execution.workspace.archive), workspace.archive);
4347
4394
  }
4348
- if (parsed.knowledge) await readArtifact(parsed.knowledge.manifest);
4395
+ if (parsed.knowledge) {
4396
+ const knowledge = await verifyWorkspaceSnapshotArtifacts(
4397
+ parsed.knowledge.snapshot,
4398
+ ports.artifacts
4399
+ );
4400
+ artifactBytes.set(artifactCacheKey(parsed.knowledge.snapshot.manifest), knowledge.manifest);
4401
+ artifactBytes.set(artifactCacheKey(parsed.knowledge.snapshot.archive), knowledge.archive);
4402
+ if (parsed.knowledge.retrievalConfig) await readArtifact(parsed.knowledge.retrievalConfig);
4403
+ await readArtifact(parsed.knowledge.evaluation);
4404
+ }
4349
4405
  if (parsed.memory.mode === "isolated" && parsed.memory.seed)
4350
4406
  await readArtifact(parsed.memory.seed);
4351
4407
  deepFreezeCandidate(parsed);
@@ -4416,6 +4472,41 @@ import {
4416
4472
  applyAgentCandidateWorkspacePlan,
4417
4473
  materializeCandidateProfile
4418
4474
  } from "@tangle-network/agent-profile-materialize";
4475
+
4476
+ // src/candidate-execution/knowledge.ts
4477
+ import { mkdtemp as mkdtemp4, rm as rm4 } from "fs/promises";
4478
+ import { tmpdir as tmpdir4 } from "os";
4479
+ import { join as join4 } from "path";
4480
+ async function prepareAgentCandidateKnowledge(candidate, ports) {
4481
+ const knowledge = candidate.bundle.knowledge;
4482
+ if (!knowledge) return void 0;
4483
+ const archive = await verifiedArtifactBytes(candidate, knowledge.snapshot.archive);
4484
+ const retrievalConfig = knowledge.retrievalConfig ? await verifiedArtifactBytes(candidate, knowledge.retrievalConfig) : void 0;
4485
+ const root = await mkdtemp4(join4(tmpdir4(), "agent-candidate-knowledge-"));
4486
+ try {
4487
+ await ports.workspaces.materialize({
4488
+ role: "knowledge",
4489
+ snapshot: knowledge.snapshot,
4490
+ archive,
4491
+ destination: root
4492
+ });
4493
+ const files = await readMaterializedWorkspaceFiles(root, knowledge.snapshot.material);
4494
+ return Object.freeze({
4495
+ candidate: knowledge.candidate,
4496
+ snapshot: knowledge.snapshot,
4497
+ files: Object.freeze(
4498
+ files.map(
4499
+ (file) => Object.freeze({ path: file.path, mode: file.mode, bytes: Uint8Array.from(file.bytes) })
4500
+ )
4501
+ ),
4502
+ ...retrievalConfig ? { retrievalConfig: Uint8Array.from(retrievalConfig) } : {}
4503
+ });
4504
+ } finally {
4505
+ await rm4(root, { recursive: true, force: true });
4506
+ }
4507
+ }
4508
+
4509
+ // src/candidate-execution/prepare.ts
4419
4510
  var MATERIALIZER_HARNESSES = /* @__PURE__ */ new Set([
4420
4511
  "claude-code",
4421
4512
  "claude",
@@ -4549,11 +4640,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4549
4640
  cleanupTimeoutMs
4550
4641
  );
4551
4642
  const memory = preparedMemory.value;
4552
- const knowledge = bundle.knowledge ? {
4553
- snapshotId: bundle.knowledge.snapshotId,
4554
- manifestDigest: bundle.knowledge.manifest.sha256,
4555
- manifest: await verifiedArtifactBytes(candidate, bundle.knowledge.manifest)
4556
- } : void 0;
4643
+ const knowledge = await prepareAgentCandidateKnowledge(candidate, ports);
4557
4644
  const baseLaunch = buildLaunch(candidate, task, profileApplication.flags);
4558
4645
  const publicEnv = mergePublicEnvironment(
4559
4646
  bundle.execution.env ?? {},
@@ -4567,7 +4654,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4567
4654
  );
4568
4655
  const routes = modelRoutes(bundle.profile, task.model.requested);
4569
4656
  const executionMaterial = {
4570
- schemaVersion: 1,
4657
+ schemaVersion: 2,
4571
4658
  kind: "agent-candidate-execution-plan-material",
4572
4659
  bundleDigest: bundle.digest,
4573
4660
  executionId: task.executionId,
@@ -4584,6 +4671,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4584
4671
  delivery: bundle.execution.instructionDelivery
4585
4672
  },
4586
4673
  repository: task.repository,
4674
+ outcome: { kind: "workspace" },
4587
4675
  workspace: task.workspace
4588
4676
  },
4589
4677
  workspaces: {
@@ -4613,7 +4701,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4613
4701
  env: publicEnv,
4614
4702
  cwd: bundle.execution.cwd
4615
4703
  },
4616
- ...bundle.knowledge ? { knowledgeManifestDigest: bundle.knowledge.manifest.sha256 } : {},
4704
+ ...bundle.knowledge ? { knowledgeManifestDigest: bundle.knowledge.snapshot.digest } : {},
4617
4705
  memory,
4618
4706
  limits: task.limits,
4619
4707
  network: { mode: "disabled" }
@@ -4625,7 +4713,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4625
4713
  throw new Error("execution plan canonical serializers disagree");
4626
4714
  }
4627
4715
  const executionPlan = agentCandidateExecutionPlanEvidenceSchema2.parse({
4628
- schemaVersion: 1,
4716
+ schemaVersion: 2,
4629
4717
  kind: "agent-candidate-execution-plan",
4630
4718
  digest: executionDigest,
4631
4719
  material: executionMaterial,
@@ -4634,7 +4722,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4634
4722
  const entrypoint = candidateEntrypointReceipt(candidate);
4635
4723
  const materializationReceipt = canonicalCandidateDocument(
4636
4724
  {
4637
- schemaVersion: 1,
4725
+ schemaVersion: 2,
4638
4726
  kind: "agent-candidate-materialization",
4639
4727
  digestAlgorithm: "rfc8785-sha256",
4640
4728
  bundleDigest: bundle.digest,
@@ -4647,7 +4735,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
4647
4735
  harnessVersion: bundle.execution.harnessVersion,
4648
4736
  container,
4649
4737
  resolvedModel,
4650
- ...bundle.knowledge ? { knowledgeManifestDigest: bundle.knowledge.manifest.sha256 } : {},
4738
+ ...bundle.knowledge ? { knowledgeManifestDigest: bundle.knowledge.snapshot.digest } : {},
4651
4739
  ...entrypoint ? { entrypoint } : {}
4652
4740
  }
4653
4741
  );
@@ -5119,7 +5207,7 @@ function exactProfileExecutorFiles(sourceFiles, expectedFiles) {
5119
5207
  const source = byPath.get(expected.relPath);
5120
5208
  const mode = source?.mode ?? 420;
5121
5209
  const bytes = Buffer.from(source?.content ?? "", "utf8");
5122
- if (!source || mode !== 420 && mode !== 493 || mode !== expected.mode || sha256Bytes(bytes) !== expected.contentSha256) {
5210
+ if (!source || !Number.isInteger(mode) || mode < 0 || mode > 511 || mode !== expected.mode || sha256Bytes(bytes) !== expected.contentSha256) {
5123
5211
  throw new Error("profile source files do not match the signed profile plan");
5124
5212
  }
5125
5213
  return { path: expected.relPath, mode, bytes: Uint8Array.from(bytes) };
@@ -5179,6 +5267,7 @@ export {
5179
5267
  verifyBytes,
5180
5268
  verifyMaterializedWorkspace,
5181
5269
  captureMaterializedWorkspace,
5270
+ candidateWorkspaceManifest,
5182
5271
  assertNoGitIndirection,
5183
5272
  readCandidateGitTreeFiles,
5184
5273
  runCandidateGit,
@@ -5200,4 +5289,4 @@ export {
5200
5289
  verifyAgentCandidateBundle,
5201
5290
  prepareAgentCandidateExecution
5202
5291
  };
5203
- //# sourceMappingURL=chunk-37V4KQDC.js.map
5292
+ //# sourceMappingURL=chunk-CNH7DF7Z.js.map