@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.
- package/README.md +65 -1
- package/dist/agent.d.ts +2 -1
- package/dist/agent.js +2 -1
- package/dist/agent.js.map +1 -1
- package/dist/{agentic-generator-JT47GnAp.d.ts → agentic-generator-DDMM45kZ.d.ts} +2 -2
- package/dist/analyst-loop.d.ts +2 -1
- package/dist/backends-BO4Jqoe2.d.ts +134 -0
- package/dist/candidate-execution/index.d.ts +2 -2
- package/dist/candidate-execution/index.js +2 -2
- package/dist/chunk-AEG3NGJ2.js +639 -0
- package/dist/chunk-AEG3NGJ2.js.map +1 -0
- package/dist/{chunk-37V4KQDC.js → chunk-CNH7DF7Z.js} +173 -84
- package/dist/chunk-CNH7DF7Z.js.map +1 -0
- package/dist/{chunk-OLZ6ZZQ2.js → chunk-D3H7F6L2.js} +11 -8
- package/dist/chunk-D3H7F6L2.js.map +1 -0
- package/dist/{chunk-5LIOH5DR.js → chunk-PCURO3DL.js} +4 -4
- package/dist/chunk-PCURO3DL.js.map +1 -0
- package/dist/{chunk-FTXM7Q7P.js → chunk-TVJQAYQM.js} +13 -21
- package/dist/chunk-TVJQAYQM.js.map +1 -0
- package/dist/{chunk-YP6B7RZ2.js → chunk-U33YZ7B2.js} +6 -635
- package/dist/chunk-U33YZ7B2.js.map +1 -0
- package/dist/chunk-VYA2YEKA.js +1187 -0
- package/dist/chunk-VYA2YEKA.js.map +1 -0
- package/dist/{chunk-MXBQNVFE.js → chunk-XP5KDM3R.js} +5 -5
- package/dist/{completion-gate-Bn4AZ_Kw.d.ts → completion-gate-D1gX1-hg.d.ts} +1 -1
- package/dist/conversation.d.ts +793 -0
- package/dist/conversation.js +56 -0
- package/dist/conversation.js.map +1 -0
- package/dist/{coordination-DzwagV_s.d.ts → coordination-Dr_axlAf.d.ts} +5 -4
- package/dist/environment-provider.d.ts +3 -2
- package/dist/{improve-BucbjddC.d.ts → improve-BN3HyXIO.d.ts} +1 -1
- package/dist/index.d.ts +29 -943
- package/dist/index.js +60 -1161
- package/dist/index.js.map +1 -1
- package/dist/intelligence.d.ts +6 -5
- package/dist/intelligence.js +6 -6
- package/dist/knowledge.d.ts +7 -6
- package/dist/lifecycle.d.ts +2 -2
- package/dist/lifecycle.js +1 -1
- package/dist/{loop-runner-bin-D6K_C6op.d.ts → loop-runner-bin-BRQSQdHa.d.ts} +2 -2
- package/dist/loop-runner-bin.d.ts +6 -5
- package/dist/loop-runner-bin.js +4 -3
- package/dist/loops.d.ts +15 -14
- package/dist/loops.js +2 -1
- package/dist/mcp/index.d.ts +9 -8
- package/dist/mcp/index.js +2 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/{mcp-serve-verifier-i6nTNSnu.d.ts → mcp-serve-verifier-DQQDbuyz.d.ts} +1 -1
- package/dist/{openai-tools-0wACz8f8.d.ts → openai-tools-fnj6SRVg.d.ts} +1 -1
- package/dist/{prepare-DIeVgQG3.d.ts → prepare-CtdtsFNG.d.ts} +18 -14
- package/dist/primeintellect/index.d.ts +214 -0
- package/dist/primeintellect/index.js +1120 -0
- package/dist/primeintellect/index.js.map +1 -0
- package/dist/profiles.d.ts +2 -1
- package/dist/{sanitize-Dcbjp0tU.d.ts → sanitize-BTSsdBXw.d.ts} +1 -1
- package/dist/{supervise-CzyytS-o.d.ts → supervise-DmYOug5f.d.ts} +4 -4
- package/dist/{types-CogNCaw7.d.ts → types-1d5QGK3t.d.ts} +1 -1
- package/dist/types-BwoZWq-i.d.ts +510 -0
- package/dist/{types-CKmyZ9TP.d.ts → types-ByAYqlVb.d.ts} +3 -509
- package/dist/{worktree-fanout-Bn7w_1bM.d.ts → worktree-fanout-CPprU-qI.d.ts} +3 -3
- package/package.json +17 -5
- package/dist/chunk-37V4KQDC.js.map +0 -1
- package/dist/chunk-5LIOH5DR.js.map +0 -1
- package/dist/chunk-FTXM7Q7P.js.map +0 -1
- package/dist/chunk-OLZ6ZZQ2.js.map +0 -1
- package/dist/chunk-YP6B7RZ2.js.map +0 -1
- /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 &&
|
|
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
|
-
|
|
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
|
-
|
|
1801
|
-
(
|
|
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
|
|
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
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
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
|
|
2208
|
+
const retrievalConfig = knowledge.retrievalConfig ? Uint8Array.from(knowledge.retrievalConfig) : void 0;
|
|
2214
2209
|
return Object.freeze({
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
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 {
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
|
|
3067
|
+
executorCapture,
|
|
3025
3068
|
modelSettlement: evidence.modelSettlement,
|
|
3026
3069
|
taskOutcome: evidence.taskOutcome.evidence,
|
|
3027
3070
|
benchmarkResult: evidence.benchmarkResult
|
|
3028
3071
|
});
|
|
3029
|
-
|
|
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:
|
|
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
|
|
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:
|
|
3379
|
+
schemaVersion: 2,
|
|
3336
3380
|
kind: "agent-candidate-task-outcome-material",
|
|
3337
3381
|
executionPlanDigest: state.executionPlan.value.digest,
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
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:
|
|
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)
|
|
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 =
|
|
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:
|
|
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.
|
|
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:
|
|
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:
|
|
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.
|
|
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
|
|
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-
|
|
5292
|
+
//# sourceMappingURL=chunk-CNH7DF7Z.js.map
|