@tangle-network/agent-eval 0.143.0 → 0.144.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/README.md +21 -8
- package/dist/analyst/index.d.ts +82 -17
- package/dist/analyst/index.d.ts.map +1 -1
- package/dist/analyst/index.js +4 -4
- package/dist/{benchmark-command-CSddvlq7.js → benchmark-command-95Zqd1e8.js} +333 -111
- package/dist/benchmark-command-95Zqd1e8.js.map +1 -0
- package/dist/benchmarks/index.d.ts +1 -1
- package/dist/benchmarks/index.js +1 -1
- package/dist/{benchmarks-Dg0B56tK.js → benchmarks-CRT4ScEA.js} +4 -4
- package/dist/{benchmarks-Dg0B56tK.js.map → benchmarks-CRT4ScEA.js.map} +1 -1
- package/dist/campaign/index.d.ts +4 -3
- package/dist/campaign/index.js +4 -4
- package/dist/{campaign-C7ZGiZYG.js → campaign-CefP3fPS.js} +12 -10
- package/dist/campaign-CefP3fPS.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/contract/index.d.ts +1 -1
- package/dist/contract/index.js +3 -3
- package/dist/{default-registry-BupFSXSN.js → default-registry-SOyHB6qG.js} +3 -3
- package/dist/{default-registry-BupFSXSN.js.map → default-registry-SOyHB6qG.js.map} +1 -1
- package/dist/{dspy-rlm-engine-CJ4sN8Wx.js → dspy-rlm-engine-BR7TtB0o.js} +69 -31
- package/dist/dspy-rlm-engine-BR7TtB0o.js.map +1 -0
- package/dist/{eval-campaign-YdkpWWoT.js → eval-campaign-lI7wB9DH.js} +2 -2
- package/dist/{eval-campaign-YdkpWWoT.js.map → eval-campaign-lI7wB9DH.js.map} +1 -1
- package/dist/external-optimizer-contracts-CdmX2K2S.d.ts +165 -0
- package/dist/external-optimizer-contracts-CdmX2K2S.d.ts.map +1 -0
- package/dist/{index-BKjcUH13.d.ts → index-BZUe-ODI.d.ts} +41 -5
- package/dist/index-BZUe-ODI.d.ts.map +1 -0
- package/dist/{index-DY83M1WL.d.ts → index-BrpxwELi.d.ts} +9 -8
- package/dist/{index-DY83M1WL.d.ts.map → index-BrpxwELi.d.ts.map} +1 -1
- package/dist/{index-CaOjqCli.d.ts → index-DRI1DU5z.d.ts} +3 -3
- package/dist/{index-CaOjqCli.d.ts.map → index-DRI1DU5z.d.ts.map} +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +12 -11
- package/dist/index.js.map +1 -1
- package/dist/{integrity-hruKe6oe.js → integrity-DY6tIbl0.js} +48 -18
- package/dist/integrity-DY6tIbl0.js.map +1 -0
- package/dist/{llm-client-B3WXSH5Y.js → llm-client-D3EoChAU.js} +7 -7
- package/dist/llm-client-D3EoChAU.js.map +1 -0
- package/dist/openapi.json +1 -1
- package/dist/rl.js +1 -1
- package/dist/{semantic-concept-judge-DJQtFr95.js → semantic-concept-judge-l8Lb3Kqz.js} +2 -2
- package/dist/{semantic-concept-judge-DJQtFr95.js.map → semantic-concept-judge-l8Lb3Kqz.js.map} +1 -1
- package/dist/{server-Cu4M3NSO.js → server-Df00sdwz.js} +3 -3
- package/dist/{server-Cu4M3NSO.js.map → server-Df00sdwz.js.map} +1 -1
- package/dist/single-run-lock-B-cFnnNn.js +1799 -0
- package/dist/single-run-lock-B-cFnnNn.js.map +1 -0
- package/dist/{skill-usage-CRqaHi0R.d.ts → skill-usage-3vUWdZ9n.d.ts} +24 -5
- package/dist/skill-usage-3vUWdZ9n.d.ts.map +1 -0
- package/dist/{skillopt-optimization-method-Di8Xkalt.js → skillopt-optimization-method-DA5mJmFE.js} +225 -347
- package/dist/skillopt-optimization-method-DA5mJmFE.js.map +1 -0
- package/dist/{skillopt-optimization-method-CwRvi-rL.d.ts → skillopt-optimization-method-DNniakI5.d.ts} +47 -9
- package/dist/skillopt-optimization-method-DNniakI5.d.ts.map +1 -0
- package/dist/supervisor-run/index.d.ts +3 -3
- package/dist/supervisor-run/index.js +3 -3
- package/dist/{supervisor-run-BEns49Nx.js → supervisor-run-DiyQVczd.js} +301 -25
- package/dist/supervisor-run-DiyQVczd.js.map +1 -0
- package/dist/types-BjMFz88h.d.ts.map +1 -1
- package/dist/{types-Dea6tiVI.d.ts → types-yLK8gXE9.d.ts} +15 -2
- package/dist/types-yLK8gXE9.d.ts.map +1 -0
- package/dist/wire/index.js +1 -1
- package/docs/campaign-proposers.md +11 -7
- package/docs/trace-analysis.md +43 -32
- package/package.json +1 -1
- package/dist/benchmark-command-CSddvlq7.js.map +0 -1
- package/dist/campaign-C7ZGiZYG.js.map +0 -1
- package/dist/dspy-rlm-engine-CJ4sN8Wx.js.map +0 -1
- package/dist/external-optimizer-contracts-nb7c_WAR.d.ts +0 -42
- package/dist/external-optimizer-contracts-nb7c_WAR.d.ts.map +0 -1
- package/dist/index-BKjcUH13.d.ts.map +0 -1
- package/dist/integrity-hruKe6oe.js.map +0 -1
- package/dist/llm-client-B3WXSH5Y.js.map +0 -1
- package/dist/single-run-lock-Do-8vBIJ.js +0 -1049
- package/dist/single-run-lock-Do-8vBIJ.js.map +0 -1
- package/dist/skill-usage-CRqaHi0R.d.ts.map +0 -1
- package/dist/skillopt-optimization-method-CwRvi-rL.d.ts.map +0 -1
- package/dist/skillopt-optimization-method-Di8Xkalt.js.map +0 -1
- package/dist/supervisor-run-BEns49Nx.js.map +0 -1
- package/dist/types-Dea6tiVI.d.ts.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dspy-rlm-engine-CJ4sN8Wx.js","names":["isRecord"],"sources":["../src/analyst/trace-tool-callback.ts","../src/analyst/dspy-rlm-engine.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto'\nimport { createServer, type IncomingMessage, type ServerResponse } from 'node:http'\nimport { closeServer, listenLocal, sendJson } from '../campaign/external-optimizer-http'\nimport type { TraceAnalysisToolDescriptor } from '../trace-analyst/tools'\n\nconst MAX_REQUEST_BYTES = 1_000_000\nconst MAX_RESPONSE_BYTES = 4_000_000\n\nexport interface TraceToolCallback {\n url: string\n token: string\n calls: () => number\n close: () => Promise<void>\n}\n\n/** Expose one bounded trace-tool set only on an authenticated loopback socket. */\nexport async function startTraceToolCallback(args: {\n tools: readonly TraceAnalysisToolDescriptor[]\n maxCalls: number\n signal?: AbortSignal\n}): Promise<TraceToolCallback> {\n if (!Number.isSafeInteger(args.maxCalls) || args.maxCalls <= 0) {\n throw new TypeError('trace tool callback maxCalls must be a positive safe integer')\n }\n args.signal?.throwIfAborted()\n const byName = new Map(args.tools.map((tool) => [tool.name, tool]))\n if (byName.size !== args.tools.length) {\n throw new Error('trace tool callback received duplicate tool names')\n }\n\n const token = randomBytes(32).toString('hex')\n let calls = 0\n let accepting = true\n let closePromise: Promise<void> | undefined\n const activeControllers = new Set<AbortController>()\n const activeHandlers = new Set<Promise<void>>()\n const server = createServer((request, response) => {\n if (!accepting) {\n sendJsonIfOpen(response, 503, { error: 'trace tool callback is closing' })\n return\n }\n const controller = new AbortController()\n const abortRequest = (): void => {\n request.destroy()\n response.destroy()\n }\n activeControllers.add(controller)\n controller.signal.addEventListener('abort', abortRequest, { once: true })\n\n let handler!: Promise<void>\n handler = handleRequest(request, response, controller.signal).finally(() => {\n controller.signal.removeEventListener('abort', abortRequest)\n activeControllers.delete(controller)\n activeHandlers.delete(handler)\n })\n activeHandlers.add(handler)\n void handler.catch(() => undefined)\n })\n const port = await listenLocal(server)\n const close = (): Promise<void> => {\n closePromise ??= closeCallback()\n return closePromise\n }\n const onAbort = (): void => {\n void close().catch(() => undefined)\n }\n args.signal?.addEventListener('abort', onAbort, { once: true })\n if (args.signal?.aborted) onAbort()\n\n return {\n url: `http://127.0.0.1:${port}/call`,\n token,\n calls: () => calls,\n close,\n }\n\n async function handleRequest(\n request: IncomingMessage,\n response: ServerResponse,\n signal: AbortSignal,\n ): Promise<void> {\n try {\n if (request.method !== 'POST' || request.url !== '/call') {\n sendJsonIfOpen(response, 404, { error: 'not found' })\n return\n }\n if (request.headers.authorization !== `Bearer ${token}`) {\n sendJsonIfOpen(response, 401, { error: 'unauthorized' })\n return\n }\n if (calls >= args.maxCalls) {\n sendJsonIfOpen(response, 429, { error: 'trace tool call limit reached' })\n return\n }\n const body = await readJson(request)\n if (!isRecord(body) || typeof body.name !== 'string' || !('args' in body)) {\n sendJsonIfOpen(response, 400, { error: 'name and args are required' })\n return\n }\n const tool = byName.get(body.name)\n if (!tool) {\n sendJsonIfOpen(response, 404, { error: `unknown trace tool '${body.name}'` })\n return\n }\n calls += 1\n const result = await tool.handler(body.args, { signal })\n const encoded = JSON.stringify({ result })\n if (Buffer.byteLength(encoded) > MAX_RESPONSE_BYTES) {\n sendJsonIfOpen(response, 413, { error: 'trace tool response too large' })\n return\n }\n response.writeHead(200, {\n 'content-type': 'application/json; charset=utf-8',\n 'content-length': String(Buffer.byteLength(encoded)),\n })\n response.end(encoded)\n } catch (error) {\n sendJsonIfOpen(response, signal.aborted ? 499 : 400, {\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n\n async function closeCallback(): Promise<void> {\n args.signal?.removeEventListener('abort', onAbort)\n accepting = false\n const closingServer = closeServer(server)\n server.closeIdleConnections?.()\n for (const controller of activeControllers) controller.abort()\n const [serverResult] = await Promise.allSettled([\n closingServer,\n waitForActiveHandlers(activeHandlers),\n ])\n if (activeControllers.size !== 0 || activeHandlers.size !== 0) {\n throw new Error('trace tool callback closed with active requests')\n }\n if (serverResult?.status === 'rejected') throw serverResult.reason\n }\n}\n\nasync function waitForActiveHandlers(activeHandlers: Set<Promise<void>>): Promise<void> {\n while (activeHandlers.size > 0) {\n await Promise.allSettled([...activeHandlers])\n }\n}\n\nfunction readJson(request: IncomingMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let size = 0\n const chunks: Buffer[] = []\n request.on('data', (chunk: Buffer) => {\n size += chunk.length\n if (size > MAX_REQUEST_BYTES) {\n reject(new Error('trace tool request too large'))\n request.destroy()\n return\n }\n chunks.push(chunk)\n })\n request.on('error', reject)\n request.on('end', () => {\n try {\n resolve(JSON.parse(Buffer.concat(chunks).toString('utf8')))\n } catch (error) {\n reject(error)\n }\n })\n })\n}\n\nfunction sendJsonIfOpen(response: ServerResponse, status: number, body: unknown): void {\n if (response.destroyed || response.writableEnded) return\n sendJson(response, status, body)\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import {\n type ExternalOptimizerModelProxy,\n type ExternalOptimizerRunnerCommand,\n removeCredentialEnvironment,\n} from '../campaign/external-optimizer-contracts'\nimport { startExternalOptimizerModelProxy } from '../campaign/external-optimizer-model-proxy'\nimport { runWithCleanup } from '../campaign/external-optimizer-resources'\nimport { runExternalOptimizerProcess } from '../campaign/external-optimizer-subprocess'\nimport type { CustomTokenPricing } from '../cost-ledger'\nimport { resolveModelPricing } from '../metrics'\nimport type { TraceAnalysisEngine, TraceAnalysisEngineResult } from './engine'\nimport { type RawAnalystFinding, RawAnalystFindingSchema } from './finding-signature'\nimport { startTraceToolCallback } from './trace-tool-callback'\n\nconst DEFAULT_TIMEOUT_MS = 10 * 60_000\n// 4096 is below what current coding models emit for a full findings array:\n// glm-5.2 through an OpenAI-compatible gateway returns 8192 and the request is\n// rejected outright (`502 — provider reported 8192 completion tokens,\n// exceeding requested limit 4096`), so the default failed 2/2 smoke cases\n// before any analysis ran. The cap exists to bound spend, and `maxCostUsd`\n// already does that directly, so it starts above what a real completion needs.\nconst DEFAULT_MODEL_OUTPUT_TOKENS = 16_384\nconst DEFAULT_MAX_COST_USD = 1\nconst MAX_MODEL_REQUEST_BYTES = 16 * 1024 * 1024\nconst MAX_MODEL_RESPONSE_BYTES = 4 * 1024 * 1024\nconst BRIDGE_MODULE = 'agent_eval_rpc.dspy_rlm_bridge'\n/** Bumped whenever this engine's execution behavior changes. */\nconst DSPY_RLM_ENGINE_VERSION = '1.0.0'\n\nexport interface DspyRlmTraceEngineOptions {\n baseUrl: string\n apiKey: string\n model: string\n /** Exact provider rates. Required when the model is absent from the pricing table. */\n pricing?: CustomTokenPricing\n /** Maximum provider spend for one investigation. Default: 1 USD. */\n maxCostUsd?: number\n /** Controller response cap. Default: 16384. */\n maxOutputTokens?: number\n /**\n * Thinking tokens one controller turn may bill on top of its completion.\n * A reasoning model bills these beyond `maxOutputTokens`, so the cost\n * reservation must cover them. Default: four times the completion cap.\n */\n maxReasoningTokens?: number\n /**\n * How the controller's reasoning and code fields are obtained.\n *\n * `tolerant` parses marker output strictly first, then recovers the fields\n * deterministically from prose plus a fenced code block — the shape coding\n * models naturally emit — at no extra model cost. `two-step` extracts with a\n * second call per turn. `chat` accepts marker output only. Default:\n * `tolerant`.\n */\n controlAdapter?: 'chat' | 'two-step' | 'tolerant'\n /** Python command used to load agent-eval-rpc[dspy]. Default: python. */\n runner?: ExternalOptimizerRunnerCommand\n /** Whole investigation deadline. Default: 10 minutes. */\n timeoutMs?: number\n}\n\n/** Use the official DSPy RLM as a bounded recursive trace-analysis engine. */\nexport function createDspyRlmTraceEngine(options: DspyRlmTraceEngineOptions): TraceAnalysisEngine {\n assertOptions(options)\n const maxOutputTokens = options.maxOutputTokens ?? DEFAULT_MODEL_OUTPUT_TOKENS\n if (!Number.isSafeInteger(maxOutputTokens) || maxOutputTokens <= 0) {\n throw new TypeError('DSPy RLM maxOutputTokens must be a positive safe integer')\n }\n const controlAdapter = options.controlAdapter ?? 'tolerant'\n const maxReasoningTokens = options.maxReasoningTokens ?? maxOutputTokens * 4\n if (!Number.isSafeInteger(maxReasoningTokens) || maxReasoningTokens < 0) {\n throw new TypeError('DSPy RLM maxReasoningTokens must be a non-negative safe integer')\n }\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS\n if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0) {\n throw new TypeError('DSPy RLM timeoutMs must be a positive safe integer')\n }\n const maxCostUsd = options.maxCostUsd ?? DEFAULT_MAX_COST_USD\n if (!Number.isFinite(maxCostUsd) || maxCostUsd <= 0) {\n throw new TypeError('DSPy RLM maxCostUsd must be positive and finite')\n }\n const pricing = options.pricing ?? pricingForModel(options.model)\n\n const runner = sanitizedRunner(options.runner)\n return {\n id: 'dspy-rlm',\n description: 'Official DSPy RLM with bounded trace tools and metered model calls.',\n model: options.model,\n version: DSPY_RLM_ENGINE_VERSION,\n executionConfig: {\n bridge_module: BRIDGE_MODULE,\n base_url: options.baseUrl,\n model: options.model,\n api_key_provided: true,\n pricing: { ...pricing },\n max_cost_usd: maxCostUsd,\n max_output_tokens: maxOutputTokens,\n max_reasoning_tokens: maxReasoningTokens,\n control_adapter: controlAdapter,\n timeout_ms: timeoutMs,\n max_request_bytes: MAX_MODEL_REQUEST_BYTES,\n max_response_bytes: MAX_MODEL_RESPONSE_BYTES,\n runner: runner ? 'caller-supplied' : 'default',\n runner_command: runner?.command ?? null,\n },\n async analyze(request) {\n const callback = await startTraceToolCallback({\n tools: request.tools,\n maxCalls: request.limits.maxToolCalls,\n ...(request.signal ? { signal: request.signal } : {}),\n })\n let modelProxy: ExternalOptimizerModelProxy | undefined\n const result = await runWithCleanup({\n label: 'DSPy RLM trace-analysis resources',\n run: async () => {\n modelProxy = await startExternalOptimizerModelProxy({\n upstreamBaseUrl: options.baseUrl,\n upstreamApiKey: options.apiKey,\n model: options.model,\n budget: {\n maxCostUsd,\n maxRequests: request.limits.maxIterations + request.limits.maxLlmCalls + 1,\n maxRequestBytes: MAX_MODEL_REQUEST_BYTES,\n maxResponseBytes: MAX_MODEL_RESPONSE_BYTES,\n maxOutputTokensPerRequest: maxOutputTokens,\n maxReasoningTokensPerRequest: maxReasoningTokens,\n requestTimeoutMs: timeoutMs,\n pricing,\n },\n costLedger: request.costLedger,\n channel: 'analyst',\n phase: request.costPhase,\n actor: request.analystId,\n ...(request.costTags ? { tags: request.costTags } : {}),\n ...(request.signal ? { signal: request.signal } : {}),\n })\n request.log?.('trace analyst engine started', {\n engine: 'dspy-rlm',\n model: options.model,\n tools: request.tools.map((tool) => tool.name),\n limits: request.limits,\n })\n const raw = await runExternalOptimizerProcess<unknown>({\n label: 'DSPy RLM trace analysis',\n tempPrefix: 'agent-eval-dspy-rlm-',\n module: BRIDGE_MODULE,\n input: {\n operation: 'analyze',\n question: request.question,\n instructions: request.instructions,\n modelProxy: {\n baseUrl: modelProxy.baseUrl,\n apiKey: modelProxy.apiKey,\n model: options.model,\n maxOutputTokens,\n },\n toolCallback: {\n url: callback.url,\n token: callback.token,\n },\n toolSpecs: request.tools.map(({ name, description, parameters }) => ({\n name,\n description,\n parameters,\n })),\n controlAdapter,\n limits: {\n maxIterations: request.limits.maxIterations,\n maxLlmCalls: request.limits.maxLlmCalls,\n maxOutputChars: request.limits.maxOutputChars,\n },\n },\n ...(runner ? { runner } : {}),\n timeoutMs,\n ...(request.signal ? { signal: request.signal } : {}),\n })\n const parsed = parseBridgeOutput(raw, (index, reason) => {\n request.log?.('finding rejected: bridge row failed schema validation', {\n engine: 'dspy-rlm',\n index,\n reason,\n })\n })\n const successfulCompletions = modelProxy.successfulCompletions()\n const requestAttempts = modelProxy.requestAttempts()\n const rateLimitRetries = modelProxy.rateLimitRetries()\n if (parsed.modelCalls !== successfulCompletions) {\n throw new Error(\n `DSPy RLM reported ${parsed.modelCalls} model calls, but the provider proxy recorded ${successfulCompletions}`,\n )\n }\n return {\n ...parsed,\n toolCalls: callback.calls(),\n runtime: {\n ...parsed.runtime,\n modelRequestAttempts: requestAttempts,\n modelSuccessfulCompletions: successfulCompletions,\n modelRateLimitRetries: rateLimitRetries,\n },\n } satisfies TraceAnalysisEngineResult\n },\n cleanup: async () => {\n const results = await Promise.allSettled([\n ...(modelProxy ? [modelProxy.close()] : []),\n callback.close(),\n ])\n const errors = results.flatMap((entry) =>\n entry.status === 'rejected' ? [entry.reason] : [],\n )\n if (errors.length > 0) {\n throw new AggregateError(errors, 'DSPy RLM resource cleanup failed')\n }\n },\n })\n request.log?.('trace analyst engine completed', {\n engine: 'dspy-rlm',\n model_calls: result.modelCalls,\n model_request_attempts: result.runtime.modelRequestAttempts,\n model_rate_limit_retries: result.runtime.modelRateLimitRetries,\n tool_calls: result.toolCalls,\n findings: result.findings.length,\n })\n return result\n },\n }\n}\n\nfunction parseBridgeOutput(\n value: unknown,\n onRejectedFinding: (index: number, reason: string) => void,\n): Omit<TraceAnalysisEngineResult, 'toolCalls'> {\n if (!isRecord(value)) throw new Error('DSPy RLM bridge output must be an object')\n if (typeof value.answer !== 'string' || !value.answer.trim()) {\n throw new Error('DSPy RLM bridge returned no answer')\n }\n if (!Array.isArray(value.findings)) {\n throw new Error('DSPy RLM bridge findings must be an array')\n }\n // Findings are model output: one malformed row is model noise, not a bridge\n // fault, and the rest of the paid investigation must survive it. Rejected\n // rows are logged per row and counted in runtime.rejectedFindings.\n let rejectedFindings = 0\n const findings: RawAnalystFinding[] = []\n value.findings.forEach((finding, index) => {\n const parsed = RawAnalystFindingSchema.safeParse(finding)\n if (!parsed.success) {\n rejectedFindings += 1\n onRejectedFinding(\n index,\n parsed.error.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`).join('; '),\n )\n return\n }\n findings.push(parsed.data)\n })\n if (!Array.isArray(value.trajectory)) {\n throw new Error('DSPy RLM bridge trajectory must be an array')\n }\n if (!Number.isSafeInteger(value.modelCalls) || (value.modelCalls as number) <= 0) {\n throw new Error('DSPy RLM bridge modelCalls must be a positive safe integer')\n }\n if (!isRecord(value.runtime)) {\n throw new Error('DSPy RLM bridge runtime must be an object')\n }\n return {\n answer: value.answer,\n findings,\n trajectory: value.trajectory,\n modelCalls: value.modelCalls as number,\n runtime: { ...value.runtime, rejectedFindings },\n }\n}\n\nfunction assertOptions(options: DspyRlmTraceEngineOptions): void {\n for (const [name, value] of [\n ['baseUrl', options.baseUrl],\n ['apiKey', options.apiKey],\n ['model', options.model],\n ] as const) {\n if (typeof value !== 'string' || !value.trim()) {\n throw new TypeError(`DSPy RLM ${name} must be a non-empty string`)\n }\n }\n}\n\nfunction pricingForModel(model: string): CustomTokenPricing {\n const pricing = resolveModelPricing(model)\n if (!pricing) {\n throw new Error(\n `no pricing is configured for '${model}'; provide DspyRlmTraceEngineOptions.pricing`,\n )\n }\n return {\n inputUsdPerMillion: pricing.input * 1_000,\n outputUsdPerMillion: pricing.output * 1_000,\n }\n}\n\nfunction sanitizedRunner(\n runner: ExternalOptimizerRunnerCommand | undefined,\n): ExternalOptimizerRunnerCommand | undefined {\n if (!runner) return undefined\n return {\n ...(runner.command ? { command: runner.command } : {}),\n ...(runner.args ? { args: runner.args } : {}),\n ...(runner.env ? { env: removeCredentialEnvironment(runner.env) } : {}),\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n"],"mappings":"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"}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { b as CustomTokenPricing } from "./cost-ledger-FuQvHxPm.js";
|
|
2
|
-
//#region src/campaign/external-optimizer-contracts.d.ts
|
|
3
|
-
interface ExternalOptimizerRunnerCommand {
|
|
4
|
-
command?: string;
|
|
5
|
-
args?: readonly string[];
|
|
6
|
-
env?: NodeJS.ProcessEnv;
|
|
7
|
-
}
|
|
8
|
-
type ExternalOptimizerResumeMode = 'never' | 'if-compatible' | 'required';
|
|
9
|
-
type ExternalTextCandidate = string | Record<string, string>;
|
|
10
|
-
interface ExternalTextEvaluationRequest {
|
|
11
|
-
candidate: ExternalTextCandidate;
|
|
12
|
-
exampleId: string;
|
|
13
|
-
}
|
|
14
|
-
interface ExternalOptimizerModelBudget {
|
|
15
|
-
/** Maximum optimizer-model spend, independent of task-evaluation spend. */
|
|
16
|
-
maxCostUsd: number;
|
|
17
|
-
/** Network attempts, including provider retries. */
|
|
18
|
-
maxRequests: number;
|
|
19
|
-
/** Reject a request body above this byte count. */
|
|
20
|
-
maxRequestBytes: number;
|
|
21
|
-
/** Reject a provider response above this byte count. */
|
|
22
|
-
maxResponseBytes: number;
|
|
23
|
-
/** Reject a request asking the provider for more output tokens. */
|
|
24
|
-
maxOutputTokensPerRequest: number;
|
|
25
|
-
/**
|
|
26
|
-
* Reasoning tokens a single response may bill beyond its completion limit.
|
|
27
|
-
*
|
|
28
|
-
* A reasoning model bounds only the completion by `max_tokens` and bills
|
|
29
|
-
* thinking on top, so a reservation sized to the completion alone is always
|
|
30
|
-
* too small and the ledger refuses the real charge. Callers that route a
|
|
31
|
-
* reasoning model declare its thinking budget here; the reservation covers
|
|
32
|
-
* it and a response exceeding it still fails loudly. Default: 0.
|
|
33
|
-
*/
|
|
34
|
-
maxReasoningTokensPerRequest?: number;
|
|
35
|
-
/** Rates used to estimate cost when the provider omits a valid `usage.cost`. */
|
|
36
|
-
pricing: CustomTokenPricing;
|
|
37
|
-
/** Per-provider-request deadline. Default: 300,000 ms. */
|
|
38
|
-
requestTimeoutMs?: number;
|
|
39
|
-
}
|
|
40
|
-
//#endregion
|
|
41
|
-
export { ExternalTextEvaluationRequest as a, ExternalTextCandidate as i, ExternalOptimizerResumeMode as n, ExternalOptimizerRunnerCommand as r, ExternalOptimizerModelBudget as t };
|
|
42
|
-
//# sourceMappingURL=external-optimizer-contracts-nb7c_WAR.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"external-optimizer-contracts-nb7c_WAR.d.ts","names":[],"sources":["../src/campaign/external-optimizer-contracts.ts"],"mappings":";;UAKiB;EACf;EACA;EACA,MAAM,OAAO;;KAGH;KAEA,iCAAiC;UAE5B;EACf,WAAW;EACX;;UAUe;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;;;;;;;;;EAUA;;EAEA,SAAS;;EAET"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BKjcUH13.d.ts","names":[],"sources":["../src/supervisor-run/source-facts.ts","../src/supervisor-run/analyze.ts","../src/supervisor-run/claude-code-reader.ts","../src/supervisor-run/integrity-types.ts","../src/supervisor-run/integrity.ts","../src/supervisor-run/loops-reader.ts","../src/supervisor-run/render.ts","../src/supervisor-run/rollout-nodes.ts"],"mappings":";;;UAqBU;EACR;EACA;EACA;EACA;;EAEA;;UAGQ;EACR,QAAQ;EACR;;UAgFe;;EAEf;EACA;EACA;EACA;EACA,MAAM;EACN;;EAEA;EACA;;UAGe;EACf;EACA;EACA;;EAEA;;EAEA;;EAEA;;EAEA;EACA;EACA,OAAO;;EAEP;;UAGe;;EAEf;EACA;EACA;;EAEA;EACA;EACA;EACA;EACA;;EAEA;EACA;EACA;;EAEA;;EAEA;EACA;;EAEA;;EAEA;EACA;EACA;EACA;EACA,eAAe;EACf,uBAAuB;;UAGR;;EAEf;EACA;;UAGe;;EAEf;;EAEA;EACA;;;;;;UAOe;WACN;WACA,iBAAiB;WACjB,iBAAiB;WACjB,uBAAuB;WACvB,uBAAuB;WACvB;IACP;IACA;IACA;IACA;;IAEA;IACA;IACA;;WAEO,YAAY,oBAAoB;;WAEhC,wBAAwB;;WAExB;;;;;;;;;WASA;;WAEA;;;;;;WAMA,0BAA0B,SAAS;;WAEnC,gBAAgB;;WAEhB,OAAO;WACP;WACA;;;;;;;;;;;;;;;;;;KAmDC;iBAiFI,oBAAoB,KAAK,uBAAuB;;;;;;;iBCnThD,4BACd,KAAK,sBACL,qBACC;;iBA6oBa,WAAW,eAAe;;;;;;iBA+C1B,qBAAqB,kBAAkB,wBAAwB;;;;cCtrBlE;;cAEA;;cAEA;UASI;;WAEN;;;;;WAKA;WACA;WACA;WACA;WACA;WACA;WACA;;;;;;iBAmOW,4BACpB,MAAM,0BACL,QAAQ;;iBAiUK,8BAA8B,MAAM,0BAA0B;;;cCnoBjE;KAED;KAEA;KAKA;UAmCK;WACN;WACA;;UAGM;WACN,MAAM;WACN;WACA,UAAU;WACV;WACA;WACA;WACA,mBAAmB;WACnB;WACA,WAAW,SAAS;;UAGd;WACN,eAAe;WACf;WACA;WACA,MAAM;WACN,iBAAiB;;UAGX;;WAEN;;;;;;;;iBC5BK,8BACd,OAAO,uBAAuB,mBAC9B,UAAS,gCACR;;;;;;;iBCFmB,uBAAuB,aAAa;UAUzC;;WAEN;;WAEA;;WAEA;;WAEA;;;;;;;iBAQW,uBACpB,gBACA,OAAM,qBACL,QAAQ;;iBAmKK,yBACd,gBACA,OAAM,qBACL;;;;;;iBAkCmB,qBACpB,gBAAgB,sBAAsB,sBACtC,OAAM,qBACL,QAAQ;UAYM,kCAAkC;;WAExC;;WAEA;;;;;;WAMA;;;;;;;;iBASW,yBACpB,gBACA,OAAM,4BACL,QAAQ;;;;;;;iBAuBK,qBAAqB;;;;;iBAiBf,6BACpB,gBACA,OAAM,4BACL,QAAQ;;;;;;iBAgBW,sBACpB,gBACA,OAAM;EAA8B;IACnC,QAAQ;;iBA0BW,sBAAsB,eAAe;;;;;;;iBC7X3C,4BAA4B,GAAG;iBAgC/B,4BAA4B,GAAG;iBAwK/B,+BACd,QAAQ,qBACR;;;UCtLe;;WAEN;;WAEA,QAAQ;;WAER;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;;WAEA;;;;;;;iBAwBK,0BACd,KAAK,sBACL,OAAM,2BACL"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"integrity-hruKe6oe.js","names":["unhandled"],"sources":["../src/supervisor-run/integrity-issues.ts","../src/supervisor-run/integrity-steer.ts","../src/supervisor-run/integrity-source.ts","../src/supervisor-run/integrity-tree.ts","../src/supervisor-run/integrity-types.ts","../src/supervisor-run/source-facts.ts","../src/supervisor-run/rollout-nodes.ts","../src/supervisor-run/integrity.ts"],"sourcesContent":["import type { SupervisorRunIntegrityEvidence, SupervisorRunIntegrityIssue } from './integrity-types'\n\nexport const MAX_EXAMPLES = 20\n\nexport function evidence(path: string, value: unknown): SupervisorRunIntegrityEvidence {\n return { path, value }\n}\n\nexport function issue(\n init: Omit<SupervisorRunIntegrityIssue, 'evidence'> & {\n evidence?: readonly SupervisorRunIntegrityEvidence[]\n },\n): SupervisorRunIntegrityIssue {\n return { ...init, evidence: init.evidence ?? [] }\n}\n","import { evidence, issue, MAX_EXAMPLES } from './integrity-issues'\nimport type { JoinedWorker } from './integrity-source'\nimport type { SupervisorRunIntegrityIssue } from './integrity-types'\n\nfunction idListDetail(ids: readonly string[]): string {\n const examples = ids\n .slice(0, MAX_EXAMPLES)\n .map((id) => JSON.stringify(id))\n .join(', ')\n return ids.length <= MAX_EXAMPLES\n ? examples\n : `${examples}, and ${ids.length - MAX_EXAMPLES} more`\n}\n\nexport function steerIssues(\n joined: JoinedWorker,\n rootCompleted: boolean,\n): SupervisorRunIntegrityIssue[] {\n const { facts } = joined\n const subject = facts.workerId ?? joined.spawn.id\n const prefix = `workers/${facts.sourceIndex}`\n const out: SupervisorRunIntegrityIssue[] = []\n if (\n !facts.inboxCaptured ||\n !facts.eventsCaptured ||\n facts.inboxInvalidRows > 0 ||\n facts.eventsInvalidRows > 0\n ) {\n const missing = [\n ...(facts.inboxCaptured ? [] : ['inbox']),\n ...(facts.eventsCaptured ? [] : ['events']),\n ]\n const malformed = [\n ...(facts.inboxInvalidRows > 0 ? [`inbox:${facts.inboxInvalidRows}`] : []),\n ...(facts.eventsInvalidRows > 0 ? [`events:${facts.eventsInvalidRows}`] : []),\n ]\n out.push(\n issue({\n code: 'worker-controls-unavailable',\n area: 'capture-integrity',\n severity: 'medium',\n subject,\n claim:\n 'Steer delivery integrity is unavailable for a worker with missing control artifacts',\n detail:\n missing.length > 0\n ? `${JSON.stringify(subject)} is missing ${missing.join(' and ')}.`\n : `${JSON.stringify(subject)} has malformed control rows (${malformed.join(', ')}).`,\n evidence: [\n ...missing.map((artifact) => evidence(`${prefix}/${artifact}`, null)),\n ...(facts.inboxInvalidRows > 0\n ? [evidence(`${prefix}/inbox/malformed-rows/count`, facts.inboxInvalidRows)]\n : []),\n ...(facts.eventsInvalidRows > 0\n ? [evidence(`${prefix}/events/malformed-rows/count`, facts.eventsInvalidRows)]\n : []),\n ],\n recommendedAction:\n 'Retain both control artifacts and repair malformed rows before correlating requests.',\n metadata: {\n assessment: 'unavailable',\n missing_artifacts: missing,\n malformed_rows: malformed,\n },\n }),\n )\n return out\n }\n\n const requestsById = new Map<string, typeof facts.steerRequests>()\n const unidentifiedRequests = facts.steerRequests.filter((request) => request.requestId === null)\n for (const request of facts.steerRequests) {\n if (request.requestId === null) continue\n const rows = requestsById.get(request.requestId) ?? []\n rows.push(request)\n requestsById.set(request.requestId, rows)\n }\n if (unidentifiedRequests.length > 0) {\n out.push(\n issue({\n code: 'steer-request-id-unavailable',\n area: 'capture-integrity',\n severity: 'high',\n subject,\n claim: 'Some queued steer requests cannot be correlated because their ids are missing',\n detail: `${unidentifiedRequests.length} queued request(s) omit id.`,\n evidence: unidentifiedRequests\n .slice(0, MAX_EXAMPLES)\n .map((request) => evidence(`${prefix}/inbox/${request.row}/id`, null)),\n recommendedAction: 'Assign one stable request id before appending a steer to the inbox.',\n metadata: { assessment: 'unavailable', unavailable_count: unidentifiedRequests.length },\n }),\n )\n }\n const duplicateRequestIds = [...requestsById]\n .filter(([, rows]) => rows.length > 1)\n .map(([id]) => id)\n if (duplicateRequestIds.length > 0) {\n out.push(\n issue({\n code: 'duplicate-steer-request-id',\n area: 'control-integrity',\n severity: 'high',\n subject,\n claim: 'A worker inbox contains duplicate steer request ids',\n detail: `${duplicateRequestIds.length} duplicate id(s): ${idListDetail(duplicateRequestIds)}.`,\n evidence: [\n evidence(\n `${prefix}/inbox/duplicate-request-ids`,\n duplicateRequestIds.slice(0, MAX_EXAMPLES),\n ),\n ],\n recommendedAction: 'Generate a unique request id for every queued steer.',\n }),\n )\n }\n\n const acknowledgementsById = new Map<string, typeof facts.steerAcknowledgements>()\n const unidentifiedAcks = facts.steerAcknowledgements.filter((ack) => ack.requestId === null)\n for (const ack of facts.steerAcknowledgements) {\n if (ack.requestId === null) continue\n const rows = acknowledgementsById.get(ack.requestId) ?? []\n rows.push(ack)\n acknowledgementsById.set(ack.requestId, rows)\n }\n if (unidentifiedAcks.length > 0) {\n out.push(\n issue({\n code: 'steer-ack-id-unavailable',\n area: 'capture-integrity',\n severity: 'high',\n subject,\n claim: 'Some steer acknowledgements cannot be correlated because requestId is missing',\n detail: `${unidentifiedAcks.length} down-leg event(s) omit requestId.`,\n evidence: unidentifiedAcks\n .slice(0, MAX_EXAMPLES)\n .map((ack) => evidence(`${prefix}/events/${ack.row}/requestId`, null)),\n recommendedAction: 'Echo the queued request id on every worker acknowledgement.',\n metadata: { assessment: 'unavailable', unavailable_count: unidentifiedAcks.length },\n }),\n )\n }\n\n const unknownAckIds = [...acknowledgementsById.keys()].filter((id) => !requestsById.has(id))\n if (unknownAckIds.length > 0) {\n out.push(\n issue({\n code: 'unknown-steer-ack',\n area: 'control-integrity',\n severity: 'high',\n subject,\n claim: 'A worker acknowledged steer request ids absent from its captured inbox',\n detail: `${unknownAckIds.length} unknown id(s): ${idListDetail(unknownAckIds)}.`,\n evidence: [\n evidence(`${prefix}/events/unknown-request-ids`, unknownAckIds.slice(0, MAX_EXAMPLES)),\n ],\n recommendedAction:\n 'Reject acknowledgements whose request id was not queued for this worker.',\n }),\n )\n }\n\n const duplicateAckIds = [...acknowledgementsById]\n .filter(([, rows]) => rows.length > 1)\n .map(([id]) => id)\n if (duplicateAckIds.length > 0) {\n out.push(\n issue({\n code: 'duplicate-steer-ack',\n area: 'control-integrity',\n severity: 'high',\n subject,\n claim: 'A worker emitted duplicate acknowledgements for steer request ids',\n detail: `${duplicateAckIds.length} duplicated id(s): ${idListDetail(duplicateAckIds)}.`,\n evidence: [\n evidence(\n `${prefix}/events/duplicate-request-ids`,\n duplicateAckIds.slice(0, MAX_EXAMPLES),\n ),\n ],\n recommendedAction: 'Make steer acknowledgement append idempotent by request id.',\n }),\n )\n }\n\n const missingAckIds = [...requestsById.keys()].filter((id) => !acknowledgementsById.has(id))\n if (rootCompleted && missingAckIds.length > 0) {\n out.push(\n issue({\n code: 'missing-steer-ack',\n area: 'control-integrity',\n severity: 'high',\n subject,\n claim: 'A completed supervisor run has queued steer requests without acknowledgements',\n detail: `${missingAckIds.length}/${requestsById.size} request id(s) are unacknowledged: ${idListDetail(missingAckIds)}.`,\n evidence: [\n evidence(\n `${prefix}/inbox/unacknowledged-request-ids`,\n missingAckIds.slice(0, MAX_EXAMPLES),\n ),\n ],\n recommendedAction:\n 'Record one delivered or failed acknowledgement for every queued request id.',\n }),\n )\n }\n\n const statusUnavailableIds: string[] = []\n const notDeliveredIds: string[] = []\n for (const [id, acknowledgements] of acknowledgementsById) {\n if (!requestsById.has(id) || acknowledgements.length !== 1) continue\n const delivered = acknowledgements[0]?.delivered\n if (delivered === null || delivered === undefined) statusUnavailableIds.push(id)\n else if (!delivered) notDeliveredIds.push(id)\n }\n if (statusUnavailableIds.length > 0) {\n out.push(\n issue({\n code: 'steer-ack-status-unavailable',\n area: 'capture-integrity',\n severity: 'high',\n subject,\n claim: 'Some steer acknowledgements omit delivery status',\n detail: `${statusUnavailableIds.length} id(s): ${idListDetail(statusUnavailableIds)}.`,\n evidence: [\n evidence(\n `${prefix}/events/status-unavailable-request-ids`,\n statusUnavailableIds.slice(0, MAX_EXAMPLES),\n ),\n ],\n recommendedAction: 'Record delivered: true or delivered: false on each acknowledgement.',\n metadata: { assessment: 'unavailable', unavailable_count: statusUnavailableIds.length },\n }),\n )\n }\n if (notDeliveredIds.length > 0) {\n out.push(\n issue({\n code: 'steer-not-delivered',\n area: 'control-integrity',\n severity: 'high',\n subject,\n claim: 'Queued steer requests were acknowledged but not delivered',\n detail: `${notDeliveredIds.length} id(s): ${idListDetail(notDeliveredIds)}.`,\n evidence: [\n evidence(\n `${prefix}/events/not-delivered-request-ids`,\n notDeliveredIds.slice(0, MAX_EXAMPLES),\n ),\n ],\n recommendedAction:\n 'Retry or explicitly fail the control request instead of treating it as delivered.',\n }),\n )\n }\n return out\n}\n","import { evidence, issue, MAX_EXAMPLES } from './integrity-issues'\nimport { steerIssues } from './integrity-steer'\nimport type { SupervisorRunIntegrityIssue } from './integrity-types'\nimport type { SpawnRow, SupervisorTreeFacts, WorkerLogFacts } from './source-facts'\nimport type { SupervisorRunSources, SupervisorRunTree } from './types'\n\nfunction sourceIdentityIssues(facts: SupervisorTreeFacts): SupervisorRunIntegrityIssue[] {\n const out: SupervisorRunIntegrityIssue[] = []\n const malformedSpawns = facts.spawns.filter((spawn) => !spawn.valid)\n if (facts.journalInvalidRows > 0 || malformedSpawns.length > 0) {\n out.push(\n issue({\n code: 'source-row-malformed',\n area: 'capture-integrity',\n severity: 'high',\n subject: 'journal-rows',\n claim: 'Some supervisor journal rows could not be interpreted',\n detail: `${facts.journalInvalidRows} of ${facts.journalRows} row(s) could not be interpreted (${facts.journalMalformedJsonRows} were not JSON objects) and ${malformedSpawns.length} malformed spawn row(s) were excluded from structural conclusions.`,\n evidence: [\n evidence('journal/uninterpretable-rows/count', facts.journalInvalidRows),\n evidence('journal/malformed-json-rows/count', facts.journalMalformedJsonRows),\n evidence('journal/rows/count', facts.journalRows),\n evidence('journal/dialect', facts.journalDialect),\n ...malformedSpawns\n .slice(0, MAX_EXAMPLES)\n .map((spawn) =>\n evidence(`journal/spawns/${spawn.sourceRow}/invalid-fields`, spawn.invalidFields),\n ),\n ],\n recommendedAction:\n 'Repair the rows, or teach the parser the shape they are in, before using the run for structural analysis. A row nobody can read must never be silently absent from the tree.',\n metadata: {\n assessment: 'unavailable',\n journal_rows: facts.journalRows,\n uninterpretable_rows: facts.journalInvalidRows,\n malformed_json_rows: facts.journalMalformedJsonRows,\n malformed_spawn_rows: malformedSpawns.length,\n journal_dialect: facts.journalDialect,\n },\n }),\n )\n }\n const unidentifiedSpawns = malformedSpawns.filter((spawn) => spawn.id.length === 0)\n const unidentifiedCloses = facts.closes.filter((close) => close.id.length === 0)\n if (unidentifiedSpawns.length + unidentifiedCloses.length > 0) {\n out.push(\n issue({\n code: 'source-event-identity-unavailable',\n area: 'capture-integrity',\n severity: 'high',\n subject: 'journal-event-identity',\n claim: 'Some supervisor journal events have no usable invocation id',\n detail: `${unidentifiedSpawns.length} spawn and ${unidentifiedCloses.length} terminal event(s) lack an id.`,\n evidence: [\n evidence('journal/unidentified-spawns/count', unidentifiedSpawns.length),\n evidence('journal/unidentified-terminals/count', unidentifiedCloses.length),\n ],\n recommendedAction: 'Reject or repair control events that omit their stable invocation id.',\n metadata: { assessment: 'unavailable', checks: ['journal-event-linkage'] },\n }),\n )\n }\n\n const spawnCounts = new Map<string, number>()\n for (const spawn of facts.spawns) {\n if (!spawn.valid || spawn.id.length === 0) continue\n spawnCounts.set(spawn.id, (spawnCounts.get(spawn.id) ?? 0) + 1)\n }\n for (const [id, count] of spawnCounts) {\n if (count < 2) continue\n out.push(\n issue({\n code: 'duplicate-spawn',\n area: 'control-integrity',\n severity: 'critical',\n subject: id,\n claim: 'An invocation has more than one spawned control event',\n detail: `${count} spawned events name invocation ${JSON.stringify(id)}.`,\n evidence: [evidence(`journal/spawn-count/${encodeURIComponent(id)}`, count)],\n recommendedAction: 'Make spawn event append idempotent.',\n }),\n )\n }\n\n const closeCounts = new Map<string, number>()\n for (const close of facts.closes) {\n if (close.id.length === 0) continue\n closeCounts.set(close.id, (closeCounts.get(close.id) ?? 0) + 1)\n }\n const uncertainSpawnIds = new Set(\n malformedSpawns.filter((spawn) => spawn.id.length > 0).map((spawn) => spawn.id),\n )\n if (unidentifiedSpawns.length === 0 && facts.journalInvalidRows === 0) {\n const orphanCloses = new Map<string, Array<(typeof facts.closes)[number]>>()\n for (const close of facts.closes) {\n if (close.id.length === 0 || spawnCounts.has(close.id) || uncertainSpawnIds.has(close.id)) {\n continue\n }\n const rows = orphanCloses.get(close.id) ?? []\n rows.push(close)\n orphanCloses.set(close.id, rows)\n }\n for (const [id, closes] of orphanCloses) {\n out.push(\n issue({\n code: 'orphan-terminal',\n area: 'control-integrity',\n severity: 'critical',\n subject: id,\n claim: 'A terminal control event names an invocation that was never spawned',\n detail: `${closes.length} terminal event(s) for ${JSON.stringify(id)} have no matching spawn.`,\n evidence: [\n evidence(`journal/closes/${encodeURIComponent(id)}/count`, closes.length),\n ...closes\n .slice(0, MAX_EXAMPLES)\n .map((close, index) =>\n evidence(`journal/closes/${encodeURIComponent(id)}/${index}`, close),\n ),\n ],\n recommendedAction: 'Retain the matching spawn event or reject the orphan terminal event.',\n }),\n )\n }\n }\n for (const [id, count] of closeCounts) {\n if (count < 2) continue\n out.push(\n issue({\n code: 'duplicate-terminal',\n area: 'control-integrity',\n severity: 'critical',\n subject: id,\n claim: 'An invocation has more than one terminal control event',\n detail: `${count} settled/cancelled events name invocation ${JSON.stringify(id)}.`,\n evidence: [evidence(`journal/terminal-count/${encodeURIComponent(id)}`, count)],\n recommendedAction: 'Make terminal event append idempotent.',\n }),\n )\n }\n return out\n}\n\nexport interface JoinedWorker {\n readonly spawn: SpawnRow\n readonly facts: WorkerLogFacts\n}\n\nfunction joinWorkerControls(facts: SupervisorTreeFacts): {\n joined: JoinedWorker[]\n issue: SupervisorRunIntegrityIssue | null\n} {\n const spawnsById = new Map<string, SpawnRow[]>()\n const spawnsByLabel = new Map<string, SpawnRow[]>()\n for (const spawn of facts.workerSpawns) {\n const ids = spawnsById.get(spawn.id) ?? []\n ids.push(spawn)\n spawnsById.set(spawn.id, ids)\n const labels = spawnsByLabel.get(spawn.label) ?? []\n labels.push(spawn)\n spawnsByLabel.set(spawn.label, labels)\n }\n const rowsWithoutIdByLabel = new Map<string, WorkerLogFacts[]>()\n for (const row of facts.workerLogRows) {\n if (row.workerId !== null && row.workerId.length > 0) continue\n const matches = rowsWithoutIdByLabel.get(row.label) ?? []\n matches.push(row)\n rowsWithoutIdByLabel.set(row.label, matches)\n }\n\n const rowsBySpawn = new Map<string, WorkerLogFacts[]>()\n const unmatchedRows: number[] = []\n const ambiguousRows: number[] = []\n for (const row of facts.workerLogRows) {\n const matches =\n row.workerId !== null && row.workerId.length > 0\n ? (spawnsById.get(row.workerId) ?? [])\n : (rowsWithoutIdByLabel.get(row.label)?.length ?? 0) === 1\n ? (spawnsByLabel.get(row.label) ?? [])\n : []\n if (matches.length === 0) {\n unmatchedRows.push(row.sourceIndex)\n continue\n }\n if (matches.length !== 1) {\n ambiguousRows.push(row.sourceIndex)\n continue\n }\n const spawn = matches[0] as SpawnRow\n const joined = rowsBySpawn.get(spawn.id) ?? []\n joined.push(row)\n rowsBySpawn.set(spawn.id, joined)\n }\n\n const joined: JoinedWorker[] = []\n const missingSpawnIds: string[] = []\n const duplicateSpawnIds: string[] = []\n for (const spawn of facts.workerSpawns) {\n if ((spawnsById.get(spawn.id)?.length ?? 0) !== 1) continue\n const rows = rowsBySpawn.get(spawn.id) ?? []\n if (rows.length === 0) missingSpawnIds.push(spawn.id)\n else if (rows.length > 1) duplicateSpawnIds.push(spawn.id)\n else joined.push({ spawn, facts: rows[0] as WorkerLogFacts })\n }\n\n if (\n missingSpawnIds.length === 0 &&\n duplicateSpawnIds.length === 0 &&\n unmatchedRows.length === 0 &&\n ambiguousRows.length === 0\n ) {\n return { joined, issue: null }\n }\n return {\n joined,\n issue: issue({\n code: 'worker-control-join-unavailable',\n area: 'capture-integrity',\n severity: 'high',\n subject: 'worker-control-join',\n claim: 'Worker control-log coverage does not match recorded child invocations',\n detail: `${missingSpawnIds.length} spawn(s) have no log, ${duplicateSpawnIds.length} have duplicate logs, ${unmatchedRows.length} log row(s) match no spawn, and ${ambiguousRows.length} row(s) are ambiguous.`,\n evidence: [\n evidence('workers/join/missing-spawn-ids', missingSpawnIds.slice(0, MAX_EXAMPLES)),\n evidence('workers/join/duplicate-spawn-ids', duplicateSpawnIds.slice(0, MAX_EXAMPLES)),\n evidence('workers/join/unmatched-source-rows', unmatchedRows.slice(0, MAX_EXAMPLES)),\n evidence('workers/join/ambiguous-source-rows', ambiguousRows.slice(0, MAX_EXAMPLES)),\n ],\n recommendedAction:\n 'Retain exactly one worker control row with workerId for every spawned invocation.',\n metadata: {\n assessment: 'unavailable',\n missing_count: missingSpawnIds.length,\n duplicate_count: duplicateSpawnIds.length,\n unmatched_count: unmatchedRows.length,\n ambiguous_count: ambiguousRows.length,\n },\n }),\n }\n}\n\nexport function sourceIssues(\n source: SupervisorRunSources,\n facts: SupervisorTreeFacts,\n tree: SupervisorRunTree,\n): SupervisorRunIntegrityIssue[] {\n const out = sourceIdentityIssues(facts)\n if (source.workers === null) {\n const reason = source.workersMissingReason ?? 'worker control-log store was not captured'\n out.push(\n issue({\n code: 'worker-controls-unavailable',\n area: 'capture-integrity',\n severity: 'medium',\n subject: 'steer-delivery',\n claim:\n 'Steer delivery integrity is unavailable because worker control logs were not captured',\n detail: reason,\n evidence: [evidence('sources/workers', null)],\n recommendedAction: 'Retain each worker inbox and event stream.',\n metadata: { assessment: 'unavailable', reason },\n }),\n )\n return out\n }\n\n const joined = joinWorkerControls(facts)\n if (joined.issue !== null) out.push(joined.issue)\n const rootCompleted =\n tree.rootId !== null &&\n tree.nodes.filter((node) => node.rollout_id === tree.rootId).length === 1 &&\n tree.nodes.find((node) => node.rollout_id === tree.rootId)?.outcome.is_completed === true\n for (const row of joined.joined) out.push(...steerIssues(row, rootCompleted))\n return out\n}\n","import { validateRolloutLine } from '../rollout/schema'\nimport { evidence, issue, MAX_EXAMPLES } from './integrity-issues'\nimport type { SupervisorRunIntegrityEvidence, SupervisorRunIntegrityIssue } from './integrity-types'\nimport type { SupervisorRunTree } from './types'\n\ninterface NodeRecord {\n readonly index: number\n readonly raw: Record<string, unknown>\n readonly errors: readonly string[]\n readonly id: string | null\n readonly parent: string | null | undefined\n readonly runId: string | null\n readonly role: string | null\n readonly messages: readonly unknown[] | null\n readonly profileId: string | null\n readonly completed: boolean | null\n readonly terminal: boolean | null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction nonEmptyString(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null\n}\n\nfunction parentValue(raw: Record<string, unknown>): string | null | undefined {\n if (raw.parent_rollout_id === null) return null\n return nonEmptyString(raw.parent_rollout_id) ?? undefined\n}\n\nfunction terminalValue(outcome: Record<string, unknown> | null): boolean | null {\n if (outcome === null) return null\n if (typeof outcome.is_completed !== 'boolean' || typeof outcome.is_truncated !== 'boolean') {\n return null\n }\n if (outcome.error !== null && typeof outcome.error !== 'string') return null\n return outcome.is_completed || outcome.is_truncated || outcome.error !== null\n}\n\nfunction nodeRecord(value: unknown, index: number): NodeRecord {\n const raw = isRecord(value) ? value : {}\n const policy = isRecord(raw.policy) ? raw.policy : null\n const outcome = isRecord(raw.outcome) ? raw.outcome : null\n return {\n index,\n raw,\n errors: validateRolloutLine(value),\n id: nonEmptyString(raw.rollout_id),\n parent: parentValue(raw),\n runId: nonEmptyString(raw.run_id),\n role: nonEmptyString(raw.role),\n messages: Array.isArray(raw.messages) ? raw.messages : null,\n profileId: policy === null ? null : nonEmptyString(policy.agent_profile_cell_id),\n completed:\n outcome !== null && typeof outcome.is_completed === 'boolean' ? outcome.is_completed : null,\n terminal: terminalValue(outcome),\n }\n}\n\nfunction metric(\n record: NodeRecord,\n keys: readonly string[],\n): { key: string; value: number } | null {\n const outcome = isRecord(record.raw.outcome) ? record.raw.outcome : null\n const metrics = outcome !== null && isRecord(outcome.metrics) ? outcome.metrics : null\n if (metrics === null) return null\n for (const key of keys) {\n const value = metrics[key]\n if (typeof value === 'number' && Number.isFinite(value)) return { key, value }\n }\n return null\n}\n\nfunction nodeEvidence(\n record: NodeRecord,\n path: string,\n value: unknown,\n): SupervisorRunIntegrityEvidence {\n const key = record.id ?? `index-${record.index}`\n return evidence(`nodes/${encodeURIComponent(key)}/${path}`, value)\n}\n\nfunction unavailableNodeChecks(record: NodeRecord): string[] {\n const checks: string[] = []\n if (record.id === null) checks.push('identity', 'root-membership', 'parent-link', 'cycle')\n if (record.parent === undefined) checks.push('parent-link', 'cycle')\n if (record.runId === null) checks.push('cross-run-parent')\n if (record.role === null) checks.push('root-role')\n if (!isRecord(record.raw.outcome)) checks.push('timing', 'terminal-state')\n return [...new Set(checks)]\n}\n\ninterface TreeIssueUncertainty {\n readonly unknownIdentityRows?: number\n readonly uncertainIds?: ReadonlySet<string>\n}\n\nexport function treeIssues(\n tree: SupervisorRunTree,\n uncertainty: TreeIssueUncertainty = {},\n): SupervisorRunIntegrityIssue[] {\n const out: SupervisorRunIntegrityIssue[] = []\n const records = (tree.nodes as readonly unknown[]).map(nodeRecord)\n const malformedSourceRows = tree.gaps\n .filter((gap) => gap.code === 'source-row-malformed')\n .reduce((count, gap) => count + (gap.count ?? 1), 0)\n\n for (const record of records) {\n if (record.errors.length === 0) continue\n out.push(\n issue({\n code: 'node-schema-invalid',\n area: 'capture-integrity',\n severity: 'high',\n subject: record.id ?? `node-${record.index}`,\n claim: 'A supervisor-tree node fails canonical rollout validation',\n detail: record.errors.join('; '),\n evidence: [evidence(`nodes/${record.index}/validation`, record.errors)],\n recommendedAction:\n 'Fix the producer so every node validates as the existing tangle.rollout.v1 shape before analysis.',\n metadata: { validation_errors: record.errors },\n }),\n )\n const unavailableChecks = unavailableNodeChecks(record)\n if (unavailableChecks.length === 0) continue\n out.push(\n issue({\n code: 'node-checks-unavailable',\n area: 'capture-integrity',\n severity: 'medium',\n subject: record.id ?? `node-${record.index}`,\n claim: 'Some integrity checks are unavailable for a malformed supervisor-tree node',\n detail: `Unavailable checks: ${unavailableChecks.join(', ')}.`,\n evidence: [evidence(`nodes/${record.index}/unavailable-checks`, unavailableChecks)],\n recommendedAction:\n 'Retain the named identity and relationship fields with their canonical types.',\n metadata: { assessment: 'unavailable', checks: unavailableChecks },\n }),\n )\n }\n\n const byId = new Map<string, NodeRecord[]>()\n for (const record of records) {\n if (record.id === null) continue\n const matches = byId.get(record.id) ?? []\n matches.push(record)\n byId.set(record.id, matches)\n }\n\n for (const [rolloutId, matches] of byId) {\n if (matches.length < 2) continue\n out.push(\n issue({\n code: 'duplicate-rollout-id',\n area: 'control-integrity',\n severity: 'critical',\n subject: rolloutId,\n claim: 'A rollout id is duplicated within one supervisor tree',\n detail: `${matches.length} nodes claim rollout_id ${JSON.stringify(rolloutId)}, so references are ambiguous.`,\n evidence: [\n evidence(`duplicates/${encodeURIComponent(rolloutId)}/count`, matches.length),\n ...matches.slice(0, MAX_EXAMPLES).map((record) =>\n evidence(`nodes/${record.index}/identity`, {\n rollout_id: record.id,\n parent_rollout_id: record.parent,\n role: record.role,\n }),\n ),\n ],\n recommendedAction: 'Give every invocation one stable rollout id and regenerate the tree.',\n }),\n )\n }\n\n const unknownIdentityRows =\n records.filter((record) => record.id === null).length +\n Math.max(malformedSourceRows, uncertainty.unknownIdentityRows ?? 0)\n const unique = records.filter(\n (record): record is NodeRecord & { readonly id: string } =>\n record.id !== null && byId.get(record.id)?.length === 1,\n )\n\n let root: NodeRecord | undefined\n if (tree.rootId === null) {\n out.push(\n issue({\n code: 'root-unavailable',\n area: 'capture-integrity',\n severity: 'high',\n subject: 'tree-root',\n claim: 'The supervisor-tree root is unavailable',\n detail: `rootId is null while ${records.length} node row(s) were captured.`,\n evidence: [evidence('rootId', null)],\n recommendedAction: 'Capture the root spawned event and preserve its rollout id as rootId.',\n metadata: { assessment: 'unavailable', node_rows: records.length },\n }),\n )\n } else {\n const rootRows = byId.get(tree.rootId) ?? []\n if (rootRows.length === 1) {\n root = rootRows[0]\n } else if (rootRows.length === 0 && unknownIdentityRows > 0) {\n out.push(\n issue({\n code: 'node-checks-unavailable',\n area: 'capture-integrity',\n severity: 'high',\n subject: tree.rootId,\n claim: 'Root membership is unavailable because a malformed node lost its rollout id',\n detail: `${unknownIdentityRows} malformed node row(s) have no usable rollout_id, so absence of root ${JSON.stringify(tree.rootId)} cannot be established.`,\n evidence: [evidence('rootId', tree.rootId)],\n recommendedAction: 'Retain rollout_id even when another node field fails validation.',\n metadata: { assessment: 'unavailable', checks: ['root-membership'] },\n }),\n )\n } else if (rootRows.length === 0) {\n out.push(\n issue({\n code: 'declared-root-missing',\n area: 'control-integrity',\n severity: 'critical',\n subject: tree.rootId,\n claim: 'The declared supervisor-tree root has no matching invocation node',\n detail: `rootId ${JSON.stringify(tree.rootId)} is absent from ${records.length} node row(s).`,\n evidence: [evidence('rootId', tree.rootId)],\n recommendedAction: 'Restore the root rollout row or correct rootId.',\n }),\n )\n }\n }\n\n if (root !== undefined) {\n if (root.parent !== undefined && root.parent !== null) {\n out.push(\n issue({\n code: 'root-has-parent',\n area: 'control-integrity',\n severity: 'critical',\n subject: root.id ?? tree.rootId ?? 'tree-root',\n claim: 'The declared supervisor-tree root has a parent',\n detail: `Root points to parent ${JSON.stringify(root.parent)}.`,\n evidence: [nodeEvidence(root, 'parent_rollout_id', root.parent)],\n recommendedAction: 'Record the root with parent_rollout_id null.',\n }),\n )\n }\n if (root.role !== null && root.role !== 'supervisor') {\n out.push(\n issue({\n code: 'root-role-invalid',\n area: 'control-integrity',\n severity: 'high',\n subject: root.id ?? tree.rootId ?? 'tree-root',\n claim: 'The declared supervisor-tree root is not labeled as a supervisor',\n detail: `Root has role ${JSON.stringify(root.role)}.`,\n evidence: [nodeEvidence(root, 'role', root.role)],\n recommendedAction:\n 'Preserve the root invocation role as supervisor when minting rollout rows.',\n }),\n )\n }\n }\n\n for (const record of unique) {\n if (record.parent === undefined) continue\n if (record.parent === null) {\n if (record.id !== tree.rootId) {\n out.push(\n issue({\n code: 'detached-node',\n area: 'control-integrity',\n severity: 'critical',\n subject: record.id,\n claim: 'A non-root invocation is recorded as a detached parentless root',\n detail: `Node ${JSON.stringify(record.id)} is parentless while rootId is ${JSON.stringify(tree.rootId)}.`,\n evidence: [\n nodeEvidence(record, 'parent_rollout_id', null),\n evidence('rootId', tree.rootId),\n ],\n recommendedAction:\n 'Attach the invocation to its spawning parent or record a separate run.',\n }),\n )\n }\n continue\n }\n\n const parentRows = byId.get(record.parent) ?? []\n if (parentRows.length === 0) {\n if (unknownIdentityRows > 0 || uncertainty.uncertainIds?.has(record.parent) === true) {\n out.push(\n issue({\n code: 'node-checks-unavailable',\n area: 'capture-integrity',\n severity: 'high',\n subject: record.id,\n claim: 'Parent membership is unavailable because a malformed node lost its rollout id',\n detail:\n uncertainty.uncertainIds?.has(record.parent) === true\n ? `Parent ${JSON.stringify(record.parent)} appears only in a malformed source row, so its absence cannot be established.`\n : `Parent ${JSON.stringify(record.parent)} cannot be matched while ${unknownIdentityRows} row(s) have no usable rollout_id.`,\n evidence: [nodeEvidence(record, 'parent_rollout_id', record.parent)],\n recommendedAction: 'Retain rollout_id on every row before assessing detached children.',\n metadata: { assessment: 'unavailable', checks: ['parent-membership'] },\n }),\n )\n } else {\n out.push(\n issue({\n code: 'parent-missing',\n area: 'control-integrity',\n severity: 'critical',\n subject: record.id,\n claim: 'An invocation points to a parent absent from the supervisor tree',\n detail: `Node ${JSON.stringify(record.id)} names missing parent ${JSON.stringify(record.parent)}.`,\n evidence: [nodeEvidence(record, 'parent_rollout_id', record.parent)],\n recommendedAction: 'Retain the parent invocation or remove the dangling edge.',\n }),\n )\n }\n continue\n }\n if (parentRows.length !== 1) continue\n const parent = parentRows[0] as NodeRecord\n\n if (record.runId !== null && parent.runId !== null && record.runId !== parent.runId) {\n out.push(\n issue({\n code: 'cross-run-parent',\n area: 'control-integrity',\n severity: 'critical',\n subject: record.id,\n claim: 'A parent-child edge crosses supervisor-run identities',\n detail: `Child run_id ${JSON.stringify(record.runId)} differs from parent run_id ${JSON.stringify(parent.runId)}.`,\n evidence: [\n nodeEvidence(record, 'run_id', record.runId),\n nodeEvidence(parent, 'run_id', parent.runId),\n ],\n recommendedAction:\n 'Keep one run_id across a supervision tree or remove the cross-run edge.',\n }),\n )\n }\n\n const childStart = metric(record, ['spawned_at', 'started_at'])\n const parentStart = metric(parent, ['spawned_at', 'started_at'])\n if (childStart !== null && parentStart !== null && childStart.value < parentStart.value) {\n out.push(\n issue({\n code: 'child-before-parent',\n area: 'control-integrity',\n severity: 'high',\n subject: record.id,\n claim: 'A child invocation is timestamped before its parent started',\n detail: `Child ${childStart.key} ${childStart.value} precedes parent ${parentStart.key} ${parentStart.value}.`,\n evidence: [\n nodeEvidence(record, `outcome.metrics.${childStart.key}`, childStart.value),\n nodeEvidence(parent, `outcome.metrics.${parentStart.key}`, parentStart.value),\n ],\n recommendedAction: 'Use one ordered clock for spawn events or retain clock metadata.',\n }),\n )\n }\n\n const parentClose = metric(parent, ['settled_at', 'completed_at', 'finished_at'])\n if (childStart !== null && parentClose !== null && childStart.value > parentClose.value) {\n out.push(\n issue({\n code: 'child-after-parent-close',\n area: 'control-integrity',\n severity: 'critical',\n subject: record.id,\n claim: 'A child invocation is timestamped after its parent closed',\n detail: `Child ${childStart.key} ${childStart.value} follows parent ${parentClose.key} ${parentClose.value}.`,\n evidence: [\n nodeEvidence(record, `outcome.metrics.${childStart.key}`, childStart.value),\n nodeEvidence(parent, `outcome.metrics.${parentClose.key}`, parentClose.value),\n ],\n recommendedAction:\n 'Correct the causal timestamps or attach the child to its actual spawner.',\n }),\n )\n }\n }\n\n for (const record of unique) {\n const start = metric(record, ['spawned_at', 'started_at'])\n const close = metric(record, ['settled_at', 'completed_at', 'finished_at'])\n if (start === null || close === null || close.value >= start.value) continue\n out.push(\n issue({\n code: 'close-before-start',\n area: 'control-integrity',\n severity: 'high',\n subject: record.id,\n claim: 'An invocation is timestamped as closing before it started',\n detail: `${start.key} is ${start.value} and ${close.key} is ${close.value}.`,\n evidence: [\n nodeEvidence(record, `outcome.metrics.${start.key}`, start.value),\n nodeEvidence(record, `outcome.metrics.${close.key}`, close.value),\n ],\n recommendedAction: 'Correct the event ordering or retain clock-domain metadata.',\n }),\n )\n }\n\n const emittedCycles = new Set<string>()\n const resolved = new Set<string>()\n for (const start of unique) {\n if (resolved.has(start.id)) continue\n const path: string[] = []\n const positions = new Map<string, number>()\n let current: string | null = start.id\n while (current !== null) {\n if (resolved.has(current)) break\n const position = positions.get(current)\n if (position !== undefined) {\n const cycle = path.slice(position)\n const key = [...cycle].sort().join('\\u0000')\n if (!emittedCycles.has(key)) {\n emittedCycles.add(key)\n out.push(\n issue({\n code: 'parent-cycle',\n area: 'control-integrity',\n severity: 'critical',\n subject: [...cycle].sort()[0] ?? 'cycle',\n claim: 'The supervisor tree contains a parent cycle',\n detail: `${cycle.join(' -> ')} -> ${cycle[0]}`,\n evidence: cycle.slice(0, MAX_EXAMPLES).flatMap((id) => {\n const rows = byId.get(id)\n const record = rows?.length === 1 ? rows[0] : undefined\n return record === undefined\n ? []\n : [nodeEvidence(record, 'parent_rollout_id', record.parent)]\n }),\n recommendedAction:\n 'Correct parent ids at ingestion; a cyclic graph is not a run tree.',\n }),\n )\n }\n break\n }\n positions.set(current, path.length)\n path.push(current)\n const rows = byId.get(current)\n if (rows?.length !== 1) break\n const parent = rows[0]?.parent\n if (parent === undefined) break\n current = parent\n }\n for (const id of path) resolved.add(id)\n }\n\n if (root?.completed === true) {\n const missingTerminal = unique.filter(\n (record) => record.id !== root?.id && record.terminal === false,\n )\n if (missingTerminal.length > 0) {\n out.push(\n issue({\n code: 'child-terminal-unavailable',\n area: 'capture-integrity',\n severity: 'high',\n subject: 'child-terminal-outcomes',\n claim: 'A completed supervisor run has children with no captured terminal outcome',\n detail: `${missingTerminal.length}/${Math.max(0, unique.length - 1)} child node(s) are neither completed, truncated, nor errored.`,\n evidence: [\n evidence('children/missing-terminal/count', missingTerminal.length),\n ...missingTerminal\n .slice(0, MAX_EXAMPLES)\n .map((record) => nodeEvidence(record, 'outcome', record.raw.outcome)),\n ],\n recommendedAction: 'Retain each child settlement or cancellation event.',\n metadata: { assessment: 'unavailable', unavailable_count: missingTerminal.length },\n }),\n )\n }\n }\n\n const missingTranscripts = records.filter((record) => record.messages?.length === 0)\n if (missingTranscripts.length > 0) {\n out.push(\n issue({\n code: 'transcript-unavailable',\n area: 'capture-integrity',\n severity: 'medium',\n subject: 'decision-transcripts',\n claim: 'Decision transcripts are unavailable for some supervisor-tree invocations',\n detail: `${missingTranscripts.length}/${records.length} node row(s) have messages: [].`,\n evidence: [\n evidence('capture/missing-transcripts/count', missingTranscripts.length),\n ...missingTranscripts\n .slice(0, MAX_EXAMPLES)\n .map((record) => nodeEvidence(record, 'messages', [])),\n ],\n recommendedAction: 'Hydrate canonical messages from the retained session transcript.',\n metadata: { assessment: 'unavailable', unavailable_count: missingTranscripts.length },\n }),\n )\n }\n\n const missingProfiles = records.filter((record) => record.profileId === null)\n if (missingProfiles.length > 0) {\n out.push(\n issue({\n code: 'profile-id-unavailable',\n area: 'capture-integrity',\n severity: 'medium',\n subject: 'agent-profile-identity',\n claim:\n 'Canonical agent-profile identity is unavailable for some supervisor-tree invocations',\n detail: `${missingProfiles.length}/${records.length} node row(s) omit policy.agent_profile_cell_id.`,\n evidence: [\n evidence('capture/missing-agent-profile-cell-id/count', missingProfiles.length),\n ...missingProfiles\n .slice(0, MAX_EXAMPLES)\n .map((record) => nodeEvidence(record, 'policy.agent_profile_cell_id', null)),\n ],\n recommendedAction:\n 'Record policy.agent_profile_cell_id on every invocation at dispatch time.',\n metadata: { assessment: 'unavailable', unavailable_count: missingProfiles.length },\n }),\n )\n }\n\n return out\n}\n","import type { SupervisorRunTree } from './types'\n\nexport const SUPERVISOR_RUN_INTEGRITY_SCHEMA = 'tangle.supervisor-run-integrity@1'\n\nexport type SupervisorRunIntegritySeverity = 'critical' | 'high' | 'medium' | 'low' | 'info'\n\nexport type SupervisorRunSourceOnlyCheckCode =\n | 'journal-event-cardinality'\n | 'worker-control-join'\n | 'steer-ack-correlation'\n\nexport type SupervisorRunIntegrityIssueCode =\n | 'source-checks-unavailable'\n | 'node-schema-invalid'\n | 'node-checks-unavailable'\n | 'root-unavailable'\n | 'duplicate-rollout-id'\n | 'declared-root-missing'\n | 'root-has-parent'\n | 'root-role-invalid'\n | 'detached-node'\n | 'parent-missing'\n | 'cross-run-parent'\n | 'child-before-parent'\n | 'child-after-parent-close'\n | 'close-before-start'\n | 'parent-cycle'\n | 'child-terminal-unavailable'\n | 'transcript-unavailable'\n | 'profile-id-unavailable'\n | 'source-row-malformed'\n | 'source-event-identity-unavailable'\n | 'duplicate-spawn'\n | 'orphan-terminal'\n | 'duplicate-terminal'\n | 'worker-controls-unavailable'\n | 'worker-control-join-unavailable'\n | 'steer-request-id-unavailable'\n | 'steer-ack-id-unavailable'\n | 'steer-ack-status-unavailable'\n | 'duplicate-steer-request-id'\n | 'missing-steer-ack'\n | 'duplicate-steer-ack'\n | 'unknown-steer-ack'\n | 'steer-not-delivered'\n\nexport interface SupervisorRunIntegrityEvidence {\n readonly path: string\n readonly value: unknown\n}\n\nexport interface SupervisorRunIntegrityIssue {\n readonly code: SupervisorRunIntegrityIssueCode\n readonly area: 'control-integrity' | 'capture-integrity'\n readonly severity: SupervisorRunIntegritySeverity\n readonly subject: string\n readonly claim: string\n readonly detail: string\n readonly evidence: readonly SupervisorRunIntegrityEvidence[]\n readonly recommendedAction: string\n readonly metadata?: Readonly<Record<string, unknown>>\n}\n\nexport interface SupervisorRunIntegrityReport {\n readonly schema: typeof SUPERVISOR_RUN_INTEGRITY_SCHEMA\n readonly runRef: string\n readonly input: 'sources' | 'tree'\n readonly tree: SupervisorRunTree\n readonly issues: readonly SupervisorRunIntegrityIssue[]\n}\n\nexport interface SupervisorRunIntegrityOptions {\n /** Pins rollout provenance when source input must be projected into a tree. */\n readonly capturedAt?: string\n}\n","import type { SupervisorRunNodeRole, SupervisorRunSources } from './types'\n\n// ---------------------------------------------------------------------------\n// Journal shapes — structurally parsed. The journal is the contract, not the type.\n// ---------------------------------------------------------------------------\n\ninterface JournalEvent {\n kind?: unknown\n id?: unknown\n parent?: unknown\n label?: unknown\n role?: unknown\n status?: unknown\n verdict?: unknown\n reason?: unknown\n seq?: unknown\n at?: unknown\n spend?: unknown\n spent?: unknown\n}\n\ninterface Tokens {\n input: number\n output: number\n cacheRead: number\n cacheWrite: number\n /** False when the event carried no cache counters at all — not \"zero cached\". */\n hasCache: boolean\n}\n\ninterface SpendLike {\n tokens: Tokens\n usd: number\n}\n\nexport function asRecord(v: unknown): Record<string, unknown> {\n return typeof v === 'object' && v !== null ? (v as Record<string, unknown>) : {}\n}\n\nfunction num(v: unknown): number {\n return typeof v === 'number' && Number.isFinite(v) ? v : 0\n}\n\nfunction readSpend(v: unknown): SpendLike {\n const rec = asRecord(v)\n const tok = asRecord(rec.tokens)\n const cacheRead = tok.cacheRead ?? tok.cache_read\n const cacheWrite = tok.cacheWrite ?? tok.cache_write\n return {\n tokens: {\n input: num(tok.input),\n output: num(tok.output),\n cacheRead: num(cacheRead),\n cacheWrite: num(cacheWrite),\n hasCache: cacheRead !== undefined || cacheWrite !== undefined,\n },\n usd: num(rec.usd),\n }\n}\n\nexport function parseJsonl(text: string | null): Record<string, unknown>[] {\n return parseJsonlWithDiagnostics(text).rows\n}\n\ninterface ParsedJsonl {\n readonly rows: Record<string, unknown>[]\n readonly invalidRows: number\n}\n\nfunction parseJsonlWithDiagnostics(text: string | null): ParsedJsonl {\n if (text === null) return { rows: [], invalidRows: 0 }\n const out: Record<string, unknown>[] = []\n let invalidRows = 0\n for (const line of text.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed) continue\n try {\n const parsed: unknown = JSON.parse(trimmed)\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n out.push(parsed as Record<string, unknown>)\n } else {\n invalidRows += 1\n }\n } catch {\n invalidRows += 1\n }\n }\n return { rows: out, invalidRows }\n}\n\nexport function parseJson(text: string | null): Record<string, unknown> | null {\n if (text === null) return null\n try {\n const parsed: unknown = JSON.parse(text)\n return typeof parsed === 'object' && parsed !== null\n ? (parsed as Record<string, unknown>)\n : null\n } catch {\n return null\n }\n}\n\nfunction ms(at: unknown): number | null {\n if (typeof at !== 'string') return null\n const t = Date.parse(at)\n return Number.isFinite(t) ? t : null\n}\n\n// ---------------------------------------------------------------------------\n// The supervision tree, as parsed from the journal event stream.\n// ---------------------------------------------------------------------------\n\nexport interface SpawnRow {\n /** Zero-based row among parsed journal objects. */\n sourceRow: number\n id: string\n parent: string | null\n label: string\n role: SupervisorRunNodeRole\n at: number | null\n /** False when identity, parentage, label, or role was malformed. */\n valid: boolean\n invalidFields: readonly string[]\n}\n\nexport interface CloseRow {\n id: string\n kind: 'settled' | 'cancelled'\n status: string | null\n /** String verdict from legacy journals, or valid/invalid for a structured verdict. */\n verdict: string | null\n /** Structured verdict validity, when recorded. */\n valid: boolean | null\n /** Structured verdict score, preserved without boolean coercion. */\n score: number | null\n /** The verdict exactly as the journal carried it. */\n rawVerdict: unknown | null\n at: number | null\n spend: SpendLike\n /** False when the close event carried no spend object — not \"spent nothing\". */\n hasSpend: boolean\n}\n\nexport interface WorkerLogFacts {\n /** Position in `SupervisorRunSources.workers`, retained for exact evidence paths. */\n sourceIndex: number\n workerId: string | null\n label: string\n /** `false` means the artifact was missing; a captured empty artifact is `true`. */\n inboxCaptured: boolean\n eventsCaptured: boolean\n inboxInvalidRows: number\n eventsInvalidRows: number\n started: number | null\n /** True once a `finished` event was seen — independent of whether its `at` parsed. */\n finished: boolean\n finishedAt: number | null\n passed: boolean | null\n /** Numeric score exactly as the finished event recorded it. */\n score: number | null\n /** `patchBytes` as reported by the finished event (not the patch file's size). */\n finishedPatchBytes: number | null\n evidenceBytes: number\n /** Unique queued request ids, or null when exact accounting is unavailable. */\n steersQueued: number | null\n /** Unique matched request ids acknowledged as delivered, or null when unavailable. */\n steersDelivered: number | null\n steersQueuedUnavailable: string | null\n steersDeliveredUnavailable: string | null\n questions: number\n steerRequests: SteerRequestFact[]\n steerAcknowledgements: SteerAcknowledgementFact[]\n}\n\nexport interface SteerRequestFact {\n /** Durable inbox request id; null when the row did not retain one. */\n requestId: string | null\n row: number\n}\n\nexport interface SteerAcknowledgementFact {\n /** Worker event request id; null when the event cannot be correlated. */\n requestId: string | null\n /** `null` means the acknowledgement omitted delivery status. */\n delivered: boolean | null\n row: number\n}\n\n/**\n * The tree + timeline the report is computed from, exposed because the rollout-row\n * minter needs exactly the same parse (one parser, two consumers).\n */\nexport interface SupervisorTreeFacts {\n readonly rootId: string | null\n readonly spawns: readonly SpawnRow[]\n readonly closes: readonly CloseRow[]\n readonly workerSpawns: readonly SpawnRow[]\n readonly workerCloses: readonly CloseRow[]\n readonly brain: {\n tokensIn: number\n tokensOut: number\n cacheRead: number\n cacheWrite: number\n /** False when no metered event carried cache counters — not \"nothing cached\". */\n hasCache: boolean\n usd: number\n meteredCount: number\n }\n readonly workerLogs: ReadonlyMap<string, WorkerLogFacts>\n /** Every worker source row, including duplicate identities that a map cannot retain. */\n readonly workerLogRows: readonly WorkerLogFacts[]\n /** Every non-empty journal line, whatever shape it turned out to have. */\n readonly journalRows: number\n /**\n * Journal lines this parser could not interpret at all: invalid JSON, non-objects, and\n * JSON objects carrying no record shape it recognizes.\n *\n * This count is what separates \"the run was empty\" from \"the input was unreadable\".\n * Zero spawns with zero invalid rows is a positive claim that nothing happened; it must\n * only ever be made about bytes the parser actually understood.\n */\n readonly journalInvalidRows: number\n /** The `journalInvalidRows` subset that was not valid JSON, or not a JSON object. */\n readonly journalMalformedJsonRows: number\n /**\n * Records recognized but deliberately not folded into the tree, counted by kind — the\n * runtime envelope's `begin` header and the `waiting` / `woken` wait-node events. Kept\n * separate from `journalInvalidRows` because these rows were understood, not rejected.\n */\n readonly journalIgnoredRowsByKind: Readonly<Record<string, number>>\n /** Which dialect(s) the journal's rows were actually written in. */\n readonly journalDialect: SupervisorJournalDialect\n /** Parsed once with the journal and worker artifacts. */\n readonly state: Record<string, unknown> | null\n readonly startedAt: number | null\n readonly completedAt: number | null\n}\n\ninterface VerdictFacts {\n label: string | null\n valid: boolean | null\n score: number | null\n raw: unknown | null\n}\n\nfunction readVerdict(v: unknown): VerdictFacts {\n if (typeof v === 'string') return { label: v, valid: null, score: null, raw: v }\n if (typeof v !== 'object' || v === null) {\n return { label: null, valid: null, score: null, raw: null }\n }\n const rec = v as Record<string, unknown>\n const valid = typeof rec.valid === 'boolean' ? rec.valid : null\n return {\n label: valid === null ? null : valid ? 'valid' : 'invalid',\n valid,\n score: typeof rec.score === 'number' && Number.isFinite(rec.score) ? rec.score : null,\n raw: v,\n }\n}\n\nexport function workerSourceKey(\n worker: NonNullable<SupervisorRunSources['workers']>[number],\n): string {\n return worker.workerId ?? worker.label\n}\n\n// ---------------------------------------------------------------------------\n// Journal dialects — the two shapes a supervision journal is actually written in.\n// ---------------------------------------------------------------------------\n\n/**\n * How a journal's rows were shaped on disk.\n *\n * `flat` — one event object per line (`{kind:'spawned', id, ...}`). The loops\n * supervisor writes this, and `readClaudeCodeSupervisorRun` synthesizes it.\n *\n * `runtime-envelope` — the records `agent-runtime`'s `FileSpawnJournal` writes:\n * a `{kind:'begin', root, at}` header followed by `{kind:'event', root, event}`\n * envelopes (`agent-runtime/src/durable/spawn-journal.ts`, `appendRecord`). It is\n * the layout `createFileRunContext(dir)` produces at `<dir>/spawn-journal.jsonl`.\n * This dialect is READ, not tolerated: agent-runtime is the writer, so a reader\n * that could not interpret it was the defect, and `journalDialect` records which\n * shape the bytes actually had so an unexpected one is never invisible.\n *\n * `mixed` — rows of both shapes in one file. `none` — no interpretable row at all.\n */\nexport type SupervisorJournalDialect = 'none' | 'flat' | 'runtime-envelope' | 'mixed'\n\ntype JournalRowDialect = 'flat' | 'runtime-envelope'\n\n/** Event kinds this parser folds into the tree. */\nconst TREE_EVENT_KINDS = ['spawned', 'settled', 'cancelled', 'metered'] as const\ntype TreeEventKind = (typeof TREE_EVENT_KINDS)[number]\n\n/**\n * Event kinds `agent-runtime` journals that this parser recognizes but does not model as\n * tree nodes: `waiting` arms a wait node and `woken` settles it. They are counted by kind\n * rather than dropped, so \"understood, not modeled\" can never be mistaken for \"absent\".\n */\nconst UNMODELLED_EVENT_KINDS: readonly string[] = ['waiting', 'woken']\n\nfunction treeEventKind(value: unknown): TreeEventKind | null {\n return (TREE_EVENT_KINDS as readonly unknown[]).includes(value) ? (value as TreeEventKind) : null\n}\n\ntype JournalRowReading =\n | {\n outcome: 'event'\n dialect: JournalRowDialect\n kind: TreeEventKind\n event: JournalEvent\n }\n | { outcome: 'ignored'; dialect: JournalRowDialect; kind: string }\n | { outcome: 'unreadable' }\n\n/**\n * Classify one parsed journal row. Every row lands in exactly one outcome — interpreted,\n * recognized-but-not-modeled, or unreadable — because a row that falls through silently is\n * how a run with events reads as a run with none.\n */\nfunction readJournalRow(row: Record<string, unknown>): JournalRowReading {\n const kind = row.kind\n if (typeof kind !== 'string') return { outcome: 'unreadable' }\n\n // agent-runtime's FileSpawnJournal record header. It carries no event.\n if (kind === 'begin' && typeof row.root === 'string') {\n return { outcome: 'ignored', dialect: 'runtime-envelope', kind: 'begin' }\n }\n if (kind === 'event') {\n const inner = row.event\n if (typeof inner !== 'object' || inner === null || Array.isArray(inner)) {\n return { outcome: 'unreadable' }\n }\n const innerKind = (inner as Record<string, unknown>).kind\n if (typeof innerKind !== 'string') return { outcome: 'unreadable' }\n const tree = treeEventKind(innerKind)\n if (tree !== null) {\n return {\n outcome: 'event',\n dialect: 'runtime-envelope',\n kind: tree,\n event: inner as JournalEvent,\n }\n }\n // The envelope proves this IS a journaled event, so an unmodelled kind is recorded by\n // name rather than called unreadable — the caller sees exactly what went uncounted.\n return { outcome: 'ignored', dialect: 'runtime-envelope', kind: innerKind }\n }\n\n const tree = treeEventKind(kind)\n if (tree !== null) {\n return { outcome: 'event', dialect: 'flat', kind: tree, event: row as JournalEvent }\n }\n if (UNMODELLED_EVENT_KINDS.includes(kind)) {\n return { outcome: 'ignored', dialect: 'flat', kind }\n }\n // A bare object with an unknown `kind` could be any record at all — unlike the envelope\n // case there is no evidence it is a journal event, so it counts as unreadable (fail closed).\n return { outcome: 'unreadable' }\n}\n\nfunction summarizeDialect(seen: ReadonlySet<JournalRowDialect>): SupervisorJournalDialect {\n if (seen.size === 0) return 'none'\n if (seen.size > 1) return 'mixed'\n return seen.has('runtime-envelope') ? 'runtime-envelope' : 'flat'\n}\n\nexport function parseSupervisorTree(src: SupervisorRunSources): SupervisorTreeFacts {\n const parsedJournal = parseJsonlWithDiagnostics(src.journal)\n const events = parsedJournal.rows\n const state = parseJson(src.state)\n\n const spawns: SpawnRow[] = []\n const closes: CloseRow[] = []\n let brainIn = 0\n let brainOut = 0\n let brainCacheRead = 0\n let brainCacheWrite = 0\n let brainHasCache = false\n let brainUsd = 0\n let meteredCount = 0\n let rootId: string | null = null\n let unreadableRows = 0\n const ignoredByKind = new Map<string, number>()\n const dialectsSeen = new Set<JournalRowDialect>()\n for (const [sourceRow, row] of events.entries()) {\n const reading = readJournalRow(row)\n if (reading.outcome === 'unreadable') {\n unreadableRows += 1\n continue\n }\n dialectsSeen.add(reading.dialect)\n if (reading.outcome === 'ignored') {\n ignoredByKind.set(reading.kind, (ignoredByKind.get(reading.kind) ?? 0) + 1)\n continue\n }\n const { kind, event: ev } = reading\n const id = typeof ev.id === 'string' ? ev.id : ''\n if (kind === 'spawned') {\n const parent = typeof ev.parent === 'string' && ev.parent.length > 0 ? ev.parent : null\n const label = typeof ev.label === 'string' ? ev.label : ''\n const invalidFields: string[] = []\n if (id.length === 0) invalidFields.push('id')\n const parentOmittedForFirstRoot = ev.parent === undefined && rootId === null\n if (\n ev.parent !== null &&\n !parentOmittedForFirstRoot &&\n !(typeof ev.parent === 'string' && ev.parent.length > 0)\n ) {\n invalidFields.push('parent')\n }\n if (label.length === 0) invalidFields.push('label')\n if (ev.role !== undefined && ev.role !== 'supervisor' && ev.role !== 'worker') {\n invalidFields.push('role')\n }\n const role: SupervisorRunNodeRole =\n ev.role === 'supervisor' || ev.role === 'worker'\n ? ev.role\n : parent === null\n ? 'supervisor'\n : 'worker'\n const valid = invalidFields.length === 0\n if (valid && parent === null && rootId === null) rootId = id\n spawns.push({\n sourceRow,\n id,\n parent,\n label,\n role,\n at: ms(ev.at),\n valid,\n invalidFields,\n })\n } else if (kind === 'settled') {\n const verdict = readVerdict(ev.verdict)\n closes.push({\n id,\n kind: 'settled',\n status: typeof ev.status === 'string' ? ev.status : null,\n verdict: verdict.label,\n valid: verdict.valid,\n score: verdict.score,\n rawVerdict: verdict.raw,\n at: ms(ev.at),\n spend: readSpend(ev.spent),\n hasSpend: asRecord(ev.spent).tokens !== undefined,\n })\n } else if (kind === 'cancelled') {\n closes.push({\n id,\n kind: 'cancelled',\n status: 'cancelled',\n verdict: typeof ev.reason === 'string' ? ev.reason : null,\n valid: null,\n score: null,\n rawVerdict: typeof ev.reason === 'string' ? ev.reason : null,\n at: ms(ev.at),\n spend: {\n tokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, hasCache: false },\n usd: 0,\n },\n hasSpend: false,\n })\n } else if (kind === 'metered') {\n const s = readSpend(ev.spend)\n brainIn += s.tokens.input\n brainOut += s.tokens.output\n brainCacheRead += s.tokens.cacheRead\n brainCacheWrite += s.tokens.cacheWrite\n brainHasCache = brainHasCache || s.tokens.hasCache\n brainUsd += s.usd\n meteredCount += 1\n } else {\n // `TREE_EVENT_KINDS` and these branches are one contract: adding a kind to the set\n // without a branch here would silently drop its rows, which is the defect this\n // accounting exists to prevent. The compiler refuses the omission.\n const unhandled: never = kind\n throw new Error(`unhandled journal event kind ${JSON.stringify(unhandled)}`)\n }\n }\n\n const workerSpawns = spawns.filter((s) => s.valid && s.id !== rootId)\n const workerIds = new Set(workerSpawns.map((s) => s.id))\n const workerCloses = closes.filter((c) => workerIds.has(c.id))\n\n const workerLogs = new Map<string, WorkerLogFacts>()\n const workerLogRows: WorkerLogFacts[] = []\n for (const [sourceIndex, w] of (src.workers ?? []).entries()) {\n const facts: WorkerLogFacts = {\n sourceIndex,\n workerId: w.workerId ?? null,\n label: w.label,\n inboxCaptured: w.inbox !== null,\n eventsCaptured: w.events !== null,\n inboxInvalidRows: 0,\n eventsInvalidRows: 0,\n started: null,\n finished: false,\n finishedAt: null,\n passed: null,\n score: null,\n finishedPatchBytes: null,\n evidenceBytes: 0,\n steersQueued: null,\n steersDelivered: null,\n steersQueuedUnavailable: null,\n steersDeliveredUnavailable: null,\n questions: 0,\n steerRequests: [],\n steerAcknowledgements: [],\n }\n const parsedInbox = parseJsonlWithDiagnostics(w.inbox)\n const parsedEvents = parseJsonlWithDiagnostics(w.events)\n facts.inboxInvalidRows = parsedInbox.invalidRows\n facts.eventsInvalidRows = parsedEvents.invalidRows\n for (const [row, req] of parsedInbox.rows.entries()) {\n if (typeof req.message !== 'string' || req.message.trim().length === 0) continue\n facts.steerRequests.push({\n requestId: typeof req.id === 'string' && req.id.length > 0 ? req.id : null,\n row,\n })\n }\n for (const [row, ev] of parsedEvents.rows.entries()) {\n const kind = ev.kind\n if (kind === 'message') {\n if (ev.direction === 'up') {\n facts.questions += 1\n continue\n }\n facts.steerAcknowledgements.push({\n requestId:\n typeof ev.requestId === 'string' && ev.requestId.length > 0 ? ev.requestId : null,\n delivered: typeof ev.delivered === 'boolean' ? ev.delivered : null,\n row,\n })\n } else if (kind === 'started') {\n facts.started = ms(ev.at)\n } else if (kind === 'finished') {\n facts.finished = true\n facts.finishedAt = ms(ev.at)\n facts.passed = typeof ev.passed === 'boolean' ? ev.passed : null\n facts.score = typeof ev.score === 'number' && Number.isFinite(ev.score) ? ev.score : null\n facts.finishedPatchBytes = typeof ev.patchBytes === 'number' ? ev.patchBytes : null\n facts.evidenceBytes = typeof ev.evidence === 'string' ? ev.evidence.length : 0\n }\n }\n const requestsById = new Map<string, number>()\n for (const request of facts.steerRequests) {\n if (request.requestId === null) continue\n requestsById.set(request.requestId, (requestsById.get(request.requestId) ?? 0) + 1)\n }\n const acknowledgementsById = new Map<string, SteerAcknowledgementFact[]>()\n for (const acknowledgement of facts.steerAcknowledgements) {\n if (acknowledgement.requestId === null) continue\n const matches = acknowledgementsById.get(acknowledgement.requestId) ?? []\n matches.push(acknowledgement)\n acknowledgementsById.set(acknowledgement.requestId, matches)\n }\n const queueProblems: string[] = []\n if (!facts.inboxCaptured) queueProblems.push('inbox absent')\n if (!facts.eventsCaptured) queueProblems.push('events absent')\n if (facts.inboxInvalidRows > 0) queueProblems.push('inbox contains malformed rows')\n if (facts.eventsInvalidRows > 0) queueProblems.push('events contain malformed rows')\n if (facts.steerRequests.some((request) => request.requestId === null)) {\n queueProblems.push('queued request id missing')\n }\n if ([...requestsById.values()].some((count) => count > 1)) {\n queueProblems.push('queued request id duplicated')\n }\n if (facts.steerAcknowledgements.some((acknowledgement) => acknowledgement.requestId === null)) {\n queueProblems.push('acknowledgement request id missing')\n }\n if ([...acknowledgementsById.keys()].some((id) => !requestsById.has(id))) {\n queueProblems.push('acknowledgement has no queued request')\n }\n if (queueProblems.length === 0) {\n facts.steersQueued = requestsById.size\n } else {\n facts.steersQueuedUnavailable = [...new Set(queueProblems)].join('; ')\n }\n\n const deliveryProblems = [...queueProblems]\n if ([...acknowledgementsById.values()].some((rows) => rows.length > 1)) {\n deliveryProblems.push('acknowledgement request id duplicated')\n }\n if (facts.steerAcknowledgements.some((acknowledgement) => acknowledgement.delivered === null)) {\n deliveryProblems.push('acknowledgement delivery status missing')\n }\n if (deliveryProblems.length === 0) {\n facts.steersDelivered = [...requestsById.keys()].filter((id) => {\n const acknowledgement = acknowledgementsById.get(id)\n return acknowledgement?.length === 1 && acknowledgement[0]?.delivered === true\n }).length\n } else {\n facts.steersDeliveredUnavailable = [...new Set(deliveryProblems)].join('; ')\n }\n workerLogRows.push(facts)\n workerLogs.set(workerSourceKey(w), facts)\n }\n\n const startedAt = ms(state?.startedAt) ?? spawns[0]?.at ?? null\n const completedAt =\n ms(state?.completedAt) ??\n [...spawns.map((s) => s.at), ...closes.map((c) => c.at)].reduce<number | null>(\n (acc, t) => (t === null ? acc : acc === null ? t : Math.max(acc, t)),\n null,\n )\n\n return {\n rootId,\n spawns,\n closes,\n workerSpawns,\n workerCloses,\n brain: {\n tokensIn: brainIn,\n tokensOut: brainOut,\n cacheRead: brainCacheRead,\n cacheWrite: brainCacheWrite,\n hasCache: brainHasCache,\n usd: brainUsd,\n meteredCount,\n },\n workerLogs,\n workerLogRows,\n journalRows: events.length + parsedJournal.invalidRows,\n journalInvalidRows: parsedJournal.invalidRows + unreadableRows,\n journalMalformedJsonRows: parsedJournal.invalidRows,\n journalIgnoredRowsByKind: Object.fromEntries(ignoredByKind),\n journalDialect: summarizeDialect(dialectsSeen),\n state,\n startedAt,\n completedAt,\n }\n}\n","/**\n * The supervision tree as `tangle.rollout.v1` rows.\n *\n * A supervisor run IS a tree of rollouts, so its nodes are not a new shape:\n * the root becomes one `RolloutLine` with `role: 'supervisor'`, and every\n * spawned invocation keeps its explicit supervisor/worker role with\n * `parent_rollout_id` pointing at its spawner. The rows append to the same\n * ledger as solo-agent rollouts and join to them with the same keys.\n *\n * What the journal CANNOT supply is the transcript: a worker's messages live\n * in its harness store (opencode sqlite, Claude Code jsonl), which the\n * `src/rollout/readers/*` intake readers own. Rows minted here are therefore\n * GAP lines (`messages: []`, `provenance.gap` set) carrying identity,\n * structure, outcome and cost; hydrating them with messages is the readers'\n * job, keyed on `artifacts.transcript_ref`.\n *\n * Timing lives in `outcome.metrics` (`spawned_at` / `settled_at` / `wall_ms`)\n * rather than a schema field: `tangle.rollout.v1` describes ONE invocation,\n * and the inter-invocation event timeline — which is what waves, concurrency,\n * idle and utilization are computed from — is a property of the journal, not\n * of any single row. The analyzer reads that timeline; these rows carry the\n * per-node facts.\n */\n\nimport { unscreenedRewardFields } from '../rollout/reward'\nimport {\n isRolloutLine,\n ROLLOUT_SCHEMA,\n type RolloutLine,\n type RolloutSplit,\n} from '../rollout/schema'\nimport { asRecord, parseJson, parseSupervisorTree, type SupervisorTreeFacts } from './source-facts'\nimport type {\n SupervisorRunSources,\n SupervisorRunTree,\n SupervisorRunTreeGap,\n WorkerLogSource,\n} from './types'\n\nexport interface SupervisorRolloutOptions {\n /** Benchmark/suite id for `task.suite`. Defaults to `'supervisor-run'`. */\n readonly suite?: string\n /** `task.split`. Defaults to `'search'` (the trainable pool). */\n readonly split?: RolloutSplit\n /** Replicate index. Defaults to 0. */\n readonly rep?: number\n /** Sampling seed the campaign pinned. Defaults to null (not recorded). */\n readonly seed?: number | null\n /** `run_id` for every node. Defaults to the supervisor root id, else `runRef`. */\n readonly runId?: string\n /** Harness that drove the supervisor. */\n readonly supervisorHarness?: string | null\n /** Harness that drove the workers. */\n readonly workerHarness?: string | null\n /** Model the supervisor ran on. */\n readonly supervisorModel?: string | null\n /** Model the workers ran on. */\n readonly workerModel?: string | null\n readonly experimentId?: string | null\n readonly candidateId?: string | null\n readonly generation?: number | null\n readonly candidateIndex?: number | null\n /** Pins `provenance.captured_at`; defaults to now. */\n readonly capturedAt?: string\n}\n\nconst EMPTY_COST = {\n usd: null,\n tokens_in: null,\n tokens_out: null,\n tokens_reasoning: null,\n cache_read: null,\n cache_write: null,\n wall_s: null,\n} as const\n\nfunction hasWorkerId(\n worker: WorkerLogSource,\n): worker is WorkerLogSource & { readonly workerId: string } {\n return worker.workerId !== undefined\n}\n\n/**\n * Mint the supervision tree as rollout rows. Returns the rows plus the gaps\n * that made any of them incomplete — same unavailable-vs-zero discipline as\n * the report: a row with no transcript says WHY, it never pretends to be empty.\n */\nexport function supervisorRunRolloutLines(\n src: SupervisorRunSources,\n opts: SupervisorRolloutOptions = {},\n): SupervisorRunTree {\n return supervisorRunRolloutLinesFromFacts(src, parseSupervisorTree(src), opts)\n}\n\n/** Mint rollout rows from an already parsed source without reading its JSONL again. */\nexport function supervisorRunRolloutLinesFromFacts(\n src: SupervisorRunSources,\n tree: SupervisorTreeFacts,\n opts: SupervisorRolloutOptions = {},\n): SupervisorRunTree {\n const gaps: SupervisorRunTreeGap[] = []\n if (src.journal === null) {\n gaps.push({\n code: 'journal-unavailable',\n message: `${src.supRunDir === null ? 'no supervisor run dir' : 'journal absent'}; no nodes recoverable`,\n })\n return { rootId: null, nodes: [], gaps }\n }\n // `journalInvalidRows` covers rows the parser could not interpret at all, including JSON\n // objects in a shape it does not recognize — so a journal it read but understood none of\n // reports an explicit gap instead of an empty tree.\n const malformedSourceRows =\n tree.journalInvalidRows + tree.spawns.filter((spawn) => !spawn.valid).length\n if (malformedSourceRows > 0) {\n gaps.push({\n code: 'source-row-malformed',\n message: `${malformedSourceRows} of ${tree.journalRows} journal row(s) were unusable and excluded from the tree`,\n count: malformedSourceRows,\n })\n }\n\n const state = tree.state\n const result = parseJson(src.result)\n const judge = parseJson(src.judge)\n const stateResult = asRecord(state?.result)\n\n const rootId = tree.rootId\n const runId = opts.runId ?? rootId ?? src.runRef\n const suite = opts.suite ?? 'supervisor-run'\n const instanceId = src.instanceId ?? src.runRef\n const split: RolloutSplit = opts.split ?? 'search'\n const capturedAt = opts.capturedAt ?? new Date().toISOString()\n\n const base = {\n schema: ROLLOUT_SCHEMA,\n run_id: runId,\n experiment_id: opts.experimentId ?? null,\n candidate_id: opts.candidateId ?? null,\n generation: opts.generation ?? null,\n candidate_index: opts.candidateIndex ?? null,\n task: {\n suite,\n instance_id: instanceId,\n split,\n seed: opts.seed ?? null,\n rep: opts.rep ?? 0,\n },\n messages: [] as RolloutLine['messages'],\n tool_defs: [] as RolloutLine['tool_defs'],\n } satisfies Partial<RolloutLine> & Record<string, unknown>\n\n const nodes: RolloutLine[] = []\n\n // ── root: the supervisor invocation ────────────────────────────────────\n if (rootId !== null) {\n const rootSpawn = tree.spawns.find((spawn) => spawn.valid && spawn.id === rootId)\n const judgeResolved = typeof judge?.resolved === 'boolean' ? judge.resolved : null\n const judgeScore = typeof judge?.score === 'number' ? judge.score : null\n const reward = judgeScore ?? (judgeResolved === null ? null : judgeResolved ? 1 : 0)\n if (reward === null) {\n gaps.push({\n code: 'root-reward-unavailable',\n message: 'no judge verdict for this run',\n nodeId: rootId,\n })\n }\n const wallMs =\n tree.startedAt !== null && tree.completedAt !== null && tree.completedAt >= tree.startedAt\n ? tree.completedAt - tree.startedAt\n : null\n nodes.push({\n ...base,\n rollout_id: rootId,\n parent_rollout_id: null,\n role: rootSpawn?.role ?? 'supervisor',\n policy: {\n harness: opts.supervisorHarness ?? null,\n harness_version: null,\n model: opts.supervisorModel ?? null,\n provider: null,\n profile_commit: null,\n sampling: null,\n },\n outcome: {\n // `reward` and `realness_gated` are written by one call, in the module\n // that owns the gate. This is the SECOND producer of rollout rewards —\n // the judge verdict in the supervision run dir, not `mintRolloutRows` —\n // and it wrote `reward` by hand while never stating the flag, so\n // `isLineRealnessGated` was structurally false for every supervisor and\n // worker row ever emitted here. `unscreenedRewardFields` is the honest\n // name for what this producer can claim: a supervision journal carries\n // no `RunRecord.outcome.realness`, so no authenticity gate has run on\n // this score, and `realness_gated: false` states that rather than\n // implying it by omission. These rows stay plain `RolloutLine`s, so a\n // caller feeding them to a training exporter must `assertMinted` first.\n ...unscreenedRewardFields(reward),\n reward_source: src.judgeSource,\n verdict: judge ?? null,\n metrics: {\n arm: src.arm,\n sup_status: typeof state?.status === 'string' ? state.status : null,\n sup_verdict: typeof state?.verdict === 'string' ? state.verdict : null,\n delivered: typeof stateResult.delivered === 'boolean' ? stateResult.delivered : null,\n verify_pass: typeof result?.verify_pass === 'boolean' ? result.verify_pass : null,\n started_at: tree.startedAt,\n completed_at: tree.completedAt,\n workers_spawned: tree.workerSpawns.length,\n brain_metered_events: tree.brain.meteredCount,\n },\n is_completed: state?.status === 'completed',\n is_truncated: false,\n error: null,\n realness_gated: false,\n },\n cost: {\n ...EMPTY_COST,\n usd:\n src.limits.spendUsd !== null\n ? null\n : typeof stateResult.spentUsd === 'number'\n ? stateResult.spentUsd\n : tree.brain.usd,\n tokens_in: src.limits.managerTokens === null ? tree.brain.tokensIn : null,\n tokens_out: src.limits.managerTokens === null ? tree.brain.tokensOut : null,\n cache_read:\n src.limits.managerTokens === null && tree.brain.hasCache ? tree.brain.cacheRead : null,\n cache_write:\n src.limits.managerTokens === null && tree.brain.hasCache ? tree.brain.cacheWrite : null,\n wall_s: wallMs === null ? null : wallMs / 1000,\n },\n artifacts: {\n patch_path: typeof result?.patchPath === 'string' ? result.patchPath : null,\n run_dir: src.supRunDir,\n transcript_ref:\n src.rootTranscriptRef !== undefined\n ? src.rootTranscriptRef\n : src.supRunDir === null\n ? null\n : `${src.supRunDir}/journal.jsonl`,\n },\n provenance: {\n captured_at: capturedAt,\n capture: 'backfill',\n gap: 'supervision journal carries structure and spend, not the brain transcript',\n },\n })\n } else {\n gaps.push({\n code: 'root-spawn-unavailable',\n message: 'no parentless spawned event in the journal',\n })\n }\n\n // ── workers: one node per spawn, keyed to its spawner ───────────────────\n const closeById = new Map(tree.closes.map((c) => [c.id, c]))\n const sourceById = new Map(\n (src.workers ?? []).filter(hasWorkerId).map((worker) => [worker.workerId, worker]),\n )\n const fallbackSourceByLabel = new Map(\n (src.workers ?? [])\n .filter((worker) => worker.workerId === undefined)\n .map((worker) => [worker.label, worker]),\n )\n // Stable ids are authoritative. Labels are a compatibility join for stores\n // that predate workerId and are only safe when the store keeps them unique.\n for (const spawn of tree.workerSpawns) {\n const close = closeById.get(spawn.id) ?? null\n const workerSource = sourceById.get(spawn.id) ?? fallbackSourceByLabel.get(spawn.label) ?? null\n const facts =\n tree.workerLogs.get(workerSource?.workerId ?? workerSource?.label ?? spawn.label) ?? null\n const wallMs =\n facts?.started != null && facts.finishedAt != null ? facts.finishedAt - facts.started : null\n const score = close?.score ?? facts?.score ?? null\n const passed = close?.valid ?? facts?.passed ?? null\n const reward = score ?? (passed === null ? null : passed ? 1 : 0)\n if (reward === null) {\n gaps.push({\n code: 'child-reward-unavailable',\n message: `child ${JSON.stringify(spawn.label)} has no verify verdict`,\n nodeId: spawn.id,\n })\n }\n const isSupervisor = spawn.role === 'supervisor'\n nodes.push({\n ...base,\n rollout_id: spawn.id,\n parent_rollout_id: spawn.parent,\n role: spawn.role,\n policy: {\n harness: isSupervisor ? (opts.supervisorHarness ?? null) : (opts.workerHarness ?? null),\n harness_version: null,\n model: isSupervisor ? (opts.supervisorModel ?? null) : (opts.workerModel ?? null),\n provider: null,\n profile_commit: null,\n sampling: null,\n },\n outcome: {\n // Same producer, same claim: a child reward is a self-verify verdict\n // from the journal that no realness gate has seen.\n ...unscreenedRewardFields(reward),\n reward_source:\n reward === null ? null : score === null ? 'worker-self-verify' : 'worker-verdict-score',\n verdict:\n close === null\n ? null\n : {\n kind: close.kind,\n status: close.status,\n verdict: close.rawVerdict,\n valid: close.valid,\n score: close.score,\n },\n metrics: {\n label: spawn.label,\n spawned_at: spawn.at,\n settled_at: close?.at ?? null,\n started_at: facts?.started ?? null,\n finished_at: facts?.finishedAt ?? null,\n wall_ms: wallMs,\n patch_bytes: workerSource?.patchBytes ?? facts?.finishedPatchBytes ?? null,\n evidence_bytes: facts?.evidenceBytes ?? null,\n steers_queued: facts?.steersQueued ?? null,\n steers_delivered: facts?.steersDelivered ?? null,\n questions: facts?.questions ?? null,\n },\n is_completed: close?.kind === 'settled',\n is_truncated: close?.kind === 'cancelled',\n error: close?.kind === 'cancelled' ? (close.verdict ?? 'cancelled') : null,\n realness_gated: false,\n },\n // `close.spend` is only a measurement when the close event carried one;\n // a store that never priced this worker must leave null, not 0.\n cost: {\n ...EMPTY_COST,\n usd: src.limits.spendUsd !== null || !close?.hasSpend ? null : close.spend.usd,\n tokens_in: workerSource?.tokensIn ?? (close?.hasSpend ? close.spend.tokens.input : null),\n tokens_out: workerSource?.tokensOut ?? (close?.hasSpend ? close.spend.tokens.output : null),\n // Mirror the tokens_in/out journal fallback so a loops-shaped store whose\n // `settled` spend carries cache counters is not reported as null cache\n // beside real tokens. Gate on `hasCache` — a spend object without cache\n // counters must stay null, not a fabricated 0.\n cache_read:\n workerSource?.cacheRead ??\n (close?.hasSpend && close.spend.tokens.hasCache ? close.spend.tokens.cacheRead : null),\n cache_write:\n workerSource?.cacheWrite ??\n (close?.hasSpend && close.spend.tokens.hasCache ? close.spend.tokens.cacheWrite : null),\n wall_s: wallMs === null ? null : wallMs / 1000,\n },\n // A reader that knows where its worker artifacts live says so; only the\n // loops layout is derivable from `supRunDir`, so guessing it for another\n // store would mint rows pointing at paths that never existed.\n artifacts: {\n patch_path:\n workerSource?.patchPath !== undefined\n ? workerSource.patchPath\n : src.supRunDir === null\n ? null\n : `${src.supRunDir}/workers/${spawn.label}.patch`,\n run_dir: src.supRunDir,\n transcript_ref:\n workerSource?.transcriptRef !== undefined\n ? workerSource.transcriptRef\n : src.supRunDir === null\n ? null\n : `${src.supRunDir}/workers/${spawn.label}.ndjson`,\n },\n provenance: {\n captured_at: capturedAt,\n capture: 'backfill',\n gap:\n workerSource?.transcriptRef == null\n ? 'worker transcript lives in the harness session store — hydrate via src/rollout/readers'\n : 'worker transcript recorded by the harness; messages not inlined into this row',\n },\n })\n }\n\n const invalid = nodes.filter((n) => !isRolloutLine(n))\n if (invalid.length > 0) {\n gaps.push({\n code: 'node-schema-invalid',\n message: `${invalid.length} node(s) failed tangle.rollout.v1 validation`,\n count: invalid.length,\n })\n }\n return { rootId, nodes, gaps }\n}\n","import { evidence, issue } from './integrity-issues'\nimport { sourceIssues } from './integrity-source'\nimport { treeIssues } from './integrity-tree'\nimport {\n SUPERVISOR_RUN_INTEGRITY_SCHEMA,\n type SupervisorRunIntegrityOptions,\n type SupervisorRunIntegrityReport,\n type SupervisorRunSourceOnlyCheckCode,\n} from './integrity-types'\nimport { supervisorRunRolloutLinesFromFacts } from './rollout-nodes'\nimport { parseSupervisorTree } from './source-facts'\nimport type { SupervisorRunSources, SupervisorRunTree } from './types'\n\nexport {\n SUPERVISOR_RUN_INTEGRITY_SCHEMA,\n type SupervisorRunIntegrityEvidence,\n type SupervisorRunIntegrityIssue,\n type SupervisorRunIntegrityIssueCode,\n type SupervisorRunIntegrityOptions,\n type SupervisorRunIntegrityReport,\n type SupervisorRunIntegritySeverity,\n type SupervisorRunSourceOnlyCheckCode,\n} from './integrity-types'\n\nfunction isTree(input: SupervisorRunSources | SupervisorRunTree): input is SupervisorRunTree {\n return 'nodes' in input && Array.isArray(input.nodes)\n}\n\nfunction treeRunRef(tree: SupervisorRunTree): string {\n const runIds = [\n ...new Set(\n tree.nodes\n .map((node) => node.run_id)\n .filter((runId): runId is string => typeof runId === 'string' && runId.length > 0),\n ),\n ].sort()\n if (runIds.length === 1) return runIds[0]!\n if (runIds.length > 1) return `mixed-runs:${runIds.join(',')}`\n return tree.rootId ?? 'unidentified-tree'\n}\n\n/**\n * Run deterministic integrity checks over source bytes or an already minted tree.\n * Source input is parsed exactly once and reused by projection and source-only checks.\n */\nexport function analyzeSupervisorRunIntegrity(\n input: SupervisorRunSources | SupervisorRunTree,\n options: SupervisorRunIntegrityOptions = {},\n): SupervisorRunIntegrityReport {\n if (isTree(input)) {\n const sourceOnlyChecks: readonly SupervisorRunSourceOnlyCheckCode[] = [\n 'journal-event-cardinality',\n 'worker-control-join',\n 'steer-ack-correlation',\n ]\n return {\n schema: SUPERVISOR_RUN_INTEGRITY_SCHEMA,\n runRef: treeRunRef(input),\n input: 'tree',\n tree: input,\n issues: [\n ...treeIssues(input),\n issue({\n code: 'source-checks-unavailable',\n area: 'capture-integrity',\n severity: 'medium',\n subject: 'source-only-control-checks',\n claim: 'Source-only control checks are unavailable for SupervisorRunTree input',\n detail:\n 'Rollout rows do not retain journal event multiplicity or worker inbox and acknowledgement rows.',\n evidence: [evidence('input/source-only-checks', sourceOnlyChecks)],\n recommendedAction:\n 'Pass SupervisorRunSources when journal and worker control checks are required.',\n metadata: { assessment: 'unavailable', checks: sourceOnlyChecks },\n }),\n ],\n }\n }\n\n const facts = parseSupervisorTree(input)\n const tree = supervisorRunRolloutLinesFromFacts(input, facts, {\n capturedAt: options.capturedAt,\n })\n return {\n schema: SUPERVISOR_RUN_INTEGRITY_SCHEMA,\n runRef: input.runRef,\n input: 'sources',\n tree,\n issues: [\n ...treeIssues(tree, {\n unknownIdentityRows:\n facts.journalInvalidRows +\n facts.spawns.filter((spawn) => !spawn.valid && spawn.id.length === 0).length,\n uncertainIds: new Set(\n facts.spawns\n .filter((spawn) => !spawn.valid && spawn.id.length > 0)\n .map((spawn) => spawn.id),\n ),\n }),\n ...sourceIssues(input, facts, tree),\n ],\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"llm-client-B3WXSH5Y.js","names":[],"sources":["../src/llm-client.ts"],"sourcesContent":["/**\n * LLM client with graceful degrade.\n *\n * OpenAI-compatible `/v1/chat/completions` client with:\n * - Exponential-backoff retry on 429 + 5xx gateway errors (502/503/504).\n * - Retry on transient network errors (fetch failed, AbortError, ECONNRESET).\n * - One retry at temperature 1 when a model explicitly requires it.\n * - Graceful json_schema → json_object degrade on 400 with schema-reject body.\n * - Fenced-JSON stripping (```json ... ```) for models that wrap structured output.\n * - Configurable base URL + api key / bearer, works with LiteLLM proxies, OpenAI\n * directly, cli-bridge subscriptions, and any router that speaks the spec.\n *\n * Usage:\n * const { value, result } = await callLlmJson<MyType>(\n * { model: 'gpt-4o', messages: [...], jsonSchema: { name: 'x', schema: {...} } },\n * { baseUrl: 'https://router.tangle.tools/v1', apiKey: process.env.KEY },\n * )\n *\n * `createChatClient` wraps this implementation for provider-neutral package\n * entry points. Direct callers can use `callLlm` or `callLlmJson`.\n */\n\nimport {\n type CostReceiptInput,\n type CustomTokenPricing,\n costForTokenPricing,\n type MaximumCharge,\n} from './cost-ledger'\nimport { AgentEvalError, CaptureIntegrityError } from './errors'\nimport {\n defaultProviderRedactor,\n type ProviderRedactor,\n providerFromBaseUrl,\n type RawProviderEvent,\n type RawProviderSink,\n} from './trace/raw-provider-sink'\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\nexport interface LlmMessage {\n role: 'system' | 'user' | 'assistant'\n /**\n * Either a plain text content string OR a multimodal content array\n * (text + image_url parts) for vision-capable models.\n */\n content:\n | string\n | Array<\n | { type: 'text'; text: string }\n | { type: 'image_url'; image_url: { url: string; detail?: 'auto' | 'low' | 'high' } }\n >\n}\n\nexport type LlmThinkingMode = 'enabled' | 'disabled'\n\nexport interface LlmCallRequest {\n model: string\n messages: LlmMessage[]\n /** Optional JSON-mode response format (response_format: json_object). */\n jsonMode?: boolean\n /** Optional structured output via JSON Schema. Falls back to json_object on 400. */\n jsonSchema?: { name: string; schema: Record<string, unknown> }\n temperature?: number\n maxTokens?: number\n /** OpenAI-compatible reasoning mode. Omitted when the provider default should apply. */\n thinking?: LlmThinkingMode\n /** Per-call timeout, default 300s. */\n timeoutMs?: number\n}\n\n/** Conservative priced bound for the exact text request sent to a provider.\n * Returns undefined when output or multimodal input is not bounded, causing a\n * capped CostLedger to reject the call before execution. Pass\n * `customTokenPricing` when package pricing does not cover the model or endpoint. */\nexport function maximumChargeForLlmRequest(\n request: Pick<LlmCallRequest, 'model' | 'messages' | 'jsonSchema' | 'maxTokens' | 'thinking'>,\n options: LlmClientOptions = {},\n): MaximumCharge | undefined {\n if (request.maxTokens === undefined) return undefined\n if (!Number.isInteger(request.maxTokens) || request.maxTokens <= 0) {\n throw new RangeError(`maximumChargeForLlmRequest: maxTokens must be a positive integer`)\n }\n if (\n request.messages.some(\n (message) =>\n Array.isArray(message.content) && message.content.some((part) => part.type === 'image_url'),\n )\n ) {\n return undefined\n }\n\n const attempts = resolveMaximumAttempts(options.maximumAttempts)\n const forceJsonObject = options.jsonSchemaTransport === 'json-object'\n // A byte-level tokenizer cannot emit more input tokens than request bytes.\n // Pricing the complete body also covers role/schema framing omitted from content-only estimates.\n const requestBytes = new TextEncoder().encode(\n JSON.stringify(buildBody(request, forceJsonObject, options.thinking)),\n ).byteLength\n // A rejected response schema can trigger one JSON-mode batch with the same output limit.\n const batches = request.jsonSchema && !forceJsonObject ? 2 : 1\n const usage = {\n inputTokens: requestBytes * attempts * batches,\n outputTokens: request.maxTokens * attempts * batches,\n }\n return options.customTokenPricing\n ? { customTokenPricing: options.customTokenPricing, ...usage }\n : { model: request.model, ...usage }\n}\n\nexport interface LlmUsage {\n promptTokens: number\n completionTokens: number\n totalTokens: number\n /** False when the provider omitted or malformed prompt/completion usage. */\n captured?: boolean\n /** Reasoning-token subset of completionTokens, when reported. */\n reasoningTokens?: number\n /** Proxies populate this when prompt caching is on. */\n cachedPromptTokens?: number\n}\n\nexport interface LlmCallResult {\n /** The text content of the first choice. Empty string if none. */\n content: string\n usage: LlmUsage\n /**\n * Cost in USD. Uses the provider's reported cost when present, otherwise\n * caller-supplied token pricing. `null` when neither is available.\n */\n costUsd: number | null\n /** Model name actually used (echoed from response). */\n model: string\n /** Wall-clock duration of the HTTP call (last attempt, if retried). */\n durationMs: number\n /**\n * `finish_reason` echoed from the first choice (`stop`, `length`,\n * `content_filter`, `tool_calls`, ...). `null` when the provider omits it.\n * Exposed so a free-form `callLlm` caller CAN detect a truncated answer\n * (`length`) instead of treating a cut-off completion as complete. Note:\n * `callLlm` does not itself reject on it — acting on this signal is the\n * caller's responsibility (in-repo free-form drivers do not yet enforce it).\n */\n finishReason?: string | null\n /**\n * True when `content.trim()` is empty. An empty completion is a silent zero\n * for free-form `callLlm` callers; this flag is the signal a caller can\n * inspect to fail loud rather than proceed on an empty string. `callLlm`\n * surfaces it but does not throw on it.\n */\n contentEmpty?: boolean\n /** Raw response body. */\n raw: Record<string, unknown>\n}\n\nexport type LlmCallMetadata = Pick<LlmCallResult, 'usage' | 'costUsd' | 'model' | 'durationMs'>\n\n/** Convert a provider result into the canonical paid-call receipt input. */\nexport function costReceiptFromLlm(\n result: LlmCallResult,\n customTokenPricing?: CustomTokenPricing,\n): CostReceiptInput {\n const cachedTokens = result.usage.cachedPromptTokens ?? 0\n const inputTokens = Math.max(0, result.usage.promptTokens - cachedTokens)\n const configuredCostUsd =\n result.costUsd === null && customTokenPricing && result.usage.captured !== false\n ? costForTokenPricing(customTokenPricing, {\n inputTokens,\n ...(cachedTokens > 0 ? { cachedTokens } : {}),\n outputTokens: result.usage.completionTokens,\n })\n : undefined\n return {\n model: result.model,\n inputTokens,\n outputTokens: result.usage.completionTokens,\n reasoningTokens: result.usage.reasoningTokens,\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\n actualCostUsd: result.costUsd ?? configuredCostUsd,\n usageUnknown: result.usage.captured === false,\n }\n}\n\n/** Structured-response failures retain their completed provider receipt. */\nexport function costReceiptFromLlmError(\n error: Error,\n customTokenPricing?: CustomTokenPricing,\n): CostReceiptInput | undefined {\n return error instanceof LlmResponseError\n ? costReceiptFromLlm(error.result, customTokenPricing)\n : undefined\n}\n\nexport class LlmCallError extends AgentEvalError {\n constructor(\n message: string,\n public readonly status: number,\n public readonly body: string,\n public readonly model: string,\n ) {\n super('judge', message)\n }\n}\n\n/** A provider response completed and incurred measurable usage, but its content\n * could not satisfy the caller's response contract. The response envelope is\n * retained so accounting can commit the receipt before the error propagates. */\nexport class LlmResponseError extends AgentEvalError {\n constructor(\n message: string,\n public readonly result: LlmCallResult,\n options?: { cause?: unknown },\n ) {\n super('judge', message, options)\n }\n}\n\nexport interface LlmClientOptions {\n /** Base URL (without trailing slash). Must end at the `/v1` prefix. */\n baseUrl?: string\n /** Bearer token — either `apiKey` or `bearer` populates `Authorization: Bearer ...`. */\n apiKey?: string\n bearer?: string\n /** Override for the `Authorization` header (e.g. `X-Auth: ...`). Takes precedence over apiKey/bearer. */\n authHeader?: { name: string; value: string }\n /** Stable provider idempotency key, reused across retries of this logical call. */\n idempotencyKey?: string\n /** Default timeout in ms. Per-call can override. */\n defaultTimeoutMs?: number\n /**\n * Caller-supplied abort signal — e.g. a campaign-wide cancel. Linked to\n * each attempt's per-attempt timeout controller, so aborting it cancels\n * the in-flight fetch. A caller abort is FATAL: it is not retried even\n * though an AbortError otherwise matches the transient patterns.\n */\n signal?: AbortSignal\n /**\n * Cross-attempt wall-clock budget in ms, measured from the first attempt.\n * Before launching each attempt the loop checks the remaining budget and\n * stops retrying once it is exhausted, rather than waiting the full\n * per-attempt timeout on every retry. Bounds total time independent of\n * total attempts × `timeoutMs`.\n */\n deadlineMs?: number\n /** Total provider attempts. Default 3. */\n maximumAttempts?: number\n /** Token rates used when the provider omits cost or package pricing does not cover the model. */\n customTokenPricing?: CustomTokenPricing\n /**\n * Transport for requests that declare `jsonSchema`. `native` sends\n * `response_format: json_schema`; `json-object` sends the broadly supported\n * JSON mode and relies on the caller to include the schema in model-visible\n * instructions. Default: `native`.\n */\n jsonSchemaTransport?: 'native' | 'json-object'\n /**\n * JSON payload parsing policy. `extract` accepts fenced or prose-prefixed JSON.\n * `exact` requires the complete response content to be one JSON value.\n * Default: `extract`.\n */\n jsonPayloadMode?: 'extract' | 'exact'\n /** Default provider reasoning mode. A per-call request value takes precedence. */\n thinking?: LlmThinkingMode\n /** Fetch implementation — defaults to global `fetch`. Override for custom transport (e.g. tests). */\n fetch?: typeof fetch\n /**\n * Optional raw HTTP capture sink. When provided, every request, response,\n * and error (across all retry attempts) is recorded to the sink, with auth\n * headers and credential-shaped body fields redacted by default. This is\n * the layer-1 forensics primitive: structured `LlmSpan`s record intent,\n * raw events record what actually crossed the wire.\n */\n rawSink?: RawProviderSink\n /**\n * Logical provider id attached to raw events. When omitted, derived from\n * `baseUrl` via `providerFromBaseUrl`.\n */\n provider?: string\n /** Trace context attached to raw events; populated by emitter-aware callers. */\n traceContext?: { runId?: string; spanId?: string }\n /** Override the redaction strategy for this call. Defaults to `defaultProviderRedactor`. */\n redactor?: ProviderRedactor\n}\n\n// ─── Internals ──────────────────────────────────────────────────────────\n\nconst DEFAULT_BASE_URL = 'https://router.tangle.tools/v1'\n// Flagship / reasoning models routinely take several minutes on large prompts (a\n// reflection over many failures, a long tool transcript). A tight cap aborts a\n// legitimately-slow but healthy call — and because every retry attempt re-uses\n// the same window, such a model aborts on ALL attempts and the loop throws. The\n// default is generous enough to let those complete, bounded enough that a truly\n// hung call still fails over after retries, and tunable per deployment via\n// TANGLE_LLM_TIMEOUT_MS. Per-call `req.timeoutMs` / `opts.defaultTimeoutMs`\n// still win for callers that know their model's latency.\nconst DEFAULT_TIMEOUT_MS = Number(process.env.TANGLE_LLM_TIMEOUT_MS) || 300_000\nconst DEFAULT_MAXIMUM_ATTEMPTS =\n process.env.TANGLE_LLM_MAXIMUM_ATTEMPTS === undefined\n ? 3\n : Number(process.env.TANGLE_LLM_MAXIMUM_ATTEMPTS)\n\nfunction resolveMaximumAttempts(configured: number | undefined): number {\n const attempts = configured ?? DEFAULT_MAXIMUM_ATTEMPTS\n if (!Number.isInteger(attempts) || attempts <= 0) {\n throw new RangeError('LLM maximum attempts must be a positive integer')\n }\n return attempts\n}\n\nfunction providerTokenCount(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : undefined\n}\n\nconst RETRYABLE_STATUS = new Set([429, 502, 503, 504])\n\n/**\n * Transient transport/network error signatures, matched against an error's\n * name, message, and `code`. Covers fetch/undici network failures, aborts\n * and timeouts, and — critically — HTTP/2 transport faults a keep-alive\n * connection raises mid-response: `terminated`, `NGHTTP2_INTERNAL_ERROR`,\n * `UND_ERR_*`, `other side closed`. Those last ones carry no clean HTTP\n * status; unrecognised, they escape the retry loop and surface as an\n * uncaught rejection.\n */\nconst TRANSIENT_ERROR_PATTERNS: readonly RegExp[] = [\n /AbortError/i,\n /TimeoutError/i,\n /this operation was aborted/i,\n /fetch failed/i,\n /ECONNRESET/i,\n /ETIMEDOUT/i,\n /EAI_AGAIN/i,\n /socket hang up/i,\n /stream.*ended.*unexpectedly/i,\n /terminated/i,\n /other side closed/i,\n /NGHTTP2/i,\n /UND_ERR/i,\n]\n\n/**\n * True when an error is a transient transport/network fault worth retrying,\n * as opposed to a deterministic failure (4xx schema reject, JSON parse) that\n * a retry cannot fix. Inspects `LlmCallError.status`, then the error's\n * name/message/code, then recurses into `error.cause` — undici nests the\n * real socket fault one or more levels under `.cause`.\n *\n * This is the retry classifier for the package: `callLlm` and\n * `withJudgeRetry` both route through it, so connection failures are treated\n * consistently across transports.\n */\nexport function isTransientLlmError(err: unknown): boolean {\n return classifyTransient(err, 0)\n}\n\nfunction classifyTransient(err: unknown, depth: number): boolean {\n if (err instanceof LlmCallError) return RETRYABLE_STATUS.has(err.status)\n if (!(err instanceof Error)) return false\n // Foreign transport errors can carry a numeric HTTP status without being an\n // LlmCallError. A retryable status is decisive.\n const status = (err as { status?: unknown }).status\n if (typeof status === 'number' && RETRYABLE_STATUS.has(status)) return true\n const code = (err as { code?: unknown }).code\n const haystack = `${err.name}\\n${err.message}\\n${typeof code === 'string' ? code : ''}`\n if (TRANSIENT_ERROR_PATTERNS.some((p) => p.test(haystack))) return true\n const cause = (err as { cause?: unknown }).cause\n if (depth < 4 && cause instanceof Error && cause !== err) {\n return classifyTransient(cause, depth + 1)\n }\n return false\n}\n\nfunction parseRetryAfter(headers: Headers): number | null {\n const h = headers.get('retry-after')\n if (!h) return null\n const asNumber = Number(h)\n if (Number.isFinite(asNumber) && asNumber > 0) return asNumber * 1000\n const asDate = Date.parse(h)\n if (Number.isFinite(asDate)) return Math.max(0, asDate - Date.now())\n return null\n}\n\n/** Exponential backoff: 500ms, 1s, 2s, 4s, ... capped at 16s. Attempt is 0-indexed. */\nexport function backoffMs(attempt: number): number {\n return Math.min(500 * 2 ** attempt, 16_000)\n}\n\nfunction buildHeaders(opts: LlmClientOptions): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n }\n if (opts.authHeader) {\n headers[opts.authHeader.name] = opts.authHeader.value\n } else if (opts.bearer || opts.apiKey) {\n headers.Authorization = `Bearer ${opts.bearer ?? opts.apiKey}`\n }\n if (opts.idempotencyKey) headers['Idempotency-Key'] = opts.idempotencyKey\n return headers\n}\n\nfunction isSchemaRejection(status: number, body: string): boolean {\n if (status !== 400) return false\n const lower = body.toLowerCase()\n return (\n lower.includes('response_format') ||\n lower.includes('json_schema') ||\n lower.includes('is unavailable') ||\n lower.includes('not supported')\n )\n}\n\nfunction isTemperatureOneRejection(status: number, body: string): boolean {\n if (status !== 400 || !/temperature/i.test(body)) return false\n return (\n /temperature[^.\\n]{0,120}\\b(?:only|must|should|required|requires?)\\b[^.\\n]{0,40}\\b1(?:\\.0+)?\\b/i.test(\n body,\n ) || /\\bonly\\s+1(?:\\.0+)?\\s+is\\s+allowed\\b[^.\\n]{0,120}\\btemperature\\b/i.test(body)\n )\n}\n\nfunction buildBody(\n req: LlmCallRequest,\n forceJsonObject: boolean,\n defaultThinking?: LlmThinkingMode,\n): Record<string, unknown> {\n const body: Record<string, unknown> = {\n model: req.model,\n messages: req.messages,\n temperature: req.temperature ?? 0,\n }\n if (req.maxTokens != null) {\n if (usesMaxCompletionTokens(req.model)) body.max_completion_tokens = req.maxTokens\n else body.max_tokens = req.maxTokens\n }\n const thinking = req.thinking ?? defaultThinking\n if (thinking !== undefined) {\n body.thinking = { type: thinking }\n }\n\n if (req.jsonSchema && !forceJsonObject) {\n body.response_format = {\n type: 'json_schema',\n json_schema: { name: req.jsonSchema.name, schema: req.jsonSchema.schema, strict: true },\n }\n } else if (req.jsonMode || req.jsonSchema) {\n body.response_format = { type: 'json_object' }\n }\n\n return body\n}\n\nfunction usesMaxCompletionTokens(model: string): boolean {\n return /^gpt-5(?:[.-]|$)/i.test(model)\n}\n\nasync function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Combine the per-attempt timeout signal with an optional caller signal into\n * one signal the fetch listens on. Prefers the native `AbortSignal.any`; falls\n * back to manual wiring on runtimes that predate it. The caller signal is also\n * propagated to the timeout controller so aborting it cancels the in-flight\n * fetch immediately.\n */\nfunction linkSignals(timeoutController: AbortController, caller?: AbortSignal): AbortSignal {\n if (!caller) return timeoutController.signal\n if (typeof (AbortSignal as { any?: unknown }).any === 'function') {\n return AbortSignal.any([timeoutController.signal, caller])\n }\n if (caller.aborted) {\n timeoutController.abort()\n } else {\n caller.addEventListener('abort', () => timeoutController.abort(), { once: true })\n }\n return timeoutController.signal\n}\n\n/** True once the cross-attempt wall-clock budget (if any) is exhausted. */\nfunction deadlineExceeded(start: number, deadlineMs: number | undefined): boolean {\n return deadlineMs != null && Date.now() - start >= deadlineMs\n}\n\n// ─── Public API ─────────────────────────────────────────────────────────\n\n/**\n * Strip a ```json / ``` code fence if the model emitted one.\n * Idempotent for naked JSON. Some models (claude-code via router, certain\n * deepseek models) wrap output even under json_object.\n */\nexport function stripFencedJson(raw: string): string {\n const trimmed = raw.trim()\n const m = trimmed.match(/^```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?```\\s*$/)\n return m ? m[1]!.trim() : trimmed\n}\n\nexport function extractJsonPayload(raw: string): string {\n const stripped = stripFencedJson(raw)\n try {\n JSON.parse(stripped)\n return stripped\n } catch {\n // A response that declares a JSON root must parse as that complete root.\n // Scanning onward could turn a truncated object into one of its valid nested\n // arrays or objects and silently change the response schema.\n if (stripped.startsWith('{') || stripped.startsWith('[')) return stripped\n }\n\n // Only prose-leading responses may contain a recoverable JSON payload.\n const starts = [...stripped.matchAll(/[[{]/g)]\n .map((match) => match.index)\n .filter((index) => index != null)\n for (const start of starts) {\n const candidate = extractBalancedJson(stripped, start)\n if (!candidate) continue\n try {\n JSON.parse(candidate)\n return candidate\n } catch {\n // Keep scanning; earlier braces may belong to prose.\n }\n }\n\n return stripped\n}\n\nfunction extractBalancedJson(input: string, start: number): string | null {\n const opener = input[start]\n const closer = opener === '{' ? '}' : opener === '[' ? ']' : null\n if (!closer) return null\n\n const stack: string[] = [closer]\n let isInString = false\n let isEscaped = false\n\n for (let i = start + 1; i < input.length; i++) {\n const char = input[i]!\n if (isEscaped) {\n isEscaped = false\n continue\n }\n if (char === '\\\\') {\n isEscaped = isInString\n continue\n }\n if (char === '\"') {\n isInString = !isInString\n continue\n }\n if (isInString) continue\n\n if (char === '{') stack.push('}')\n else if (char === '[') stack.push(']')\n else if (char === stack[stack.length - 1]) {\n stack.pop()\n if (stack.length === 0) return input.slice(start, i + 1)\n }\n }\n\n return null\n}\n\n/**\n * Low-level call. Returns raw content + usage + cost. Retries on transient\n * failures; does NOT degrade schema here — callers that want graceful\n * degrade use `callLlmJson`.\n */\nexport async function callLlm(\n req: LlmCallRequest,\n opts: LlmClientOptions = {},\n): Promise<LlmCallResult> {\n const baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '')\n const url = `${baseUrl}/chat/completions`\n const endpoint = '/chat/completions'\n const timeoutMs = req.timeoutMs ?? opts.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS\n const maximumAttempts = resolveMaximumAttempts(opts.maximumAttempts)\n const fetchFn = opts.fetch ?? globalThis.fetch\n const headers = buildHeaders(opts)\n const provider = opts.provider ?? providerFromBaseUrl(baseUrl)\n const sink = opts.rawSink\n const redactor = opts.redactor ?? defaultProviderRedactor\n const traceContext = opts.traceContext\n const callerSignal = opts.signal\n const deadlineMs = opts.deadlineMs\n const deadlineStart = Date.now()\n if (opts.customTokenPricing) {\n costForTokenPricing(opts.customTokenPricing, { inputTokens: 0, outputTokens: 0 })\n }\n\n let lastErr: unknown\n let effectiveRequest = req\n for (let attempt = 0; attempt < maximumAttempts; attempt++) {\n // A caller cancel is fatal — never retried. Checking before each attempt\n // means an already-aborted signal short-circuits without firing fetch.\n if (callerSignal?.aborted) {\n throw new DOMException('callLlm aborted by caller signal', 'AbortError')\n }\n // Stop retrying once the cross-attempt budget is spent rather than burning\n // a full per-attempt timeout on each remaining retry.\n if (attempt > 0 && deadlineExceeded(deadlineStart, deadlineMs)) {\n throw lastErr instanceof Error ? lastErr : new Error(String(lastErr))\n }\n const controller = new AbortController()\n const attemptSignal = linkSignals(controller, callerSignal)\n const timeoutHandle = setTimeout(() => controller.abort(), timeoutMs)\n const started = Date.now()\n const requestBody = buildBody(\n effectiveRequest,\n opts.jsonSchemaTransport === 'json-object',\n opts.thinking,\n )\n let attemptErrorRecorded = false\n if (sink) {\n await recordRaw(sink, redactor, {\n eventId: cryptoEventId(),\n runId: traceContext?.runId,\n spanId: traceContext?.spanId,\n provider,\n model: req.model,\n endpoint,\n baseUrl,\n attemptIndex: attempt,\n direction: 'request',\n timestamp: started,\n requestHeaders: headers,\n requestBody,\n redactedFields: [],\n })\n }\n\n try {\n const res = await fetchFn(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody),\n signal: attemptSignal,\n })\n clearTimeout(timeoutHandle)\n const responseHeaders = sink ? headersToObject(res.headers) : undefined\n\n if (!res.ok) {\n const body = await res.text()\n if (sink) {\n await recordRaw(sink, redactor, {\n eventId: cryptoEventId(),\n runId: traceContext?.runId,\n spanId: traceContext?.spanId,\n provider,\n model: req.model,\n endpoint,\n baseUrl,\n attemptIndex: attempt,\n direction: 'error',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n statusCode: res.status,\n responseHeaders,\n responseBody: body,\n errorMessage: `HTTP ${res.status}`,\n redactedFields: [],\n })\n attemptErrorRecorded = true\n }\n const err = new LlmCallError(\n `LLM call failed with HTTP ${res.status}`,\n res.status,\n body,\n req.model,\n )\n if (\n isTemperatureOneRejection(res.status, body) &&\n effectiveRequest.temperature !== 1 &&\n attempt < maximumAttempts - 1 &&\n !deadlineExceeded(deadlineStart, deadlineMs)\n ) {\n lastErr = err\n effectiveRequest = { ...effectiveRequest, temperature: 1 }\n continue\n }\n if (\n RETRYABLE_STATUS.has(res.status) &&\n attempt < maximumAttempts - 1 &&\n !deadlineExceeded(deadlineStart, deadlineMs)\n ) {\n lastErr = err\n const retryAfter = parseRetryAfter(res.headers)\n await sleep(retryAfter ?? backoffMs(attempt))\n continue\n }\n throw err\n }\n\n const text = await res.text()\n let json: Record<string, unknown>\n try {\n json = JSON.parse(text) as Record<string, unknown>\n } catch (parseErr) {\n if (sink) {\n await recordRaw(sink, redactor, {\n eventId: cryptoEventId(),\n runId: traceContext?.runId,\n spanId: traceContext?.spanId,\n provider,\n model: req.model,\n endpoint,\n baseUrl,\n attemptIndex: attempt,\n direction: 'error',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n statusCode: res.status,\n responseHeaders,\n responseBody: text,\n errorMessage: `non-JSON response: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`,\n redactedFields: [],\n })\n attemptErrorRecorded = true\n }\n throw parseErr\n }\n if (sink) {\n await recordRaw(sink, redactor, {\n eventId: cryptoEventId(),\n runId: traceContext?.runId,\n spanId: traceContext?.spanId,\n provider,\n model: req.model,\n endpoint,\n baseUrl,\n attemptIndex: attempt,\n direction: 'response',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n statusCode: res.status,\n responseHeaders,\n responseBody: json,\n redactedFields: [],\n })\n }\n const choice = (\n json.choices as\n | Array<{ message?: { content?: string }; finish_reason?: string | null }>\n | undefined\n )?.[0]\n const usageRaw =\n json.usage && typeof json.usage === 'object' && !Array.isArray(json.usage)\n ? (json.usage as Record<string, unknown>)\n : undefined\n const promptTokens = providerTokenCount(usageRaw?.prompt_tokens)\n const completionTokens = providerTokenCount(usageRaw?.completion_tokens)\n const totalTokens = providerTokenCount(usageRaw?.total_tokens)\n const completionDetails =\n usageRaw?.completion_tokens_details &&\n typeof usageRaw.completion_tokens_details === 'object' &&\n !Array.isArray(usageRaw.completion_tokens_details)\n ? (usageRaw.completion_tokens_details as Record<string, unknown>)\n : undefined\n const reasoningRaw = completionDetails?.reasoning_tokens\n const reasoningTokens =\n reasoningRaw === undefined ? undefined : providerTokenCount(reasoningRaw)\n const cachedRaw =\n usageRaw?.prompt_tokens_details &&\n typeof usageRaw.prompt_tokens_details === 'object' &&\n !Array.isArray(usageRaw.prompt_tokens_details)\n ? (usageRaw.prompt_tokens_details as Record<string, unknown>).cached_tokens\n : undefined\n const cachedPromptTokens = cachedRaw === undefined ? undefined : providerTokenCount(cachedRaw)\n const usageCaptured =\n promptTokens !== undefined &&\n completionTokens !== undefined &&\n (reasoningRaw === undefined ||\n (reasoningTokens !== undefined && reasoningTokens <= completionTokens)) &&\n (cachedRaw === undefined ||\n (cachedPromptTokens !== undefined && cachedPromptTokens <= promptTokens)) &&\n (totalTokens === undefined || totalTokens === promptTokens + completionTokens)\n const costFromProxy = (json._response_cost ?? json.cost_usd) as number | undefined\n const content = choice?.message?.content ?? ''\n\n const configuredCost =\n typeof costFromProxy !== 'number' && usageCaptured && opts.customTokenPricing\n ? costForTokenPricing(opts.customTokenPricing, {\n inputTokens: promptTokens! - (cachedPromptTokens ?? 0),\n ...(cachedPromptTokens ? { cachedTokens: cachedPromptTokens } : {}),\n outputTokens: completionTokens!,\n })\n : undefined\n\n return {\n content,\n finishReason: choice?.finish_reason ?? null,\n contentEmpty: content.trim().length === 0,\n usage: {\n promptTokens: promptTokens ?? 0,\n completionTokens: completionTokens ?? 0,\n totalTokens: totalTokens ?? (promptTokens ?? 0) + (completionTokens ?? 0),\n captured: usageCaptured,\n reasoningTokens,\n cachedPromptTokens,\n },\n costUsd: typeof costFromProxy === 'number' ? costFromProxy : (configuredCost ?? null),\n model: (json.model as string) ?? req.model,\n durationMs: Date.now() - started,\n raw: json,\n }\n } catch (err) {\n clearTimeout(timeoutHandle)\n lastErr = err\n // A caller cancel is fatal even though an AbortError matches the\n // transient patterns — a cancelled call must surface immediately, not\n // be retried against the same dead intent.\n if (callerSignal?.aborted) {\n if (sink && !attemptErrorRecorded) {\n await recordRaw(sink, redactor, {\n eventId: cryptoEventId(),\n runId: traceContext?.runId,\n spanId: traceContext?.spanId,\n provider,\n model: req.model,\n endpoint,\n baseUrl,\n attemptIndex: attempt,\n direction: 'error',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n errorMessage: err instanceof Error ? err.message : String(err),\n redactedFields: [],\n })\n }\n throw err\n }\n if (sink && !attemptErrorRecorded) {\n // Record only if neither the !res.ok branch nor the JSON.parse catch\n // already produced an error event for this attempt. Covers network\n // failures, timeouts, and aborts.\n await recordRaw(sink, redactor, {\n eventId: cryptoEventId(),\n runId: traceContext?.runId,\n spanId: traceContext?.spanId,\n provider,\n model: req.model,\n endpoint,\n baseUrl,\n attemptIndex: attempt,\n direction: 'error',\n timestamp: Date.now(),\n durationMs: Date.now() - started,\n errorMessage: err instanceof Error ? err.message : String(err),\n redactedFields: [],\n })\n }\n if (\n attempt < maximumAttempts - 1 &&\n isTransientLlmError(err) &&\n !deadlineExceeded(deadlineStart, deadlineMs)\n ) {\n await sleep(backoffMs(attempt))\n continue\n }\n throw err\n }\n }\n throw lastErr instanceof Error ? lastErr : new Error(String(lastErr))\n}\n\nasync function recordRaw(\n sink: RawProviderSink,\n redactor: ProviderRedactor,\n event: RawProviderEvent,\n): Promise<void> {\n // Errors from sinks must not crash the LLM call. Forensic capture is\n // best-effort; the structured trace is the system of record.\n try {\n await sink.record(redactor(event))\n } catch {\n // Intentionally swallowed.\n }\n}\n\nfunction headersToObject(h: Headers): Record<string, string> {\n const out: Record<string, string> = {}\n h.forEach((value, key) => {\n out[key] = value\n })\n return out\n}\n\nfunction cryptoEventId(): string {\n if (typeof globalThis.crypto?.randomUUID === 'function') return globalThis.crypto.randomUUID()\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`\n}\n\n/**\n * Structured-output call. Returns parsed JSON plus the raw result envelope.\n * Degrades `jsonSchema` → `jsonMode` on a 400 that names the schema param —\n * critical for deepseek-v3/v4, kimi-k2.6, and other models that don't accept\n * the `response_format.json_schema` shape but DO accept `json_object`.\n */\nexport async function callLlmJson<T = unknown>(\n req: LlmCallRequest,\n opts: LlmClientOptions = {},\n): Promise<{ value: T; result: LlmCallResult }> {\n const result = await callLlmStructured(req, opts)\n const value = parseJsonResult<T>(result, opts.jsonPayloadMode ?? 'extract')\n return { value, result }\n}\n\n/** Shared schema-to-JSON-mode fallback that preserves the raw result. */\nasync function callLlmStructured(\n req: LlmCallRequest,\n opts: LlmClientOptions = {},\n): Promise<LlmCallResult> {\n try {\n return await callLlm({ ...req, jsonMode: req.jsonMode ?? !req.jsonSchema }, opts)\n } catch (err) {\n if (\n opts.jsonSchemaTransport !== 'json-object' &&\n err instanceof LlmCallError &&\n isSchemaRejection(err.status, err.body) &&\n req.jsonSchema\n ) {\n const degradedReq: LlmCallRequest = { ...req, jsonMode: true, jsonSchema: undefined }\n return await callLlm(degradedReq, opts)\n }\n throw err\n }\n}\n\nfunction parseJsonResult<T>(\n result: LlmCallResult,\n jsonPayloadMode: NonNullable<LlmClientOptions['jsonPayloadMode']>,\n): T {\n try {\n if (result.finishReason === 'length') {\n throw new Error(\n `LLM returned truncated JSON content (model=${result.model}, finishReason=length)`,\n )\n }\n return parseJsonSafely<T>(result.content, result.model, jsonPayloadMode)\n } catch (error) {\n if (error instanceof LlmResponseError) throw error\n const cause = error instanceof Error ? error : new Error(String(error))\n throw new LlmResponseError(cause.message, result, { cause })\n }\n}\n\nfunction parseJsonSafely<T>(\n content: string,\n model: string,\n jsonPayloadMode: NonNullable<LlmClientOptions['jsonPayloadMode']>,\n): T {\n const payload = jsonPayloadMode === 'exact' ? content : extractJsonPayload(content)\n try {\n return JSON.parse(payload) as T\n } catch {\n throw new Error(`LLM returned non-JSON content (model=${model})`)\n }\n}\n\n// ─── Route assertion ────────────────────────────────────────────────────\n\nexport type LlmRouteAssertionReason =\n | 'no_explicit_base_url'\n | 'base_url_blocked'\n | 'base_url_not_allowed'\n | 'no_auth'\n | 'wrong_provider'\n\nexport class LlmRouteAssertionError extends CaptureIntegrityError {\n constructor(\n message: string,\n public readonly reason: LlmRouteAssertionReason,\n public readonly baseUrl: string,\n ) {\n super(message)\n }\n}\n\nexport interface LlmRouteRequirements {\n /**\n * Throw if `opts.baseUrl` is undefined, i.e. the call would fall back to\n * `DEFAULT_BASE_URL`. Set this for evaluation runs where silently using\n * the public/free-tier router is a defect — the launch reviewer needs to\n * know exactly which provider answered.\n */\n requireExplicitBaseUrl?: boolean\n /**\n * Allowlist of acceptable base URLs. Strings match by prefix\n * (case-insensitive); RegExps test against the full base URL.\n */\n allowedBaseUrls?: Array<string | RegExp>\n /** Blocklist that takes precedence over `allowedBaseUrls`. */\n blockedBaseUrls?: Array<string | RegExp>\n /** Throw if no auth header / api key is configured. */\n requireAuth?: boolean\n /**\n * Logical provider id the configured `baseUrl` is expected to match (via\n * `providerFromBaseUrl`). Mainly useful when paired with `requireExplicitBaseUrl`.\n */\n expectedProvider?: string\n}\n\n/**\n * Fail-loud assertion that the configured LLM client points at the route\n * the caller intends. Designed for the matrix-runner preflight: invoke\n * once before any LLM call to catch misconfiguration before a sweep burns\n * dollars on the wrong provider.\n *\n * Throws `LlmRouteAssertionError`. Pure — no I/O — so it's safe to call\n * from constructors and CI gates.\n */\nexport function assertLlmRoute(opts: LlmClientOptions, req: LlmRouteRequirements = {}): void {\n const baseUrlExplicit = opts.baseUrl !== undefined\n const baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '')\n\n if (req.requireExplicitBaseUrl && !baseUrlExplicit) {\n throw new LlmRouteAssertionError(\n `assertLlmRoute: requireExplicitBaseUrl set but opts.baseUrl is undefined; would fall back to ${DEFAULT_BASE_URL}.`,\n 'no_explicit_base_url',\n baseUrl,\n )\n }\n\n if (req.blockedBaseUrls?.some((p) => matchUrl(baseUrl, p))) {\n throw new LlmRouteAssertionError(\n `assertLlmRoute: baseUrl ${baseUrl} matches a blocked pattern.`,\n 'base_url_blocked',\n baseUrl,\n )\n }\n\n if (req.allowedBaseUrls && req.allowedBaseUrls.length > 0) {\n const ok = req.allowedBaseUrls.some((p) => matchUrl(baseUrl, p))\n if (!ok) {\n throw new LlmRouteAssertionError(\n `assertLlmRoute: baseUrl ${baseUrl} is not in the allowed list (${req.allowedBaseUrls.map(describePattern).join(', ')}).`,\n 'base_url_not_allowed',\n baseUrl,\n )\n }\n }\n\n if (req.requireAuth && !opts.apiKey && !opts.bearer && !opts.authHeader) {\n throw new LlmRouteAssertionError(\n `assertLlmRoute: requireAuth set but no apiKey, bearer, or authHeader was supplied.`,\n 'no_auth',\n baseUrl,\n )\n }\n\n if (req.expectedProvider) {\n const actual = opts.provider ?? providerFromBaseUrl(baseUrl)\n if (actual !== req.expectedProvider) {\n throw new LlmRouteAssertionError(\n `assertLlmRoute: expected provider ${req.expectedProvider} but baseUrl ${baseUrl} resolves to ${actual}.`,\n 'wrong_provider',\n baseUrl,\n )\n }\n }\n}\n\nfunction matchUrl(url: string, pattern: string | RegExp): boolean {\n if (pattern instanceof RegExp) return pattern.test(url)\n return url.toLowerCase().startsWith(pattern.toLowerCase())\n}\n\nfunction describePattern(p: string | RegExp): string {\n return p instanceof RegExp ? p.source : p\n}\n\n/**\n * Probe whether a model is reachable. Returns latency + null error on\n * success; `ok=false` + error message on any failure (HTTP, timeout,\n * network, parse). Designed for sweep preflights — fail loud at the\n * boundary before burning a 30-leaf run on a misconfigured router.\n *\n * Sends a tiny `ping` message with `maxTokens=64`. Reasoning models\n * (glm-5.1, deepseek-v4) can burn the entire budget on internal reasoning\n * for short prompts, so don't tighten this further. We don't validate\n * content; HTTP 200 means reachable.\n */\nexport async function probeLlm(\n model: string,\n opts: LlmClientOptions & { timeoutMs?: number } = {},\n): Promise<{ ok: boolean; latencyMs: number; error: string | null }> {\n const start = Date.now()\n try {\n await callLlm(\n {\n model,\n messages: [{ role: 'user', content: 'ping' }],\n maxTokens: 64,\n timeoutMs: opts.timeoutMs ?? 30_000,\n },\n opts,\n )\n return { ok: true, latencyMs: Date.now() - start, error: null }\n } catch (err) {\n return {\n ok: false,\n latencyMs: Date.now() - start,\n error: err instanceof Error ? err.message : String(err),\n }\n }\n}\n\n/**\n * Stateful client — construct once with defaults, call many times.\n * Thin wrapper around the free functions; exists for callers that want\n * to inject a single configured instance into multiple primitives.\n */\nexport class LlmClient {\n readonly maximumAttempts: number\n private readonly opts: LlmClientOptions\n\n constructor(opts: LlmClientOptions = {}) {\n this.opts = opts\n this.maximumAttempts = resolveMaximumAttempts(opts.maximumAttempts)\n }\n\n call(req: LlmCallRequest, per?: LlmClientOptions): Promise<LlmCallResult> {\n const options = { ...this.opts, ...per }\n return req.jsonSchema ? callLlmStructured(req, options) : callLlm(req, options)\n }\n\n callJson<T = unknown>(\n req: LlmCallRequest,\n per?: LlmClientOptions,\n ): Promise<{ value: T; result: LlmCallResult }> {\n return callLlmJson<T>(req, { ...this.opts, ...per })\n }\n}\n"],"mappings":"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"}
|