@tangle-network/agent-eval 0.145.22 → 0.146.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["v1"],"sources":["../../../src/multishot/golden/compare.ts","../../../src/multishot/golden/recording.ts","../../../src/multishot/golden/matrix-scenarios.ts","../../../src/multishot/golden/records/v1.json","../../../src/multishot/golden/records/index.ts","../../../src/multishot/golden/scenarios.ts","../../../src/multishot/golden/harness.ts"],"sourcesContent":["// Structural comparison with a readable failure path.\n//\n// A golden mismatch has to name the field that moved, not print two blobs.\n// Every mismatch is one line: the dotted path, what the record holds, and what\n// the engine produced.\n\nconst MAX_RENDER = 240\n\nexport interface CompareOptions {\n /** Stop after this many mismatches. A structural divergence high in the\n * tree would otherwise report every leaf below it. */\n limit?: number\n}\n\nexport function compareJson(\n expected: unknown,\n actual: unknown,\n path: string,\n options: CompareOptions = {},\n): string[] {\n const limit = options.limit ?? 25\n const mismatches: string[] = []\n walk(expected, actual, path, mismatches, limit)\n // The walk stops checking past the cap but a single frame can push several\n // lines, so the list is trimmed to the number the caller asked for.\n return mismatches.slice(0, limit)\n}\n\nfunction walk(\n expected: unknown,\n actual: unknown,\n path: string,\n out: string[],\n limit: number,\n): void {\n if (out.length >= limit) return\n\n if (Array.isArray(expected) || Array.isArray(actual)) {\n if (!Array.isArray(expected) || !Array.isArray(actual)) {\n out.push(mismatch(path, expected, actual))\n return\n }\n if (expected.length !== actual.length) {\n out.push(`${path}: expected ${expected.length} entries, received ${actual.length}`)\n }\n const shared = Math.min(expected.length, actual.length)\n for (let i = 0; i < shared && out.length < limit; i++) {\n walk(expected[i], actual[i], `${path}[${i}]`, out, limit)\n }\n return\n }\n\n const expectedIsRow = isRow(expected)\n const actualIsRow = isRow(actual)\n if (expectedIsRow || actualIsRow) {\n if (!expectedIsRow || !actualIsRow) {\n out.push(mismatch(path, expected, actual))\n return\n }\n const keys = [...new Set([...Object.keys(expected), ...Object.keys(actual)])].sort()\n for (const key of keys) {\n const inExpected = key in expected\n const inActual = key in actual\n const child = path ? `${path}.${key}` : key\n if (!inActual) {\n out.push(`${child}: expected ${render(expected[key])}, received nothing`)\n continue\n }\n if (!inExpected) {\n out.push(`${child}: expected nothing, received ${render(actual[key])}`)\n continue\n }\n walk(expected[key], actual[key], child, out, limit)\n if (out.length >= limit) return\n }\n return\n }\n\n if (!Object.is(expected, actual)) out.push(mismatch(path, expected, actual))\n}\n\nfunction isRow(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction mismatch(path: string, expected: unknown, actual: unknown): string {\n return `${path}: expected ${render(expected)}, received ${render(actual)}`\n}\n\nfunction render(value: unknown): string {\n if (value === undefined) return 'undefined'\n let text: string\n try {\n text = JSON.stringify(value) ?? String(value)\n } catch {\n text = String(value)\n }\n return text.length > MAX_RENDER ? `${text.slice(0, MAX_RENDER)}…` : text\n}\n","// Normalizers shared by the recorder and the replay check.\n//\n// Everything here is pure. The recorder writes what these functions produce;\n// the check runs the same functions over a live engine and compares. A field\n// that is not normalized identically on both sides would read as a permanent\n// mismatch, so there is exactly one implementation.\n\nimport { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'\nimport { join, posix, relative, sep } from 'node:path'\nimport { readCellSpend } from '../../matrix'\nimport type { MultishotResult, MultishotToolDefinition, MultishotTransportRequest } from '../types'\nimport type {\n MultishotRecordedMessage,\n MultishotRecordedRequest,\n RecordedJudgeRequest,\n RecordedMultishotError,\n RecordedMultishotResult,\n} from './types'\n\n/** Keys whose value is wall clock or run identity. Two runs never agree on\n * them, so they are removed before comparison instead of being compared. */\nexport const VOLATILE_KEYS: ReadonlySet<string> = new Set([\n 'durationMs',\n 'meanDurationMs',\n 'matrixId',\n 'runId',\n])\n\nexport function recordMessage(raw: unknown): MultishotRecordedMessage {\n const row = (typeof raw === 'object' && raw !== null ? raw : {}) as Record<string, unknown>\n const message: MultishotRecordedMessage = {\n role: typeof row.role === 'string' ? row.role : '(missing role)',\n content: typeof row.content === 'string' ? row.content : null,\n }\n if (typeof row.tool_call_id === 'string') message.toolCallId = row.tool_call_id\n if (Array.isArray(row.tool_calls)) {\n message.toolCalls = row.tool_calls.map((call) => {\n const entry = (typeof call === 'object' && call !== null ? call : {}) as Record<\n string,\n unknown\n >\n const fn = (\n typeof entry.function === 'object' && entry.function !== null ? entry.function : {}\n ) as Record<string, unknown>\n return {\n id: typeof entry.id === 'string' ? entry.id : '(missing id)',\n name: typeof fn.name === 'string' ? fn.name : '(missing name)',\n arguments: typeof fn.arguments === 'string' ? fn.arguments : '(missing arguments)',\n }\n })\n }\n return message\n}\n\nexport function recordRequest(\n leg: 'agent' | 'driver',\n req: MultishotTransportRequest,\n): MultishotRecordedRequest {\n return {\n leg,\n model: req.model,\n temperature: req.temperature ?? null,\n maxTokens: req.maxTokens ?? null,\n tools: req.tools ? (JSON.parse(JSON.stringify(req.tools)) as MultishotToolDefinition[]) : null,\n messages: req.messages.map(recordMessage),\n }\n}\n\n/** Judge calls reach the wire as an OpenAI-compat body, not through a\n * transport, so they are recorded from the request body the stub receives. */\nexport function recordJudgeRequest(body: Record<string, unknown>): RecordedJudgeRequest {\n return {\n model: typeof body.model === 'string' ? body.model : '(missing model)',\n temperature: typeof body.temperature === 'number' ? body.temperature : null,\n maxTokens: typeof body.max_tokens === 'number' ? body.max_tokens : null,\n messages: Array.isArray(body.messages) ? body.messages.map(recordMessage) : [],\n }\n}\n\nexport function recordResult(result: MultishotResult): RecordedMultishotResult {\n const { durationMs: _durationMs, ...rest } = result\n return JSON.parse(JSON.stringify(rest)) as RecordedMultishotResult\n}\n\nexport function recordError(err: unknown): RecordedMultishotError {\n const spend = readCellSpend(err)\n return {\n name: err instanceof Error ? err.name : typeof err,\n message: err instanceof Error ? err.message : String(err),\n cellSpend: spend ? { costUsd: spend.costUsd, kind: spend.kind } : null,\n }\n}\n\n/** Deep copy with every wall-clock and run-identity key removed. */\nexport function stripVolatile(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(stripVolatile)\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {}\n for (const [key, entry] of Object.entries(value as Record<string, unknown>)) {\n if (VOLATILE_KEYS.has(key)) continue\n out[key] = stripVolatile(entry)\n }\n return out\n }\n return value\n}\n\n/** The matrix summary Markdown carries a rendered duration. Mask it so the rest\n * of the document — cell counts, pass rate, mean, cost, the uncaptured warning\n * — stays under comparison.\n *\n * A duration the mask does not recognise would stay in the comparison and make\n * every run mismatch on a definitionally irreproducible field, so an\n * unmaskable duration line fails loud instead. */\nexport function maskVolatileMarkdown(text: string): string {\n const masked = text.replace(/\\*\\*Duration\\*\\*: [\\d.]+\\s*(?:ms|s|m)\\b/g, '**Duration**: <elided>')\n if (/\\*\\*Duration\\*\\*: (?!<elided>)/.test(masked)) {\n throw new Error(\n `multishot golden: a rendered duration is not in a form the mask recognises — ${\n masked.match(/\\*\\*Duration\\*\\*: [^|\\n]*/)?.[0] ?? '(unreadable)'\n }`,\n )\n }\n return masked\n}\n\n/** Judge calls fan out through `Promise.all` across three slots, so their\n * issue order is an implementation detail of the cell body, not behaviour a\n * caller can observe. Their CONTENT is behaviour, so they are compared as a\n * set with a stable order. */\nexport function sortJudgeRequests(\n requests: readonly RecordedJudgeRequest[],\n): RecordedJudgeRequest[] {\n return [...requests].sort((a, b) => {\n const left = JSON.stringify(a)\n const right = JSON.stringify(b)\n return left < right ? -1 : left > right ? 1 : 0\n })\n}\n\n/** Every file under `dir`, keyed by slash-separated relative path. JSON is\n * parsed and stripped of wall-clock keys; Markdown keeps its text with the\n * rendered duration masked; anything else is kept verbatim. */\nexport function readRunDir(dir: string): Record<string, unknown> {\n if (!existsSync(dir)) {\n throw new Error(\n `multishot golden: the run directory ${dir} does not exist — the engine wrote no per-cell files`,\n )\n }\n const files: Record<string, unknown> = {}\n for (const path of walkFiles(dir)) {\n const key = relative(dir, path).split(sep).join(posix.sep)\n const text = readFileSync(path, 'utf8')\n if (path.endsWith('.json')) {\n files[key] = stripVolatile(JSON.parse(text))\n continue\n }\n files[key] = path.endsWith('.md') ? maskVolatileMarkdown(text) : text\n }\n return files\n}\n\nfunction walkFiles(dir: string): string[] {\n const out: string[] = []\n for (const entry of readdirSync(dir).sort()) {\n const path = join(dir, entry)\n if (statSync(path).isDirectory()) out.push(...walkFiles(path))\n else out.push(path)\n }\n return out\n}\n","// Deterministic multishot MATRIX scenarios.\n//\n// The shot scenarios pin one conversation. These pin the cell body around it:\n// profile x persona fan-out, the three judge slots, the cell composite, the\n// per-cell files, the run summary, and the cost provenance the cell reports.\n//\n// Cells run one at a time. Concurrency is the matrix runner's own mechanic and\n// is covered by the runner's tests; forcing it to one here makes the recorded\n// request ledger a property of the conversation engine alone, not of how two\n// engines happen to interleave their microtasks.\n\nimport type { AgentProfile } from '@tangle-network/agent-interface'\nimport type { JudgeConfig } from '../judges'\nimport type { RunMultishotMatrixOptions } from '../matrix'\nimport type {\n MultishotPersona,\n MultishotToolDefinition,\n MultishotToolExecutor,\n MultishotTransport,\n} from '../types'\nimport { recordJudgeRequest, recordRequest } from './recording'\nimport type { MultishotRecordedRequest, RecordedJudgeRequest } from './types'\n\nexport interface MultishotMatrixGoldenCase {\n options: RunMultishotMatrixOptions<MultishotPersona>\n requests: MultishotRecordedRequest[]\n /** Judge calls, filled while the case runs. Sorted before comparison. */\n judgeRequests: RecordedJudgeRequest[]\n /** Installs the deterministic judge wire on `globalThis.fetch` and returns\n * the function that restores the previous one. */\n installJudgeWire: () => () => void\n}\n\nexport interface MultishotMatrixGoldenScenario {\n readonly id: string\n readonly description: string\n readonly build: (runDir: string) => MultishotMatrixGoldenCase\n}\n\nconst JUDGE_BASE_URL = 'http://router.invalid/v1'\n\nconst personas: MultishotPersona[] = [\n { id: 'retail-founder', ask: 'a launch brief' },\n { id: 'saas-operator', ask: 'a pricing page' },\n]\n\nconst profiles: Array<{ id: string; value: AgentProfile }> = [\n {\n id: 'baseline',\n value: {\n name: 'multishot-golden-baseline',\n prompt: { systemPrompt: 'You are the baseline operator.' },\n },\n },\n {\n id: 'challenger',\n value: {\n name: 'multishot-golden-challenger',\n prompt: { systemPrompt: 'You are the challenger operator.' },\n },\n },\n]\n\nconst shape = {\n buildOpener: (p: MultishotPersona) => `I need ${String(p.ask)}. What do you need from me?`,\n buildDriverSystemPrompt: (p: MultishotPersona) => `You are ${p.id}. Demand ${String(p.ask)}.`,\n}\n\nconst tools: MultishotToolDefinition[] = [\n {\n type: 'function',\n function: { name: 'delegate_research', description: 'research', parameters: {} },\n },\n { type: 'function', function: { name: 'delegate_code', description: 'code', parameters: {} } },\n]\n\nfunction toolExecutors(): Record<string, MultishotToolExecutor> {\n return {\n delegate_research: async (args) => ({\n content: `RESEARCH: ${JSON.stringify(args)}`,\n costUsd: 0.011,\n }),\n delegate_code: async (args) => ({ content: `CODE: ${JSON.stringify(args)}`, costUsd: 0.023 }),\n }\n}\n\nconst artifactTypeFor = (name: string): string | undefined =>\n name === 'delegate_research' ? 'research' : name === 'delegate_code' ? 'code' : undefined\n\n/** Turn 1 dispatches research silently, turn 2 dispatches code beside text,\n * turn 3 answers with text — so both artifact kinds exist in every cell and\n * both artifact judge slots fire. */\nconst agentTransport: MultishotTransport = async (req) => {\n const userCount = req.messages.filter((m) => m.role === 'user').length\n const last = req.messages[req.messages.length - 1] as { role?: string }\n const afterTools = last?.role === 'tool'\n if (userCount === 1 && !afterTools) {\n return {\n message: {\n content: '',\n tool_calls: [\n {\n id: 'tc-1',\n type: 'function',\n function: { name: 'delegate_research', arguments: '{\"topic\":\"market\"}' },\n },\n ],\n },\n usage: { prompt_tokens: 100, completion_tokens: 20 },\n }\n }\n if (userCount === 1 && afterTools) {\n return {\n message: { content: 'Research done — here is the direction.' },\n usage: { prompt_tokens: 140, completion_tokens: 30 },\n costUsd: 0.005,\n }\n }\n if (userCount === 2 && !afterTools) {\n return {\n message: {\n content: 'Building it now.',\n tool_calls: [\n {\n id: 'tc-2',\n type: 'function',\n function: { name: 'delegate_code', arguments: '{\"spec\":\"landing page\"}' },\n },\n ],\n },\n usage: { prompt_tokens: 200, completion_tokens: 25 },\n costUsd: 0.004,\n }\n }\n if (userCount === 2 && afterTools) {\n return {\n message: { content: 'Shipped the artifact you asked for.' },\n usage: { prompt_tokens: 240, completion_tokens: 40 },\n costUsd: 0.006,\n }\n }\n return {\n message: { content: `Closing summary for turn ${userCount}.` },\n usage: { prompt_tokens: 260, completion_tokens: 15 },\n costUsd: 0.002,\n }\n}\n\nconst driverTransport: MultishotTransport = async (req) => {\n const priorReplies = req.messages.filter((m) => m.role === 'assistant').length\n return {\n message: { content: `Driver follow-up #${priorReplies}: sharper, please.` },\n usage: { prompt_tokens: 80, completion_tokens: 18 },\n costUsd: 0.001,\n }\n}\n\nconst dimensions = [\n { key: 'usefulness', description: 'Was it useful? (0-10)' },\n { key: 'specificity', description: 'Was it specific? (0-10)' },\n]\n\nfunction judge<TInput>(name: string, buildPrompt: (input: TInput) => string): JudgeConfig<TInput> {\n return {\n name,\n model: 'test/judge-model',\n dimensions,\n systemPrompt: `JUDGE:${name}`,\n buildPrompt,\n apiKey: 'golden-key',\n baseUrl: JUDGE_BASE_URL,\n }\n}\n\n/** True while some case holds `globalThis.fetch`. Module scope, because the\n * resource being guarded is the process's own fetch. */\nlet judgeWireInstalled = false\n\n/** Scores keyed by judge name, so the wire is a pure function of the request. */\nconst JUDGE_SCORES: Record<string, { usefulness: number; specificity: number }> = {\n conversation: { usefulness: 8, specificity: 7 },\n 'code-review': { usefulness: 6, specificity: 9 },\n 'content-quality': { usefulness: 5, specificity: 4 },\n}\n\nexport function multishotMatrixGoldenScenarios(): MultishotMatrixGoldenScenario[] {\n return [\n {\n id: 'matrix-two-profiles-two-personas',\n description:\n 'a 2x2 matrix at one replicate: every cell produces both artifact kinds, all three judge slots score, and the run persists per-cell files plus the summary',\n build: (runDir: string) => buildMatrixCase(runDir),\n },\n ]\n}\n\nfunction buildMatrixCase(runDir: string): MultishotMatrixGoldenCase {\n const requests: MultishotRecordedRequest[] = []\n const judgeRequests: RecordedJudgeRequest[] = []\n\n const options: RunMultishotMatrixOptions<MultishotPersona> = {\n profiles,\n personas,\n shape,\n judges: {\n conversation: judge(\n 'conversation',\n (input: { transcript: unknown[] }) =>\n `Score this conversation of ${input.transcript.length} messages.`,\n ),\n codeReview: judge(\n 'code-review',\n (input: { artifact: { content: string } }) => `Score this code: ${input.artifact.content}`,\n ),\n contentQuality: judge(\n 'content-quality',\n (input: { artifact: { content: string } }) =>\n `Score this content: ${input.artifact.content}`,\n ),\n },\n tools,\n toolExecutors: toolExecutors(),\n artifactTypeFor,\n runDir,\n reps: 1,\n maxTurns: 3,\n maxConcurrency: 1,\n agentModel: 'test/agent-model',\n driverModel: 'test/driver-model',\n apiKey: 'golden-key',\n baseUrl: JUDGE_BASE_URL,\n agentTransport: async (req) => {\n requests.push(recordRequest('agent', req))\n return agentTransport(req)\n },\n driverTransport: async (req) => {\n requests.push(recordRequest('driver', req))\n return driverTransport(req)\n },\n }\n\n const installJudgeWire = (): (() => void) => {\n // The wire is process-wide, so two matrix checks running at once in one\n // process would cross their judge ledgers. Refuse the second one instead of\n // recording a mixture: a golden check that silently reads another run's\n // calls reports a mismatch nobody can explain.\n if (judgeWireInstalled) {\n throw new Error(\n 'multishot golden judge wire: another matrix check already holds globalThis.fetch — run matrix checks serially within one process',\n )\n }\n judgeWireInstalled = true\n const previous = globalThis.fetch\n globalThis.fetch = (async (url: unknown, init?: { body?: string }) => {\n // The judge leg is the ONLY call allowed to reach the wire; the agent\n // and driver legs run on the scripted transports above. Anything else is\n // a wiring defect in the engine under test, so fail loud.\n if (String(url) !== `${JUDGE_BASE_URL}/chat/completions`) {\n throw new Error(`multishot golden judge wire: unexpected request to ${String(url)}`)\n }\n const body = JSON.parse(init?.body ?? '{}') as Record<string, unknown>\n judgeRequests.push(recordJudgeRequest(body))\n const messages = (body.messages ?? []) as Array<{ role: string; content: string }>\n const system = messages.find((m) => m.role === 'system')?.content ?? ''\n const name = system.replace('JUDGE:', '')\n const score = JUDGE_SCORES[name]\n if (!score) {\n throw new Error(`multishot golden judge wire: unknown judge system prompt ${system}`)\n }\n return {\n ok: true,\n status: 200,\n json: async () => ({\n choices: [{ message: { content: JSON.stringify({ ...score, notes: `${name} ok` }) } }],\n usage: { prompt_tokens: 300, completion_tokens: 25 },\n model: 'test/judge-model',\n _response_cost: 0.0007,\n }),\n text: async () => '',\n }\n }) as unknown as typeof globalThis.fetch\n return () => {\n globalThis.fetch = previous\n judgeWireInstalled = false\n }\n }\n\n return { options, requests, judgeRequests, installJudgeWire }\n}\n","","// Frozen golden-record fixtures.\n//\n// A version file is written once and never edited. A behaviour change mints a\n// new file and registers it here beside the old one, so the diff between two\n// versions is the reviewable record of what moved and the previous contract\n// stays runnable.\n\nimport type { MultishotGoldenRecordSet } from '../types'\nimport v1 from './v1.json'\n\n/** Version a check uses when the caller names none. */\nexport const CURRENT_MULTISHOT_GOLDEN_VERSION = 'v1'\n\n/** A fixture reaches this module as parsed JSON, which types cannot vouch for.\n * A record set that is not the shape the harness reads would surface as a\n * confusing mismatch on every scenario, so the shape is checked once at load\n * and named where it breaks. */\nfunction assertRecordSet(value: unknown, version: string): MultishotGoldenRecordSet {\n const fail = (reason: string): never => {\n throw new Error(`multishot golden ${version}: malformed record set — ${reason}`)\n }\n if (typeof value !== 'object' || value === null) fail('expected an object')\n const set = value as Record<string, unknown>\n for (const key of ['version', 'recordedFrom', 'recordedFromPackageVersion', 'recordedAt']) {\n if (typeof set[key] !== 'string') fail(`${key} must be a string`)\n }\n if (set.version !== version) fail(`declares version ${String(set.version)}`)\n if (!Array.isArray(set.scenarios) || set.scenarios.length === 0) {\n fail('scenarios must be a non-empty array')\n }\n if (!Array.isArray(set.matrixScenarios)) fail('matrixScenarios must be an array')\n for (const [index, entry] of (set.scenarios as unknown[]).entries()) {\n const row = entry as Record<string, unknown>\n if (typeof row?.id !== 'string') fail(`scenarios[${index}].id must be a string`)\n if (!Array.isArray(row.requests)) fail(`scenarios[${index}].requests must be an array`)\n const outcome = row.outcome as Record<string, unknown> | undefined\n if (outcome?.kind !== 'result' && outcome?.kind !== 'error') {\n fail(`scenarios[${index}].outcome.kind must be result or error`)\n }\n }\n for (const [index, entry] of (set.matrixScenarios as unknown[]).entries()) {\n const row = entry as Record<string, unknown>\n if (typeof row?.id !== 'string') fail(`matrixScenarios[${index}].id must be a string`)\n if (typeof row.files !== 'object' || row.files === null) {\n fail(`matrixScenarios[${index}].files must be an object`)\n }\n }\n return set as unknown as MultishotGoldenRecordSet\n}\n\n/** The set is handed to every caller, so a caller that mutated it would move\n * the oracle for the whole process. Freezing makes the documented immutability\n * a property of the value rather than a convention. */\nfunction deepFreeze<T>(value: T): T {\n if (value === null || typeof value !== 'object') return value\n for (const entry of Object.values(value as Record<string, unknown>)) deepFreeze(entry)\n return Object.freeze(value)\n}\n\nconst VERSIONS: Record<string, MultishotGoldenRecordSet> = {\n v1: deepFreeze(assertRecordSet(v1, 'v1')),\n}\n\nexport function multishotGoldenVersions(): string[] {\n return Object.keys(VERSIONS)\n}\n\nexport function goldenRecords(\n version: string = CURRENT_MULTISHOT_GOLDEN_VERSION,\n): MultishotGoldenRecordSet {\n const set = VERSIONS[version]\n if (!set) {\n throw new Error(\n `multishot golden: no record set for version \"${version}\" — known versions are ${multishotGoldenVersions().join(', ')}`,\n )\n }\n return set\n}\n","// Deterministic multishot scenarios.\n//\n// Every scenario is a closed system: scripted agent and driver transports,\n// scripted tool executors, a fixed persona and profile, fixed token budgets.\n// Nothing reads the clock for a recorded field, nothing calls a network, and\n// nothing draws a random number. Two runs of the same scenario on the same\n// engine produce byte-identical records; the recorder enforces that.\n//\n// The catalog is the union of the behaviours the merged loop-to-graph parity\n// proofs covered. Two scripts run through it:\n//\n// delegation-* a research/code delegation agent: silent multi-tool\n// turns, an unknown tool, typed artifacts of two kinds,\n// both cost paths, turn-count edges, driver rotation.\n// sampling-contract-* a tool-using agent with distinct per-leg token\n// budgets: retry-on-empty, whitespace-only driver\n// content, an empty assistant follow-up, full rotation.\n\nimport type { AgentProfile } from '@tangle-network/agent-interface'\nimport type { RunMultishotOptions } from '../multishot'\nimport {\n MultishotFatalToolError,\n type MultishotPersona,\n type MultishotToolDefinition,\n type MultishotToolExecutor,\n type MultishotTransport,\n type MultishotTransportResponse,\n} from '../types'\nimport { recordRequest } from './recording'\nimport type { MultishotRecordedRequest } from './types'\n\n/** Options plus the ledger the scenario's transports fill while it runs. */\nexport interface MultishotGoldenCase {\n options: RunMultishotOptions<MultishotPersona>\n /** Every transport call, in issue order. Populated by running the case. */\n requests: MultishotRecordedRequest[]\n}\n\nexport interface MultishotGoldenScenario {\n readonly id: string\n readonly description: string\n /** Fresh options and a fresh ledger. Scripted transports carry per-run\n * state, so an engine run and a re-run must never share a case. */\n readonly build: () => MultishotGoldenCase\n}\n\nfunction ledgerTransport(\n ledger: MultishotRecordedRequest[],\n leg: 'agent' | 'driver',\n inner: MultishotTransport,\n): MultishotTransport {\n return async (req) => {\n ledger.push(recordRequest(leg, req))\n return inner(req)\n }\n}\n\n// ---------------------------------------------------------------------------\n// delegation script\n// ---------------------------------------------------------------------------\n\nconst delegationPersona: MultishotPersona = { id: 'test-owner', ask: 'a launch brief' }\n\nconst delegationProfile: AgentProfile = {\n name: 'multishot-golden-delegation',\n prompt: { systemPrompt: 'You are the operator agent under test.' },\n}\n\nconst delegationShape = {\n buildOpener: (p: MultishotPersona) => `I need ${String(p.ask)}. What do you need from me?`,\n buildDriverSystemPrompt: (p: MultishotPersona) => `You are ${p.id}. Demand ${String(p.ask)}.`,\n}\n\nconst delegationTools: MultishotToolDefinition[] = [\n {\n type: 'function',\n function: { name: 'delegate_research', description: 'research', parameters: {} },\n },\n { type: 'function', function: { name: 'delegate_code', description: 'code', parameters: {} } },\n]\n\nfunction delegationExecutors(): Record<string, MultishotToolExecutor> {\n return {\n delegate_research: async (args) => ({\n content: `RESEARCH: ${JSON.stringify(args)}`,\n costUsd: 0.011,\n }),\n delegate_code: async (args) => ({ content: `CODE: ${JSON.stringify(args)}`, costUsd: 0.023 }),\n }\n}\n\nconst delegationArtifactTypeFor = (name: string): string | undefined =>\n name === 'delegate_research' ? 'research' : name === 'delegate_code' ? 'code' : undefined\n\n/** Pure in the request. The turn index is the number of `user` messages; a\n * trailing `tool` message means the follow-up call after inline execution.\n * Turn 1 is a SILENT multi-tool turn (empty content, two calls, one of them\n * an unknown tool with unparseable arguments); turn 2 dispatches one tool\n * beside text; turn 3 and later answer with text only. */\nconst delegationAgent: MultishotTransport = async (req) => {\n const userCount = req.messages.filter((m) => m.role === 'user').length\n const last = req.messages[req.messages.length - 1] as { role?: string }\n const afterTools = last?.role === 'tool'\n if (userCount === 1 && !afterTools) {\n return {\n message: {\n content: '',\n tool_calls: [\n {\n id: 'tc-1',\n type: 'function',\n function: { name: 'delegate_research', arguments: '{\"topic\":\"market\"}' },\n },\n {\n id: 'tc-2',\n type: 'function',\n function: { name: 'mystery_tool', arguments: 'not json' },\n },\n ],\n },\n usage: { prompt_tokens: 100, completion_tokens: 20 },\n }\n }\n if (userCount === 1 && afterTools) {\n return {\n message: { content: 'Research done — here is the direction.' },\n usage: { prompt_tokens: 140, completion_tokens: 30 },\n costUsd: 0.005,\n }\n }\n if (userCount === 2 && !afterTools) {\n return {\n message: {\n content: 'Building it now.',\n tool_calls: [\n {\n id: 'tc-3',\n type: 'function',\n function: { name: 'delegate_code', arguments: '{\"spec\":\"landing page\"}' },\n },\n ],\n },\n usage: { prompt_tokens: 200, completion_tokens: 25 },\n costUsd: 0.004,\n }\n }\n if (userCount === 2 && afterTools) {\n return {\n message: { content: 'Shipped the artifact you asked for.' },\n usage: { prompt_tokens: 240, completion_tokens: 40 },\n costUsd: 0.006,\n }\n }\n return {\n message: { content: `Closing summary for turn ${userCount}.` },\n usage: { prompt_tokens: 260, completion_tokens: 15 },\n costUsd: 0.002,\n }\n}\n\n/** Pure in the request: the reply indexes on how many prior driver replies the\n * point-of-view-translated conversation already carries. */\nconst delegationDriver: MultishotTransport = async (req) => {\n const priorReplies = req.messages.filter((m) => m.role === 'assistant').length\n return {\n message: { content: `Driver follow-up #${priorReplies}: sharper, please.` },\n usage: { prompt_tokens: 80, completion_tokens: 18 },\n costUsd: 0.001,\n }\n}\n\ninterface DelegationOverrides {\n maxTurns?: number\n maxToolDispatches?: number\n driverFallbackModels?: string[]\n toolExecutors?: Record<string, MultishotToolExecutor>\n agent?: MultishotTransport\n driver?: MultishotTransport\n}\n\nfunction delegationCase(overrides: DelegationOverrides = {}): MultishotGoldenCase {\n const requests: MultishotRecordedRequest[] = []\n const options: RunMultishotOptions<MultishotPersona> = {\n profile: delegationProfile,\n persona: delegationPersona,\n shape: delegationShape,\n tools: delegationTools,\n toolExecutors: overrides.toolExecutors ?? delegationExecutors(),\n artifactTypeFor: delegationArtifactTypeFor,\n maxTurns: overrides.maxTurns ?? 3,\n agentModel: 'test/agent-model',\n driverModel: 'test/driver-model',\n apiKey: 'golden-key',\n baseUrl: 'http://router.invalid',\n agentTransport: ledgerTransport(requests, 'agent', overrides.agent ?? delegationAgent),\n driverTransport: ledgerTransport(requests, 'driver', overrides.driver ?? delegationDriver),\n }\n if (overrides.maxToolDispatches !== undefined) {\n options.maxToolDispatches = overrides.maxToolDispatches\n }\n if (overrides.driverFallbackModels !== undefined) {\n options.driverFallbackModels = overrides.driverFallbackModels\n }\n return { options, requests }\n}\n\n/** Silent on the primary model, substantive on any other — the rotation path. */\nconst delegationSilentPrimaryDriver: MultishotTransport = async (req) => {\n if (req.model === 'test/driver-model') {\n return { message: { content: '' }, usage: { prompt_tokens: 10, completion_tokens: 0 } }\n }\n const priorReplies = req.messages.filter((m) => m.role === 'assistant').length\n return {\n message: { content: `Fallback follow-up #${priorReplies}.` },\n usage: { prompt_tokens: 80, completion_tokens: 18 },\n costUsd: 0.003,\n }\n}\n\nconst delegationAlwaysSilentDriver: MultishotTransport = async () => ({\n message: { content: '' },\n usage: { prompt_tokens: 10, completion_tokens: 0 },\n})\n\n/** One tool call per assistant turn, forever — walks past any dispatch cap. */\nconst delegationToolStormAgent: MultishotTransport = async (req) => ({\n message: {\n content: '',\n tool_calls: [\n {\n id: `tc-${req.messages.length}`,\n type: 'function',\n function: { name: 'delegate_research', arguments: '{}' },\n },\n ],\n },\n usage: { prompt_tokens: 10, completion_tokens: 5 },\n})\n\n// ---------------------------------------------------------------------------\n// sampling-contract script\n// ---------------------------------------------------------------------------\n\nconst SAMPLING_AGENT_MAX_TOKENS = 111\nconst SAMPLING_FOLLOWUP_MAX_TOKENS = 222\nconst SAMPLING_DRIVER_MAX_TOKENS = 333\n\nconst samplingPersona: MultishotPersona = { id: 'parity-persona', name: 'Parity Persona' }\n\nconst samplingProfile: AgentProfile = {\n name: 'multishot-golden-sampling',\n prompt: { systemPrompt: 'You are the domain agent under test.' },\n}\n\nconst samplingShape = {\n buildOpener: () => 'I need help with my CA return.',\n buildDriverSystemPrompt: (p: MultishotPersona) => `You simulate taxpayer ${p.id}.`,\n}\n\nconst samplingTools: MultishotToolDefinition[] = [\n {\n type: 'function',\n function: {\n name: 'state_tax_search',\n description: 'search state tax rules',\n parameters: { type: 'object', properties: {} },\n },\n },\n {\n type: 'function',\n function: {\n name: 'list_source_documents',\n description: 'list docs',\n parameters: { type: 'object', properties: {} },\n },\n },\n]\n\nfunction samplingExecutors(): Record<string, MultishotToolExecutor> {\n return {\n state_tax_search: async (args) => ({\n content: JSON.stringify({ ok: true, echo: args }),\n costUsd: 0.01,\n }),\n list_source_documents: async () => ({ content: '', costUsd: 0 }),\n }\n}\n\n/** A transport that answers from a fixed list and fails loud past its end. An\n * engine that issues more calls than the script has steps is a divergence,\n * not a longer conversation. */\nfunction scriptedTransport(steps: MultishotTransportResponse[], label: string): MultishotTransport {\n let index = 0\n return async () => {\n const step = steps[index++]\n if (!step) throw new Error(`${label}: unscripted call ${index}`)\n return step\n }\n}\n\n/** Three agent turns: a silent multi-tool dispatch with one unparseable\n * argument payload, a priced follow-up, a text-plus-unknown-tool turn, an\n * EMPTY follow-up with no usage at all (the uncaptured cost path), and a\n * closing answer priced from usage alone. */\nfunction samplingAgentScript(): MultishotTransportResponse[] {\n return [\n {\n message: {\n content: '',\n tool_calls: [\n {\n id: 'tc-1',\n type: 'function',\n function: { name: 'state_tax_search', arguments: '{\"state\":\"CA\"}' },\n },\n {\n id: 'tc-2',\n type: 'function',\n function: { name: 'list_source_documents', arguments: 'not-json' },\n },\n ],\n },\n usage: { prompt_tokens: 100, completion_tokens: 20 },\n },\n {\n message: { content: 'Here is my CA analysis.' },\n usage: { prompt_tokens: 140, completion_tokens: 30 },\n costUsd: 0.002,\n },\n {\n message: {\n content: 'Checking one more source.',\n tool_calls: [\n { id: 'tc-3', type: 'function', function: { name: 'mystery_tool', arguments: '{}' } },\n ],\n },\n usage: { prompt_tokens: 200, completion_tokens: 15 },\n },\n { message: { content: '' } },\n {\n message: { content: 'Final answer: file CA 540.' },\n usage: { prompt_tokens: 260, completion_tokens: 40 },\n },\n ]\n}\n\n/** Two driver turns: retry-on-empty on the primary, then a whitespace-only\n * reply that must count as empty, then full rotation to the fallback. */\nfunction samplingDriverScript(): MultishotTransportResponse[] {\n return [\n { message: { content: '' } },\n {\n message: { content: 'Follow-up question A.' },\n usage: { prompt_tokens: 50, completion_tokens: 12 },\n },\n { message: { content: '' } },\n { message: { content: ' ' } },\n { message: { content: 'Follow-up question B.' }, costUsd: 0.0004 },\n ]\n}\n\ninterface SamplingOverrides {\n maxToolDispatches?: number\n toolExecutors?: Record<string, MultishotToolExecutor>\n agentScript?: MultishotTransportResponse[]\n driverScript?: MultishotTransportResponse[]\n}\n\nfunction samplingCase(overrides: SamplingOverrides = {}): MultishotGoldenCase {\n const requests: MultishotRecordedRequest[] = []\n const options: RunMultishotOptions<MultishotPersona> = {\n profile: samplingProfile,\n persona: samplingPersona,\n shape: samplingShape,\n tools: samplingTools,\n toolExecutors: overrides.toolExecutors ?? samplingExecutors(),\n artifactTypeFor: (toolName: string) =>\n toolName.startsWith('state_tax_') ? 'state-tax-tool' : undefined,\n maxTurns: 3,\n agentMaxTokens: SAMPLING_AGENT_MAX_TOKENS,\n toolFollowupMaxTokens: SAMPLING_FOLLOWUP_MAX_TOKENS,\n driverMaxTokens: SAMPLING_DRIVER_MAX_TOKENS,\n maxToolDispatches: overrides.maxToolDispatches ?? 4,\n agentModel: 'scripted/agent',\n driverModel: 'primary/driver',\n driverFallbackModels: ['fallback/driver'],\n apiKey: 'golden-key',\n baseUrl: 'http://router.invalid',\n agentTransport: ledgerTransport(\n requests,\n 'agent',\n scriptedTransport(overrides.agentScript ?? samplingAgentScript(), 'agent transport'),\n ),\n driverTransport: ledgerTransport(\n requests,\n 'driver',\n scriptedTransport(overrides.driverScript ?? samplingDriverScript(), 'driver transport'),\n ),\n }\n return { options, requests }\n}\n\n// ---------------------------------------------------------------------------\n// catalog\n// ---------------------------------------------------------------------------\n\n/** Every recorded shot scenario, in record order. */\nexport function multishotGoldenScenarios(): MultishotGoldenScenario[] {\n return [\n {\n id: 'delegation-three-turns',\n description:\n 'three turns with a silent multi-tool dispatch, an unknown tool, both typed artifact kinds, and both cost paths',\n build: () => delegationCase(),\n },\n {\n id: 'delegation-ten-turns',\n description: 'ten turns — the function default depth, past any short driver-turn budget',\n build: () => delegationCase({ maxTurns: 10 }),\n },\n {\n id: 'delegation-zero-turns',\n description: 'maxTurns 0 returns the opener-only result and spends nothing',\n build: () => delegationCase({ maxTurns: 0 }),\n },\n {\n id: 'delegation-nan-turns',\n description: 'a non-numeric maxTurns behaves as zero turns, not as the default',\n build: () => delegationCase({ maxTurns: Number('not-a-number') }),\n },\n {\n id: 'delegation-single-turn',\n description: 'maxTurns 1 never calls the driver leg',\n build: () => delegationCase({ maxTurns: 1 }),\n },\n {\n id: 'delegation-driver-rotation',\n description: 'a silent primary driver rotates to the fallback model after two attempts',\n build: () =>\n delegationCase({\n driver: delegationSilentPrimaryDriver,\n driverFallbackModels: ['test/driver-fallback'],\n }),\n },\n {\n id: 'delegation-fatal-tool-error',\n description:\n 'MultishotFatalToolError from an executor aborts the shot and declares its spend',\n build: () =>\n delegationCase({\n toolExecutors: {\n ...delegationExecutors(),\n delegate_research: async () => {\n throw new MultishotFatalToolError('research backend down')\n },\n },\n }),\n },\n {\n id: 'delegation-driver-empty',\n description: 'a driver silent on every model raises MultishotDriverEmptyError',\n build: () => delegationCase({ driver: delegationAlwaysSilentDriver }),\n },\n {\n id: 'delegation-dispatch-cap',\n description: 'a tool storm trips the dispatch cap with the exact cap message',\n build: () =>\n delegationCase({ agent: delegationToolStormAgent, maxToolDispatches: 2, maxTurns: 3 }),\n },\n {\n id: 'sampling-contract-three-turns',\n description:\n 'per-leg token budgets, driver retry-on-empty, a whitespace-only driver reply, an empty assistant follow-up with no usage, and full rotation',\n build: () => samplingCase(),\n },\n {\n id: 'sampling-contract-fatal-tool-error',\n description: 'MultishotFatalToolError propagates unchanged out of the first tool dispatch',\n build: () =>\n samplingCase({\n toolExecutors: {\n state_tax_search: async () => {\n throw new MultishotFatalToolError('citation budget exhausted')\n },\n list_source_documents: async () => ({ content: '', costUsd: 0 }),\n },\n }),\n },\n {\n id: 'sampling-contract-driver-empty-after-rotation',\n description:\n 'MultishotDriverEmptyError names the turn only after both attempts on both models',\n build: () =>\n samplingCase({\n driverScript: [\n { message: { content: '' } },\n { message: { content: '' } },\n { message: { content: '' } },\n { message: { content: '' } },\n ],\n }),\n },\n {\n id: 'sampling-contract-dispatch-cap',\n description: 'three calls against a cap of two fail loud on turn 0',\n build: () =>\n samplingCase({\n maxToolDispatches: 2,\n agentScript: [\n {\n message: {\n content: '',\n tool_calls: [1, 2, 3].map((n) => ({\n id: `tc-${n}`,\n type: 'function' as const,\n function: { name: 'state_tax_search', arguments: '{}' },\n })),\n },\n },\n ],\n driverScript: [],\n }),\n },\n ]\n}\n","// The check a conversation engine runs against the golden records.\n//\n// The harness owns the whole comparison: it builds the scenario, runs the\n// engine, normalizes what came back exactly as the recorder did, and reports\n// every field that moved. It asserts through a thrown error rather than a test\n// framework, so a consumer on vitest, node:test, or a plain script all use the\n// same call.\n\nimport type { RunMultishotMatrixResult } from '../matrix'\nimport { compareJson } from './compare'\nimport type { MultishotGoldenEngine, MultishotMatrixGoldenEngine } from './engine'\nimport {\n type MultishotMatrixGoldenScenario,\n multishotMatrixGoldenScenarios,\n} from './matrix-scenarios'\nimport {\n readRunDir,\n recordError,\n recordResult,\n sortJudgeRequests,\n stripVolatile,\n} from './recording'\nimport { goldenRecords } from './records'\nimport { type MultishotGoldenScenario, multishotGoldenScenarios } from './scenarios'\nimport type {\n MultishotGoldenRecord,\n MultishotGoldenRecordSet,\n MultishotMatrixGoldenRecord,\n} from './types'\n\nexport interface MultishotGoldenScenarioReport {\n id: string\n description: string\n ok: boolean\n mismatches: string[]\n}\n\nexport interface MultishotGoldenReport {\n version: string\n recordedFrom: string\n ok: boolean\n scenarios: MultishotGoldenScenarioReport[]\n}\n\nexport class MultishotGoldenMismatchError extends Error {\n constructor(\n readonly scenarioId: string,\n readonly mismatches: string[],\n readonly version: string,\n ) {\n super(\n [\n `multishot golden ${version} — scenario \"${scenarioId}\" diverged from the record:`,\n ...mismatches.map((line) => ` - ${line}`),\n ].join('\\n'),\n )\n this.name = 'MultishotGoldenMismatchError'\n }\n}\n\nfunction requireRecord(records: MultishotGoldenRecordSet, id: string): MultishotGoldenRecord {\n const record = records.scenarios.find((entry) => entry.id === id)\n if (!record) {\n throw new Error(\n `multishot golden ${records.version} holds no record for scenario \"${id}\" — regenerate the fixture for the new scenario`,\n )\n }\n return record\n}\n\nfunction requireMatrixRecord(\n records: MultishotGoldenRecordSet,\n id: string,\n): MultishotMatrixGoldenRecord {\n const record = records.matrixScenarios.find((entry) => entry.id === id)\n if (!record) {\n throw new Error(\n `multishot golden ${records.version} holds no matrix record for scenario \"${id}\" — regenerate the fixture for the new scenario`,\n )\n }\n return record\n}\n\n/** Run one scenario and report every field that diverged from the record. */\nexport async function checkMultishotGoldenScenario(opts: {\n engine: MultishotGoldenEngine\n scenario: MultishotGoldenScenario\n records?: MultishotGoldenRecordSet\n}): Promise<MultishotGoldenScenarioReport> {\n const records = opts.records ?? goldenRecords()\n const record = requireRecord(records, opts.scenario.id)\n const runCase = opts.scenario.build()\n\n let observed: MultishotGoldenRecord['outcome']\n const mismatches: string[] = []\n try {\n const result = await opts.engine(runCase.options)\n observed = { kind: 'result', result: recordResult(result) }\n // durationMs is wall clock and is excluded from the record, but it is still\n // part of the contract: a result must report a usable duration. It joins the\n // other mismatches rather than replacing them, so one bad field cannot hide\n // the rest of a divergent run.\n if (!isUsableDuration(result.durationMs)) {\n mismatches.push(\n `durationMs: expected a finite number >= 0, received ${String(result.durationMs)}`,\n )\n }\n } catch (err) {\n observed = { kind: 'error', error: recordError(err) }\n }\n\n mismatches.push(\n ...compareJson(record.outcome, observed, 'outcome'),\n ...compareJson(record.requests, runCase.requests, 'requests'),\n )\n return {\n id: opts.scenario.id,\n description: opts.scenario.description,\n ok: mismatches.length === 0,\n mismatches,\n }\n}\n\n/** Same as `checkMultishotGoldenScenario`, but throws on divergence. */\nexport async function assertMultishotGoldenScenario(opts: {\n engine: MultishotGoldenEngine\n scenario: MultishotGoldenScenario\n records?: MultishotGoldenRecordSet\n}): Promise<void> {\n const records = opts.records ?? goldenRecords()\n const report = await checkMultishotGoldenScenario({ ...opts, records })\n if (!report.ok) {\n throw new MultishotGoldenMismatchError(report.id, report.mismatches, records.version)\n }\n}\n\n/** Run every shot scenario. Never throws on divergence — read `ok`. */\nexport async function checkMultishotGolden(opts: {\n engine: MultishotGoldenEngine\n records?: MultishotGoldenRecordSet\n only?: string[]\n}): Promise<MultishotGoldenReport> {\n const records = opts.records ?? goldenRecords()\n const catalog = multishotGoldenScenarios()\n const wanted = opts.only ? new Set(opts.only) : undefined\n if (wanted) {\n // An id that names no scenario would silently shrink the run, and a run of\n // zero scenarios reports ok. A stale id after a rename must stop the check,\n // not green it.\n const unknown = [...wanted].filter((id) => !catalog.some((s) => s.id === id)).sort()\n if (unknown.length > 0) {\n throw new Error(\n `multishot golden: \\`only\\` names ${unknown.length === 1 ? 'a scenario' : 'scenarios'} the catalog does not hold: ${unknown.join(', ')}`,\n )\n }\n }\n const scenarios = catalog.filter((s) => !wanted || wanted.has(s.id))\n const reports: MultishotGoldenScenarioReport[] = []\n for (const scenario of scenarios) {\n reports.push(await checkMultishotGoldenScenario({ engine: opts.engine, scenario, records }))\n }\n return {\n version: records.version,\n recordedFrom: records.recordedFrom,\n ok: reports.every((report) => report.ok),\n scenarios: reports,\n }\n}\n\n/** Run one matrix scenario against `runDir` and report every divergence. */\nexport async function checkMultishotMatrixGoldenScenario(opts: {\n engine: MultishotMatrixGoldenEngine\n scenario: MultishotMatrixGoldenScenario\n /** An empty directory the engine may write its per-cell files into. */\n runDir: string\n records?: MultishotGoldenRecordSet\n}): Promise<MultishotGoldenScenarioReport> {\n const records = opts.records ?? goldenRecords()\n const record = requireMatrixRecord(records, opts.scenario.id)\n const runCase = opts.scenario.build(opts.runDir)\n const restore = runCase.installJudgeWire()\n let matrix: RunMultishotMatrixResult\n try {\n matrix = await opts.engine(runCase.options)\n } finally {\n restore()\n }\n\n const mismatches = [\n ...compareJson(record.matrix, stripVolatile(matrix.matrix), 'matrix'),\n ...compareJson(record.requests, runCase.requests, 'requests'),\n ...compareJson(record.judgeRequests, sortJudgeRequests(runCase.judgeRequests), 'judgeRequests'),\n ...compareJson(record.files, readRunDir(opts.runDir), 'files'),\n ]\n return {\n id: opts.scenario.id,\n description: opts.scenario.description,\n ok: mismatches.length === 0,\n mismatches,\n }\n}\n\nexport async function assertMultishotMatrixGoldenScenario(opts: {\n engine: MultishotMatrixGoldenEngine\n scenario: MultishotMatrixGoldenScenario\n runDir: string\n records?: MultishotGoldenRecordSet\n}): Promise<void> {\n const records = opts.records ?? goldenRecords()\n const report = await checkMultishotMatrixGoldenScenario({ ...opts, records })\n if (!report.ok) {\n throw new MultishotGoldenMismatchError(report.id, report.mismatches, records.version)\n }\n}\n\n/** A duration a caller can read: finite and not negative. */\nexport function isUsableDuration(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0\n}\n\nexport { multishotGoldenScenarios, multishotMatrixGoldenScenarios }\n"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AErRA,MAAa,mCAAmC;;;;;AAMhD,SAAS,gBAAgB,OAAgB,SAA2C;CAClF,MAAM,QAAQ,WAA0B;EACtC,MAAM,IAAI,MAAM,oBAAoB,QAAQ,2BAA2B,QAAQ;CACjF;CACA,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,KAAK,oBAAoB;CAC1E,MAAM,MAAM;CACZ,KAAK,MAAM,OAAO;EAAC;EAAW;EAAgB;EAA8B;CAAY,GACtF,IAAI,OAAO,IAAI,SAAS,UAAU,KAAK,GAAG,IAAI,kBAAkB;CAElE,IAAI,IAAI,YAAY,SAAS,KAAK,oBAAoB,OAAO,IAAI,OAAO,GAAG;CAC3E,IAAI,CAAC,MAAM,QAAQ,IAAI,SAAS,KAAK,IAAI,UAAU,WAAW,GAC5D,KAAK,qCAAqC;CAE5C,IAAI,CAAC,MAAM,QAAQ,IAAI,eAAe,GAAG,KAAK,kCAAkC;CAChF,KAAK,MAAM,CAAC,OAAO,UAAW,IAAI,UAAwB,QAAQ,GAAG;EACnE,MAAM,MAAM;EACZ,IAAI,OAAO,KAAK,OAAO,UAAU,KAAK,aAAa,MAAM,sBAAsB;EAC/E,IAAI,CAAC,MAAM,QAAQ,IAAI,QAAQ,GAAG,KAAK,aAAa,MAAM,4BAA4B;EACtF,MAAM,UAAU,IAAI;EACpB,IAAI,SAAS,SAAS,YAAY,SAAS,SAAS,SAClD,KAAK,aAAa,MAAM,uCAAuC;CAEnE;CACA,KAAK,MAAM,CAAC,OAAO,UAAW,IAAI,gBAA8B,QAAQ,GAAG;EACzE,MAAM,MAAM;EACZ,IAAI,OAAO,KAAK,OAAO,UAAU,KAAK,mBAAmB,MAAM,sBAAsB;EACrF,IAAI,OAAO,IAAI,UAAU,YAAY,IAAI,UAAU,MACjD,KAAK,mBAAmB,MAAM,0BAA0B;CAE5D;CACA,OAAO;AACT;;;;AAKA,SAAS,WAAc,OAAa;CAClC,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU,OAAO;CACxD,KAAK,MAAM,SAAS,OAAO,OAAO,KAAgC,GAAG,WAAW,KAAK;CACrF,OAAO,OAAO,OAAO,KAAK;AAC5B;AAEA,MAAM,WAAqD,EACzD,IAAI,WAAW,gBAAgBA,YAAI,IAAI,CAAC,EAC1C;AAEA,SAAgB,0BAAoC;CAClD,OAAO,OAAO,KAAK,QAAQ;AAC7B;AAEA,SAAgB,cACd,UAAA,MAC0B;CAC1B,MAAM,MAAM,SAAS;CACrB,IAAI,CAAC,KACH,MAAM,IAAI,MACR,gDAAgD,QAAQ,yBAAyB,wBAAwB,CAAC,CAAC,KAAK,IAAI,GACtH;CAEF,OAAO;AACT;;;AC/BA,SAAS,gBACP,QACA,KACA,OACoB;CACpB,OAAO,OAAO,QAAQ;EACpB,OAAO,KAAK,cAAc,KAAK,GAAG,CAAC;EACnC,OAAO,MAAM,GAAG;CAClB;AACF;AAMA,MAAM,oBAAsC;CAAE,IAAI;CAAc,KAAK;AAAiB;AAEtF,MAAM,oBAAkC;CACtC,MAAM;CACN,QAAQ,EAAE,cAAc,yCAAyC;AACnE;AAEA,MAAM,kBAAkB;CACtB,cAAc,MAAwB,UAAU,OAAO,EAAE,GAAG,EAAE;CAC9D,0BAA0B,MAAwB,WAAW,EAAE,GAAG,WAAW,OAAO,EAAE,GAAG,EAAE;AAC7F;AAEA,MAAM,kBAA6C,CACjD;CACE,MAAM;CACN,UAAU;EAAE,MAAM;EAAqB,aAAa;EAAY,YAAY,CAAC;CAAE;AACjF,GACA;CAAE,MAAM;CAAY,UAAU;EAAE,MAAM;EAAiB,aAAa;EAAQ,YAAY,CAAC;CAAE;AAAE,CAC/F;AAEA,SAAS,sBAA6D;CACpE,OAAO;EACL,mBAAmB,OAAO,UAAU;GAClC,SAAS,aAAa,KAAK,UAAU,IAAI;GACzC,SAAS;EACX;EACA,eAAe,OAAO,UAAU;GAAE,SAAS,SAAS,KAAK,UAAU,IAAI;GAAK,SAAS;EAAM;CAC7F;AACF;AAEA,MAAM,6BAA6B,SACjC,SAAS,sBAAsB,aAAa,SAAS,kBAAkB,SAAS,KAAA;;;;;;AAOlF,MAAM,kBAAsC,OAAO,QAAQ;CACzD,MAAM,YAAY,IAAI,SAAS,QAAQ,MAAM,EAAE,SAAS,MAAM,CAAC,CAAC;CAEhE,MAAM,aADO,IAAI,SAAS,IAAI,SAAS,SAAS,EACzB,EAAE,SAAS;CAClC,IAAI,cAAc,KAAK,CAAC,YACtB,OAAO;EACL,SAAS;GACP,SAAS;GACT,YAAY,CACV;IACE,IAAI;IACJ,MAAM;IACN,UAAU;KAAE,MAAM;KAAqB,WAAW;IAAqB;GACzE,GACA;IACE,IAAI;IACJ,MAAM;IACN,UAAU;KAAE,MAAM;KAAgB,WAAW;IAAW;GAC1D,CACF;EACF;EACA,OAAO;GAAE,eAAe;GAAK,mBAAmB;EAAG;CACrD;CAEF,IAAI,cAAc,KAAK,YACrB,OAAO;EACL,SAAS,EAAE,SAAS,yCAAyC;EAC7D,OAAO;GAAE,eAAe;GAAK,mBAAmB;EAAG;EACnD,SAAS;CACX;CAEF,IAAI,cAAc,KAAK,CAAC,YACtB,OAAO;EACL,SAAS;GACP,SAAS;GACT,YAAY,CACV;IACE,IAAI;IACJ,MAAM;IACN,UAAU;KAAE,MAAM;KAAiB,WAAW;IAA0B;GAC1E,CACF;EACF;EACA,OAAO;GAAE,eAAe;GAAK,mBAAmB;EAAG;EACnD,SAAS;CACX;CAEF,IAAI,cAAc,KAAK,YACrB,OAAO;EACL,SAAS,EAAE,SAAS,sCAAsC;EAC1D,OAAO;GAAE,eAAe;GAAK,mBAAmB;EAAG;EACnD,SAAS;CACX;CAEF,OAAO;EACL,SAAS,EAAE,SAAS,4BAA4B,UAAU,GAAG;EAC7D,OAAO;GAAE,eAAe;GAAK,mBAAmB;EAAG;EACnD,SAAS;CACX;AACF;;;AAIA,MAAM,mBAAuC,OAAO,QAAQ;CAE1D,OAAO;EACL,SAAS,EAAE,SAAS,qBAFD,IAAI,SAAS,QAAQ,MAAM,EAAE,SAAS,WAAW,CAAC,CAAC,OAEhB,oBAAoB;EAC1E,OAAO;GAAE,eAAe;GAAI,mBAAmB;EAAG;EAClD,SAAS;CACX;AACF;AAWA,SAAS,eAAe,YAAiC,CAAC,GAAwB;CAChF,MAAM,WAAuC,CAAC;CAC9C,MAAM,UAAiD;EACrD,SAAS;EACT,SAAS;EACT,OAAO;EACP,OAAO;EACP,eAAe,UAAU,iBAAiB,oBAAoB;EAC9D,iBAAiB;EACjB,UAAU,UAAU,YAAY;EAChC,YAAY;EACZ,aAAa;EACb,QAAQ;EACR,SAAS;EACT,gBAAgB,gBAAgB,UAAU,SAAS,UAAU,SAAS,eAAe;EACrF,iBAAiB,gBAAgB,UAAU,UAAU,UAAU,UAAU,gBAAgB;CAC3F;CACA,IAAI,UAAU,sBAAsB,KAAA,GAClC,QAAQ,oBAAoB,UAAU;CAExC,IAAI,UAAU,yBAAyB,KAAA,GACrC,QAAQ,uBAAuB,UAAU;CAE3C,OAAO;EAAE;EAAS;CAAS;AAC7B;;AAGA,MAAM,gCAAoD,OAAO,QAAQ;CACvE,IAAI,IAAI,UAAU,qBAChB,OAAO;EAAE,SAAS,EAAE,SAAS,GAAG;EAAG,OAAO;GAAE,eAAe;GAAI,mBAAmB;EAAE;CAAE;CAGxF,OAAO;EACL,SAAS,EAAE,SAAS,uBAFD,IAAI,SAAS,QAAQ,MAAM,EAAE,SAAS,WAAW,CAAC,CAAC,OAEd,GAAG;EAC3D,OAAO;GAAE,eAAe;GAAI,mBAAmB;EAAG;EAClD,SAAS;CACX;AACF;AAEA,MAAM,+BAAmD,aAAa;CACpE,SAAS,EAAE,SAAS,GAAG;CACvB,OAAO;EAAE,eAAe;EAAI,mBAAmB;CAAE;AACnD;;AAGA,MAAM,2BAA+C,OAAO,SAAS;CACnE,SAAS;EACP,SAAS;EACT,YAAY,CACV;GACE,IAAI,MAAM,IAAI,SAAS;GACvB,MAAM;GACN,UAAU;IAAE,MAAM;IAAqB,WAAW;GAAK;EACzD,CACF;CACF;CACA,OAAO;EAAE,eAAe;EAAI,mBAAmB;CAAE;AACnD;AAMA,MAAM,4BAA4B;AAClC,MAAM,+BAA+B;AACrC,MAAM,6BAA6B;AAEnC,MAAM,kBAAoC;CAAE,IAAI;CAAkB,MAAM;AAAiB;AAEzF,MAAM,kBAAgC;CACpC,MAAM;CACN,QAAQ,EAAE,cAAc,uCAAuC;AACjE;AAEA,MAAM,gBAAgB;CACpB,mBAAmB;CACnB,0BAA0B,MAAwB,yBAAyB,EAAE,GAAG;AAClF;AAEA,MAAM,gBAA2C,CAC/C;CACE,MAAM;CACN,UAAU;EACR,MAAM;EACN,aAAa;EACb,YAAY;GAAE,MAAM;GAAU,YAAY,CAAC;EAAE;CAC/C;AACF,GACA;CACE,MAAM;CACN,UAAU;EACR,MAAM;EACN,aAAa;EACb,YAAY;GAAE,MAAM;GAAU,YAAY,CAAC;EAAE;CAC/C;AACF,CACF;AAEA,SAAS,oBAA2D;CAClE,OAAO;EACL,kBAAkB,OAAO,UAAU;GACjC,SAAS,KAAK,UAAU;IAAE,IAAI;IAAM,MAAM;GAAK,CAAC;GAChD,SAAS;EACX;EACA,uBAAuB,aAAa;GAAE,SAAS;GAAI,SAAS;EAAE;CAChE;AACF;;;;AAKA,SAAS,kBAAkB,OAAqC,OAAmC;CACjG,IAAI,QAAQ;CACZ,OAAO,YAAY;EACjB,MAAM,OAAO,MAAM;EACnB,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,GAAG,MAAM,oBAAoB,OAAO;EAC/D,OAAO;CACT;AACF;;;;;AAMA,SAAS,sBAAoD;CAC3D,OAAO;EACL;GACE,SAAS;IACP,SAAS;IACT,YAAY,CACV;KACE,IAAI;KACJ,MAAM;KACN,UAAU;MAAE,MAAM;MAAoB,WAAW;KAAiB;IACpE,GACA;KACE,IAAI;KACJ,MAAM;KACN,UAAU;MAAE,MAAM;MAAyB,WAAW;KAAW;IACnE,CACF;GACF;GACA,OAAO;IAAE,eAAe;IAAK,mBAAmB;GAAG;EACrD;EACA;GACE,SAAS,EAAE,SAAS,0BAA0B;GAC9C,OAAO;IAAE,eAAe;IAAK,mBAAmB;GAAG;GACnD,SAAS;EACX;EACA;GACE,SAAS;IACP,SAAS;IACT,YAAY,CACV;KAAE,IAAI;KAAQ,MAAM;KAAY,UAAU;MAAE,MAAM;MAAgB,WAAW;KAAK;IAAE,CACtF;GACF;GACA,OAAO;IAAE,eAAe;IAAK,mBAAmB;GAAG;EACrD;EACA,EAAE,SAAS,EAAE,SAAS,GAAG,EAAE;EAC3B;GACE,SAAS,EAAE,SAAS,6BAA6B;GACjD,OAAO;IAAE,eAAe;IAAK,mBAAmB;GAAG;EACrD;CACF;AACF;;;AAIA,SAAS,uBAAqD;CAC5D,OAAO;EACL,EAAE,SAAS,EAAE,SAAS,GAAG,EAAE;EAC3B;GACE,SAAS,EAAE,SAAS,wBAAwB;GAC5C,OAAO;IAAE,eAAe;IAAI,mBAAmB;GAAG;EACpD;EACA,EAAE,SAAS,EAAE,SAAS,GAAG,EAAE;EAC3B,EAAE,SAAS,EAAE,SAAS,KAAK,EAAE;EAC7B;GAAE,SAAS,EAAE,SAAS,wBAAwB;GAAG,SAAS;EAAO;CACnE;AACF;AASA,SAAS,aAAa,YAA+B,CAAC,GAAwB;CAC5E,MAAM,WAAuC,CAAC;CA8B9C,OAAO;EAAE,SAAA;GA5BP,SAAS;GACT,SAAS;GACT,OAAO;GACP,OAAO;GACP,eAAe,UAAU,iBAAiB,kBAAkB;GAC5D,kBAAkB,aAChB,SAAS,WAAW,YAAY,IAAI,mBAAmB,KAAA;GACzD,UAAU;GACV,gBAAgB;GAChB,uBAAuB;GACvB,iBAAiB;GACjB,mBAAmB,UAAU,qBAAqB;GAClD,YAAY;GACZ,aAAa;GACb,sBAAsB,CAAC,iBAAiB;GACxC,QAAQ;GACR,SAAS;GACT,gBAAgB,gBACd,UACA,SACA,kBAAkB,UAAU,eAAe,oBAAoB,GAAG,iBAAiB,CACrF;GACA,iBAAiB,gBACf,UACA,UACA,kBAAkB,UAAU,gBAAgB,qBAAqB,GAAG,kBAAkB,CACxF;EAEa;EAAG;CAAS;AAC7B;;AAOA,SAAgB,2BAAsD;CACpE,OAAO;EACL;GACE,IAAI;GACJ,aACE;GACF,aAAa,eAAe;EAC9B;EACA;GACE,IAAI;GACJ,aAAa;GACb,aAAa,eAAe,EAAE,UAAU,GAAG,CAAC;EAC9C;EACA;GACE,IAAI;GACJ,aAAa;GACb,aAAa,eAAe,EAAE,UAAU,EAAE,CAAC;EAC7C;EACA;GACE,IAAI;GACJ,aAAa;GACb,aAAa,eAAe,EAAE,UAAU,IAAuB,CAAC;EAClE;EACA;GACE,IAAI;GACJ,aAAa;GACb,aAAa,eAAe,EAAE,UAAU,EAAE,CAAC;EAC7C;EACA;GACE,IAAI;GACJ,aAAa;GACb,aACE,eAAe;IACb,QAAQ;IACR,sBAAsB,CAAC,sBAAsB;GAC/C,CAAC;EACL;EACA;GACE,IAAI;GACJ,aACE;GACF,aACE,eAAe,EACb,eAAe;IACb,GAAG,oBAAoB;IACvB,mBAAmB,YAAY;KAC7B,MAAM,IAAI,wBAAwB,uBAAuB;IAC3D;GACF,EACF,CAAC;EACL;EACA;GACE,IAAI;GACJ,aAAa;GACb,aAAa,eAAe,EAAE,QAAQ,6BAA6B,CAAC;EACtE;EACA;GACE,IAAI;GACJ,aAAa;GACb,aACE,eAAe;IAAE,OAAO;IAA0B,mBAAmB;IAAG,UAAU;GAAE,CAAC;EACzF;EACA;GACE,IAAI;GACJ,aACE;GACF,aAAa,aAAa;EAC5B;EACA;GACE,IAAI;GACJ,aAAa;GACb,aACE,aAAa,EACX,eAAe;IACb,kBAAkB,YAAY;KAC5B,MAAM,IAAI,wBAAwB,2BAA2B;IAC/D;IACA,uBAAuB,aAAa;KAAE,SAAS;KAAI,SAAS;IAAE;GAChE,EACF,CAAC;EACL;EACA;GACE,IAAI;GACJ,aACE;GACF,aACE,aAAa,EACX,cAAc;IACZ,EAAE,SAAS,EAAE,SAAS,GAAG,EAAE;IAC3B,EAAE,SAAS,EAAE,SAAS,GAAG,EAAE;IAC3B,EAAE,SAAS,EAAE,SAAS,GAAG,EAAE;IAC3B,EAAE,SAAS,EAAE,SAAS,GAAG,EAAE;GAC7B,EACF,CAAC;EACL;EACA;GACE,IAAI;GACJ,aAAa;GACb,aACE,aAAa;IACX,mBAAmB;IACnB,aAAa,CACX,EACE,SAAS;KACP,SAAS;KACT,YAAY;MAAC;MAAG;MAAG;KAAC,CAAC,CAAC,KAAK,OAAO;MAChC,IAAI,MAAM;MACV,MAAM;MACN,UAAU;OAAE,MAAM;OAAoB,WAAW;MAAK;KACxD,EAAE;IACJ,EACF,CACF;IACA,cAAc,CAAC;GACjB,CAAC;EACL;CACF;AACF;;;ACheA,IAAa,+BAAb,cAAkD,MAAM;CAE3C;CACA;CACA;CAHX,YACE,YACA,YACA,SACA;EACA,MACE,CACE,oBAAoB,QAAQ,eAAe,WAAW,8BACtD,GAAG,WAAW,KAAK,SAAS,OAAO,MAAM,CAC3C,CAAC,CAAC,KAAK,IAAI,CACb;EATS,KAAA,aAAA;EACA,KAAA,aAAA;EACA,KAAA,UAAA;EAQT,KAAK,OAAO;CACd;AACF;AAEA,SAAS,cAAc,SAAmC,IAAmC;CAC3F,MAAM,SAAS,QAAQ,UAAU,MAAM,UAAU,MAAM,OAAO,EAAE;CAChE,IAAI,CAAC,QACH,MAAM,IAAI,MACR,oBAAoB,QAAQ,QAAQ,iCAAiC,GAAG,gDAC1E;CAEF,OAAO;AACT;AAEA,SAAS,oBACP,SACA,IAC6B;CAC7B,MAAM,SAAS,QAAQ,gBAAgB,MAAM,UAAU,MAAM,OAAO,EAAE;CACtE,IAAI,CAAC,QACH,MAAM,IAAI,MACR,oBAAoB,QAAQ,QAAQ,wCAAwC,GAAG,gDACjF;CAEF,OAAO;AACT;;AAGA,eAAsB,6BAA6B,MAIR;CAEzC,MAAM,SAAS,cADC,KAAK,WAAW,cAAc,GACR,KAAK,SAAS,EAAE;CACtD,MAAM,UAAU,KAAK,SAAS,MAAM;CAEpC,IAAI;CACJ,MAAM,aAAuB,CAAC;CAC9B,IAAI;EACF,MAAM,SAAS,MAAM,KAAK,OAAO,QAAQ,OAAO;EAChD,WAAW;GAAE,MAAM;GAAU,QAAQ,aAAa,MAAM;EAAE;EAK1D,IAAI,CAAC,iBAAiB,OAAO,UAAU,GACrC,WAAW,KACT,uDAAuD,OAAO,OAAO,UAAU,GACjF;CAEJ,SAAS,KAAK;EACZ,WAAW;GAAE,MAAM;GAAS,OAAO,YAAY,GAAG;EAAE;CACtD;CAEA,WAAW,KACT,GAAG,YAAY,OAAO,SAAS,UAAU,SAAS,GAClD,GAAG,YAAY,OAAO,UAAU,QAAQ,UAAU,UAAU,CAC9D;CACA,OAAO;EACL,IAAI,KAAK,SAAS;EAClB,aAAa,KAAK,SAAS;EAC3B,IAAI,WAAW,WAAW;EAC1B;CACF;AACF;;AAGA,eAAsB,8BAA8B,MAIlC;CAChB,MAAM,UAAU,KAAK,WAAW,cAAc;CAC9C,MAAM,SAAS,MAAM,6BAA6B;EAAE,GAAG;EAAM;CAAQ,CAAC;CACtE,IAAI,CAAC,OAAO,IACV,MAAM,IAAI,6BAA6B,OAAO,IAAI,OAAO,YAAY,QAAQ,OAAO;AAExF;;AAGA,eAAsB,qBAAqB,MAIR;CACjC,MAAM,UAAU,KAAK,WAAW,cAAc;CAC9C,MAAM,UAAU,yBAAyB;CACzC,MAAM,SAAS,KAAK,OAAO,IAAI,IAAI,KAAK,IAAI,IAAI,KAAA;CAChD,IAAI,QAAQ;EAIV,MAAM,UAAU,CAAC,GAAG,MAAM,CAAC,CAAC,QAAQ,OAAO,CAAC,QAAQ,MAAM,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK;EACnF,IAAI,QAAQ,SAAS,GACnB,MAAM,IAAI,MACR,oCAAoC,QAAQ,WAAW,IAAI,eAAe,YAAY,8BAA8B,QAAQ,KAAK,IAAI,GACvI;CAEJ;CACA,MAAM,YAAY,QAAQ,QAAQ,MAAM,CAAC,UAAU,OAAO,IAAI,EAAE,EAAE,CAAC;CACnE,MAAM,UAA2C,CAAC;CAClD,KAAK,MAAM,YAAY,WACrB,QAAQ,KAAK,MAAM,6BAA6B;EAAE,QAAQ,KAAK;EAAQ;EAAU;CAAQ,CAAC,CAAC;CAE7F,OAAO;EACL,SAAS,QAAQ;EACjB,cAAc,QAAQ;EACtB,IAAI,QAAQ,OAAO,WAAW,OAAO,EAAE;EACvC,WAAW;CACb;AACF;;AAGA,eAAsB,mCAAmC,MAMd;CAEzC,MAAM,SAAS,oBADC,KAAK,WAAW,cAAc,GACF,KAAK,SAAS,EAAE;CAC5D,MAAM,UAAU,KAAK,SAAS,MAAM,KAAK,MAAM;CAC/C,MAAM,UAAU,QAAQ,iBAAiB;CACzC,IAAI;CACJ,IAAI;EACF,SAAS,MAAM,KAAK,OAAO,QAAQ,OAAO;CAC5C,UAAU;EACR,QAAQ;CACV;CAEA,MAAM,aAAa;EACjB,GAAG,YAAY,OAAO,QAAQ,cAAc,OAAO,MAAM,GAAG,QAAQ;EACpE,GAAG,YAAY,OAAO,UAAU,QAAQ,UAAU,UAAU;EAC5D,GAAG,YAAY,OAAO,eAAe,kBAAkB,QAAQ,aAAa,GAAG,eAAe;EAC9F,GAAG,YAAY,OAAO,OAAO,WAAW,KAAK,MAAM,GAAG,OAAO;CAC/D;CACA,OAAO;EACL,IAAI,KAAK,SAAS;EAClB,aAAa,KAAK,SAAS;EAC3B,IAAI,WAAW,WAAW;EAC1B;CACF;AACF;AAEA,eAAsB,oCAAoC,MAKxC;CAChB,MAAM,UAAU,KAAK,WAAW,cAAc;CAC9C,MAAM,SAAS,MAAM,mCAAmC;EAAE,GAAG;EAAM;CAAQ,CAAC;CAC5E,IAAI,CAAC,OAAO,IACV,MAAM,IAAI,6BAA6B,OAAO,IAAI,OAAO,YAAY,QAAQ,OAAO;AAExF;;AAGA,SAAgB,iBAAiB,OAAiC;CAChE,OAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,SAAS;AACzE"}
@@ -1,147 +1,6 @@
1
- import { p as CostProvenance } from "../cost-ledger-DbQdN3nO.js";
2
1
  import { w as JudgeScore } from "../types-DABZgDGV.js";
3
- import { o as MatrixResult } from "../index-D_P7Ye43.js";
2
+ import { A as JudgeConfig, C as MultishotToolExecutor, D as MultishotTransportToolCall, E as MultishotTransportResponse, F as runJudge, M as JudgeRunResult, N as renderDimensions, O as assertMultishotShotResult, P as renderJsonFooter, S as MultishotToolDefinition, T as MultishotTransportRequest, _ as MultishotMessage, a as MultishotCellOutput, b as MultishotShape, c as RunMultishotMatrixResult, d as MultishotShot, f as RunMultishotOptions, g as MultishotFatalToolError, h as MultishotDriverEmptyError, i as ConversationJudgeInput, j as JudgeDimension, k as DEFAULT_JUDGE_MODEL, l as computeCellComposite, m as MultishotArtifact, n as CellCompositeInput, o as MultishotJudges, p as runMultishot, r as CellCompositeScore, s as RunMultishotMatrixOptions, t as ArtifactJudgeInput, u as runMultishotMatrix, v as MultishotPersona, w as MultishotTransport, x as MultishotShotResultError, y as MultishotResult } from "../matrix-su7mIfbB.js";
4
3
  import { AgentProfile } from "@tangle-network/agent-interface";
5
- //#region src/multishot/types.d.ts
6
- interface MultishotMessage {
7
- role: 'user' | 'assistant' | 'tool';
8
- content: string;
9
- toolCallId?: string;
10
- toolCalls?: Array<{
11
- id: string;
12
- name: string;
13
- args: Record<string, unknown>;
14
- }>;
15
- }
16
- interface MultishotArtifact {
17
- type: string;
18
- turn: number;
19
- invocation: {
20
- name: string;
21
- args: Record<string, unknown>;
22
- };
23
- content: string;
24
- }
25
- interface MultishotResult {
26
- transcript: MultishotMessage[];
27
- artifacts: MultishotArtifact[];
28
- toolCalls: number;
29
- durationMs: number;
30
- /** Known spend. A subtotal, not a total, when `costProvenance.kind` is
31
- * `uncaptured`. */
32
- costUsd: number;
33
- /** Origin of `costUsd`. A shot that priced every call reports `estimated`
34
- * or `observed`; a shot with a call the router priced at nothing reports
35
- * `uncaptured`, and the matrix records the cell as under-counted instead of
36
- * presenting the subtotal as a complete estimate.
37
- *
38
- * Optional so an engine written before this field keeps working; the matrix
39
- * then judges the cell on judge receipts alone, as it did before. */
40
- costProvenance?: CostProvenance;
41
- }
42
- interface MultishotToolDefinition {
43
- type: 'function';
44
- function: {
45
- name: string;
46
- description: string;
47
- parameters: Record<string, unknown>;
48
- };
49
- }
50
- /** One chat-completion request the multishot loop issues for a single agent
51
- * (or driver) inference step. Mirrors the OpenAI-compat body the loop would
52
- * otherwise POST to the Tangle router. */
53
- interface MultishotTransportRequest {
54
- model: string;
55
- messages: Array<Record<string, unknown>>;
56
- tools?: MultishotToolDefinition[];
57
- temperature?: number;
58
- maxTokens?: number;
59
- signal?: AbortSignal;
60
- }
61
- interface MultishotTransportToolCall {
62
- id: string;
63
- type: 'function';
64
- function: {
65
- name: string;
66
- arguments: string;
67
- };
68
- }
69
- interface MultishotTransportResponse {
70
- message: {
71
- content?: string | null;
72
- tool_calls?: MultishotTransportToolCall[];
73
- };
74
- usage?: {
75
- prompt_tokens?: number;
76
- completion_tokens?: number;
77
- };
78
- /** Actual spend for this call. When omitted, the loop meters cost from
79
- * `usage` via the per-model router estimator (estimateRouterCost). */
80
- costUsd?: number;
81
- }
82
- /** Execution seam for one leg of the multishot loop. When provided, it
83
- * replaces the internal router HTTP call for that leg — the loop still owns
84
- * turn scheduling, tool dispatch, transcript capture, and cost metering.
85
- * agent-eval has no dependency on agent-runtime; adapt agent-runtime's
86
- * resolveAgentBackend (or any sandbox/cli-bridge/router client) into this
87
- * signature product-side. */
88
- type MultishotTransport = (req: MultishotTransportRequest) => Promise<MultishotTransportResponse>;
89
- type MultishotToolExecutor = (args: Record<string, unknown>, ctx: {
90
- apiKey: string;
91
- baseUrl: string;
92
- signal?: AbortSignal;
93
- }) => Promise<{
94
- content: string;
95
- costUsd: number;
96
- }>;
97
- interface MultishotPersona {
98
- /** Stable identifier — used for per-cell artifact paths + matrix axis keys. */
99
- id: string;
100
- /** Per-domain payload (income/profile/voice/etc.) shaped by the consumer. */
101
- [k: string]: unknown;
102
- }
103
- /**
104
- * Persona-shaping callbacks. Both are OPTIONAL: when omitted, the loop derives
105
- * them from the `AgentProfile` + persona payload (see `defaultShapeFromProfile`)
106
- * so a pure-profile call — `runMultishot({ profile, persona })` — works with no
107
- * role-builder functions. Provide callbacks only to override the derived shape.
108
- */
109
- interface MultishotShape<TPersona extends MultishotPersona> {
110
- /** Opening user message (turn 0) — the persona's first ask. */
111
- buildOpener?: (persona: TPersona) => string;
112
- /** System prompt the driver LLM uses to roleplay the persona. Should set
113
- * voice, goals, constraints, time-pressure, and the "never go silent" rule. */
114
- buildDriverSystemPrompt?: (persona: TPersona) => string;
115
- }
116
- declare class MultishotDriverEmptyError extends Error {
117
- readonly turn: number;
118
- constructor(turn: number);
119
- }
120
- declare class MultishotFatalToolError extends Error {
121
- constructor(message: string);
122
- }
123
- declare class MultishotShotResultError extends Error {
124
- constructor(reason: string);
125
- }
126
- /** Contract guard for the value a caller-supplied shot resolves with. The
127
- * matrix writes per-cell artifacts, builds judge inputs, and meters cost from
128
- * this value, so a malformed result must stop the cell instead of scoring a
129
- * degraded one. Two silent degradations this closes: an artifact with no
130
- * `type` matches neither the code nor the content artifact set, so the cell
131
- * scores as though the artifact was never produced; a non-finite `costUsd`
132
- * reaches `summary.totalCostUsd` and makes every cost number NaN.
133
- *
134
- * A rejected cell is still billed: the matrix cell reads the shot's own
135
- * `costUsd` when it is a usable amount and declares that spend on the throw,
136
- * so money the shot spent before returning a malformed result stays in the
137
- * cumulative sum the cost ceiling reads. A result whose `costUsd` is itself
138
- * malformed carries no usable amount, and the cell records as `uncaptured`.
139
- *
140
- * Every required field of `MultishotMessage` and `MultishotArtifact` is
141
- * checked, including `toolCalls` elements and `invocation.args`. Optional
142
- * fields are checked only when present. */
143
- declare function assertMultishotShotResult(value: unknown): asserts value is MultishotResult;
144
- //#endregion
145
4
  //#region src/multishot/router.d.ts
146
5
  interface RouterCompletionRequest {
147
6
  apiKey: string;
@@ -217,243 +76,6 @@ interface DefaultToolsBundle {
217
76
  }
218
77
  declare function defaultDelegationTools(config?: DefaultToolsConfig): DefaultToolsBundle;
219
78
  //#endregion
220
- //#region src/multishot/judges.d.ts
221
- declare const DEFAULT_JUDGE_MODEL = "openai/gpt-4o-mini";
222
- interface JudgeDimension {
223
- /** JSON field name + score key. */
224
- key: string;
225
- /** Description shown in the judge's user prompt. */
226
- description: string;
227
- }
228
- interface JudgeConfig<TInput> {
229
- /** Display name (for trace + log). */
230
- name: string;
231
- /** Model used for this judge. */
232
- model?: string;
233
- /** 0-10 scored dimensions. */
234
- dimensions: JudgeDimension[];
235
- /** Judge system prompt — sets persona + JSON-only constraint. */
236
- systemPrompt: string;
237
- /** Build the user prompt from the typed input. Must include "Respond with
238
- * ONLY this JSON: { ... }" listing each dimension key. */
239
- buildPrompt: (input: TInput) => string;
240
- /** Optional model + api overrides. */
241
- apiKey?: string;
242
- baseUrl?: string;
243
- /** Maximum output tokens for the judge response. Defaults to 1500. */
244
- maxTokens?: number;
245
- }
246
- interface JudgeRunResult {
247
- /** Semantic result; failed scores remain non-throwing so matrix aggregation can exclude them. */
248
- score: JudgeScore;
249
- /** Cost of the completed call, separate from diagnostic provider metadata. */
250
- cost: CostProvenance;
251
- }
252
- declare function runJudge<TInput>(judge: JudgeConfig<TInput>, input: TInput): Promise<JudgeRunResult>;
253
- /** Convenience: stringified dimension list for inclusion in a judge prompt.
254
- * Returns lines like `- audience_fit: Does this match what the audience cares about? (0-10)`. */
255
- declare function renderDimensions(dims: readonly JudgeDimension[]): string;
256
- /** Convenience: build the "Respond with ONLY this JSON" footer for a judge prompt. */
257
- declare function renderJsonFooter(dims: readonly JudgeDimension[]): string;
258
- //#endregion
259
- //#region src/multishot/multishot.d.ts
260
- interface RunMultishotOptions<TPersona extends MultishotPersona> {
261
- profile: AgentProfile;
262
- persona: TPersona;
263
- /** Persona-shaping callbacks. Optional — omitted callbacks are derived from
264
- * the profile + persona payload, so a pure-profile call works. */
265
- shape?: MultishotShape<TPersona>;
266
- /** Tool definitions advertised to the agent. Defaults to delegate_research + delegate_code. */
267
- tools?: MultishotToolDefinition[];
268
- /** Map from tool name → executor invoked inline when the agent emits a tool_call. */
269
- toolExecutors?: Record<string, MultishotToolExecutor>;
270
- /** Map from tool name → artifact type label written into MultishotArtifact.type.
271
- * Tools without a mapping still execute, but their results aren't surfaced as
272
- * typed artifacts (only as tool messages in the transcript). */
273
- artifactTypeFor?: (toolName: string) => string | undefined;
274
- maxTurns?: number;
275
- agentModel?: string;
276
- driverModel?: string;
277
- /** Fallback driver models tried when the primary simulated-user model returns empty twice. */
278
- driverFallbackModels?: string[];
279
- /** Maximum output tokens for the first agent call in each assistant turn. */
280
- agentMaxTokens?: number;
281
- /** Maximum output tokens for agent follow-up calls after tool results. */
282
- toolFollowupMaxTokens?: number;
283
- /** Maximum output tokens for each simulated-user driver response. */
284
- driverMaxTokens?: number;
285
- /** Maximum tool calls the agent may dispatch inside one assistant turn. */
286
- maxToolDispatches?: number;
287
- /** Execution seam for the agent leg. When provided, every agent inference
288
- * step goes through this function instead of the router HTTP call; the
289
- * string levers (agentModel, apiKey, baseUrl) stop applying to that leg.
290
- * apiKey/baseUrl are still resolved for tool executors and any leg
291
- * without an injected transport. */
292
- agentTransport?: MultishotTransport;
293
- /** Execution seam for the simulated-user driver leg (symmetric to
294
- * agentTransport). Driver model fallback rotation still applies — the
295
- * transport receives each candidate model in turn. */
296
- driverTransport?: MultishotTransport;
297
- apiKey?: string;
298
- baseUrl?: string;
299
- signal?: AbortSignal;
300
- }
301
- /** One multishot shot — the conversation engine `runMultishotMatrix` invokes
302
- * once per cell. `runMultishot` is the default implementation.
303
- *
304
- * An alternative engine (a graph-backed conversation, a replay of a recorded
305
- * transcript, a sandbox-hosted agent) implements this exact signature and
306
- * reaches the matrix through `RunMultishotMatrixOptions.runShot`. The matrix
307
- * keeps every other cell mechanic — cell fan-out, concurrency, the cost
308
- * ceiling, the judge slots, the cell composite, and the per-cell writers — so
309
- * swapping the engine needs no copy of the cell body. */
310
- type MultishotShot<TPersona extends MultishotPersona> = (opts: RunMultishotOptions<TPersona>) => Promise<MultishotResult>;
311
- declare function runMultishot<TPersona extends MultishotPersona>(opts: RunMultishotOptions<TPersona>): Promise<MultishotResult>;
312
- //#endregion
313
- //#region src/multishot/matrix.d.ts
314
- interface ConversationJudgeInput<TPersona extends MultishotPersona> {
315
- transcript: MultishotMessage[];
316
- persona: TPersona;
317
- }
318
- interface ArtifactJudgeInput<TPersona extends MultishotPersona> {
319
- artifact: MultishotArtifact;
320
- persona: TPersona;
321
- }
322
- interface MultishotJudges<TPersona extends MultishotPersona> {
323
- /** Scores the full transcript end-to-end (always runs). */
324
- conversation: JudgeConfig<ConversationJudgeInput<TPersona>>;
325
- /** Scores each code-type artifact. Optional — omit when domain has no code artifacts. */
326
- codeReview?: JudgeConfig<ArtifactJudgeInput<TPersona>>;
327
- /** Scores each non-code (research/content/template) artifact. Optional. */
328
- contentQuality?: JudgeConfig<ArtifactJudgeInput<TPersona>>;
329
- /** Which artifact types route to codeReview. Defaults to ['code']. */
330
- codeArtifactTypes?: string[];
331
- /** Which artifact types route to contentQuality. Defaults to ['research']. */
332
- contentArtifactTypes?: string[];
333
- }
334
- interface CellCompositeScore {
335
- composite: number;
336
- conversation: JudgeScore;
337
- codeReview?: {
338
- perArtifact: Array<JudgeScore & {
339
- turn: number;
340
- type: string;
341
- }>;
342
- composite: number;
343
- };
344
- contentQuality?: {
345
- perArtifact: Array<JudgeScore & {
346
- turn: number;
347
- type: string;
348
- }>;
349
- composite: number;
350
- };
351
- }
352
- interface RunMultishotMatrixOptions<TPersona extends MultishotPersona> {
353
- /** AgentProfile axis (matrix primary). */
354
- profiles: Array<{
355
- id: string;
356
- value: AgentProfile;
357
- }>;
358
- /** Persona axis. */
359
- personas: TPersona[];
360
- /** Persona-shaping callbacks. Optional — omitted callbacks are derived per
361
- * cell from that cell's profile + persona payload (pure-profile path). */
362
- shape?: MultishotShape<TPersona>;
363
- /** Judge configurations. */
364
- judges: MultishotJudges<TPersona>;
365
- /** Tool definitions advertised to the agent. Defaults to delegate_research + delegate_code. */
366
- tools?: MultishotToolDefinition[];
367
- /** Map from tool name → inline executor. Must align with `tools`. */
368
- toolExecutors?: Record<string, MultishotToolExecutor>;
369
- /** Tool name → artifact type label. Defaults to research/code mapping. */
370
- artifactTypeFor?: (toolName: string) => string | undefined;
371
- /** Where per-cell artifacts land. Cells write to `<runDir>/<profileId>/<personaId>/rep-N/`. */
372
- runDir: string;
373
- /** Replicates per (profile, persona) cell. */
374
- reps?: number;
375
- /** Max conversation turns per cell. */
376
- maxTurns?: number;
377
- /** Maximum tool calls the agent may dispatch inside one assistant turn. */
378
- maxToolDispatches?: number;
379
- /** Max concurrent cells. */
380
- maxConcurrency?: number;
381
- /** Total $ ceiling across the matrix; cells aborted past this. */
382
- costCeiling?: number;
383
- /** Upper bound on what one cell can spend. A cell whose cost is a subtotal
384
- * is charged this bound against `costCeiling` instead of its known amount,
385
- * so hidden spend cannot walk the run past its budget. */
386
- maxCellCostUsd?: number;
387
- /** Agent model. */
388
- agentModel?: string;
389
- /** Driver model. */
390
- driverModel?: string;
391
- /** Fallback driver models tried when the primary simulated-user model returns empty twice. */
392
- driverFallbackModels?: string[];
393
- /** Maximum output tokens for the first agent call in each assistant turn. */
394
- agentMaxTokens?: number;
395
- /** Maximum output tokens for agent follow-up calls after tool results. */
396
- toolFollowupMaxTokens?: number;
397
- /** Maximum output tokens for each simulated-user driver response. */
398
- driverMaxTokens?: number;
399
- /** Maximum output tokens for each judge response. */
400
- judgeMaxTokens?: number;
401
- /** Execution seam for the agent leg of every cell — replaces the router
402
- * HTTP call when provided (see RunMultishotOptions.agentTransport).
403
- * Judges are unaffected; configure those via MultishotJudges. */
404
- agentTransport?: MultishotTransport;
405
- /** Execution seam for the simulated-user driver leg of every cell. */
406
- driverTransport?: MultishotTransport;
407
- /** Conversation engine for every cell. Defaults to `runMultishot`.
408
- *
409
- * The matrix owns everything around the shot — cell fan-out, concurrency,
410
- * the cost ceiling, the judge slots, the cell composite, the per-cell
411
- * artifact writers and the run summary — and forwards the whole cell input
412
- * to this function, so an alternative engine replaces ONLY the
413
- * conversation. Every option on this interface that `runMultishot` accepts
414
- * reaches the shot unchanged. `RunMultishotOptions.signal` has no
415
- * matrix-level counterpart and is not forwarded; a shot owns its own
416
- * cancellation.
417
- *
418
- * A shot that resolves with a value outside `MultishotResult` throws
419
- * `MultishotShotResultError` for that cell. The default engine is never
420
- * used as a fallback. */
421
- runShot?: MultishotShot<TPersona>;
422
- /** Pass-thru fields. */
423
- apiKey?: string;
424
- baseUrl?: string;
425
- }
426
- /** Per-cell output the multishot matrix records in `MatrixResult.cells`.
427
- * A consumer that supplies its own `runShot` reads the matrix through this
428
- * type instead of declaring a structural copy. */
429
- interface MultishotCellOutput {
430
- turns: number;
431
- toolCalls: number;
432
- artifactCount: number;
433
- }
434
- interface CellCompositeInput {
435
- conversation: JudgeScore;
436
- /** Present iff the codeReview judge is configured. */
437
- codeReviews?: ReadonlyArray<JudgeScore>;
438
- /** Present iff the contentQuality judge is configured. */
439
- contentReviews?: ReadonlyArray<JudgeScore>;
440
- }
441
- /** Cell composite = mean over configured judge slots, excluding failed
442
- * scores: a failed conversation judge or an all-failed artifact slot carries
443
- * no signal and is dropped from the mean. `composite` is 0 only when EVERY
444
- * configured slot failed (`allJudgesFailed` distinguishes that from a real
445
- * zero). Pure — exported for deterministic testing. */
446
- declare function computeCellComposite(input: CellCompositeInput): {
447
- composite: number;
448
- codeComposite: number;
449
- contentComposite: number;
450
- allJudgesFailed: boolean;
451
- };
452
- interface RunMultishotMatrixResult {
453
- matrix: MatrixResult<MultishotCellOutput>;
454
- }
455
- declare function runMultishotMatrix<TPersona extends MultishotPersona>(opts: RunMultishotMatrixOptions<TPersona>): Promise<RunMultishotMatrixResult>;
456
- //#endregion
457
79
  //#region src/multishot/shape-defaults.d.ts
458
80
  /** Persona payload rendered as stable `- key: value` lines. `id` is identity,
459
81
  * not voice, and structured values are serialized so nothing is dropped. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/multishot/types.ts","../../src/multishot/router.ts","../../src/multishot/default-tools.ts","../../src/multishot/judges.ts","../../src/multishot/multishot.ts","../../src/multishot/matrix.ts","../../src/multishot/shape-defaults.ts"],"mappings":";;;;;UAIiB;EACf;EACA;EACA;EACA,YAAY;IAAQ;IAAY;IAAc,MAAM;;;UAGrC;EACf;EACA;EACA;IAAc;IAAc,MAAM;;EAClC;;UAGe;EACf,YAAY;EACZ,WAAW;EACX;EACA;;;EAGA;;;;;;;;EAQA,iBAAiB;;UAGF;EACf;EACA;IACE;IACA;IACA,YAAY;;;;;;UAOC;EACf;EACA,UAAU,MAAM;EAChB,QAAQ;EACR;EACA;EACA,SAAS;;UAGM;EACf;EACA;EACA;IAAY;IAAc;;;UAGX;EACf;IAAW;IAAyB,aAAa;;EACjD;IAAU;IAAwB;;;;EAGlC;;;;;;;;KASU,sBACV,KAAK,8BACF,QAAQ;KAED,yBACV,MAAM,yBACN;EAAO;EAAgB;EAAiB,SAAS;MAC9C;EAAU;EAAiB;;UAEf;;EAEf;;GAEC;;;;;;;;UASc,eAAe,iBAAiB;;EAE/C,eAAe,SAAS;;;EAGxB,2BAA2B,SAAS;;cAGzB,kCAAkC;WACjB;EAA5B,YAA4B;;cAMjB,gCAAgC;EAC3C,YAAY;;cAMD,iCAAiC;EAC5C,YAAY;;;;;;;;;;;;;;;;;;;iBAyBE,0BAA0B,yBAAyB,SAAS;;;UC7I3D;EACf;EACA;EACA;EACA,UAAU,MAAM;EAChB,QAAQ;EACR;EACA;EACA,SAAS;;UAGM;EACf;EACA;EACA;IAAY;IAAc;;;UAGX;EACf;IAAW;IAAyB,aAAa;;EACjD;IAAU;IAAwB;;;EAElC;;EAEA;EACA;;iBAGoB,iBACpB,KAAK,0BACJ,QAAQ;iBA2CK,mBACd,eACA;EAAU;EAAwB;;iBAoBpB;iBAOA;;;cCjGH;cACA;UAEI;;;EAGf;EACA;;UAGe;;;EAGf;EACA;;cASW,gCAAgC;cAoBhC,4BAA4B;iBAoBzB,uBACd,SAAQ,0BACP;iBAsBa,mBAAmB,SAAQ,qBAA0B;UAsBpD;EACf,WAAW;EACX,OAAO;;;EAGP;;UAGe;EACf,OAAO;EACP,WAAW,eAAe;EAC1B,kBAAkB;;iBAGJ,uBAAuB,SAAQ,qBAA0B;;;cC5G5D;UAEI;;EAEf;;EAEA;;UAGe,YAAY;;EAE3B;;EAEA;;EAEA,YAAY;;EAEZ;;;EAGA,cAAc,OAAO;;EAErB;EACA;;EAEA;;UAGe;;EAEf,OAAO;;EAEP,MAAM;;iBAGc,SAAS,QAC7B,OAAO,YAAY,SACnB,OAAO,SACN,QAAQ;;;iBAkIK,iBAAiB,eAAe;;iBAKhC,iBAAiB,eAAe;;;UCvK/B,oBAAoB,iBAAiB;EACpD,SAAS;EACT,SAAS;;;EAGT,QAAQ,eAAe;;EAEvB,QAAQ;;EAER,gBAAgB,eAAe;;;;EAI/B,mBAAmB;EACnB;EACA;EACA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;;;;;EAMA,iBAAiB;;;;EAIjB,kBAAkB;EAClB;EACA;EACA,SAAS;;;;;;;;;;;KAYC,cAAc,iBAAiB,qBACzC,MAAM,oBAAoB,cACvB,QAAQ;iBAWS,aAAa,iBAAiB,kBAClD,MAAM,oBAAoB,YACzB,QAAQ;;;UCtEM,uBAAuB,iBAAiB;EACvD,YAAY;EACZ,SAAS;;UAGM,mBAAmB,iBAAiB;EACnD,UAAU;EACV,SAAS;;UAGM,gBAAgB,iBAAiB;;EAEhD,cAAc,YAAY,uBAAuB;;EAEjD,aAAa,YAAY,mBAAmB;;EAE5C,iBAAiB,YAAY,mBAAmB;;EAEhD;;EAEA;;UAGe;EACf;EACA,cAAc;EACd;IACE,aAAa,MAAM;MAAe;MAAc;;IAChD;;EAEF;IACE,aAAa,MAAM;MAAe;MAAc;;IAChD;;;UAIa,0BAA0B,iBAAiB;;EAE1D,UAAU;IAAQ;IAAY,OAAO;;;EAErC,UAAU;;;EAGV,QAAQ,eAAe;;EAEvB,QAAQ,gBAAgB;;EAExB,QAAQ;;EAER,gBAAgB,eAAe;;EAE/B,mBAAmB;;EAEnB;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;;;EAIA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;;;EAIA,iBAAiB;;EAEjB,kBAAkB;;;;;;;;;;;;;;;EAelB,UAAU,cAAc;;EAExB;EACA;;;;;UAMe;EACf;EACA;EACA;;UAoBe;EACf,cAAc;;EAEd,cAAc,cAAc;;EAE5B,iBAAiB,cAAc;;;;;;;iBAQjB,qBAAqB,OAAO;EAC1C;EACA;EACA;EACA;;UAuBe;EACf,QAAQ,aAAa;;iBAGD,mBAAmB,iBAAiB,kBACxD,MAAM,0BAA0B,YAC/B,QAAQ;;;;;iBCjMK,mBAAmB,SAAS;;;iBAe5B,uBAAuB,SAAS,cAAc,SAAS;;;iBAavD,mCACd,SAAS,cACT,SAAS;;;iBAqBK,wBAAwB,iBAAiB,kBACvD,SAAS,cACT,QAAQ,eAAe,YACtB,SAAS,eAAe"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/multishot/router.ts","../../src/multishot/default-tools.ts","../../src/multishot/shape-defaults.ts"],"mappings":";;;;UAMiB;EACf;EACA;EACA;EACA,UAAU,MAAM;EAChB,QAAQ;EACR;EACA;EACA,SAAS;;UAGM;EACf;EACA;EACA;IAAY;IAAc;;;UAGX;EACf;IAAW;IAAyB,aAAa;;EACjD;IAAU;IAAwB;;;EAElC;;EAEA;EACA;;iBAGoB,iBACpB,KAAK,0BACJ,QAAQ;iBA2CK,mBACd,eACA;EAAU;EAAwB;;iBAoBpB;iBAOA;;;cCjGH;cACA;UAEI;;;EAGf;EACA;;UAGe;;;EAGf;EACA;;cASW,gCAAgC;cAoBhC,4BAA4B;iBAoBzB,uBACd,SAAQ,0BACP;iBAsBa,mBAAmB,SAAQ,qBAA0B;UAsBpD;EACf,WAAW;EACX,OAAO;;;EAGP;;UAGe;EACf,OAAO;EACP,WAAW,eAAe;EAC1B,kBAAkB;;iBAGJ,uBAAuB,SAAQ,qBAA0B;;;;;iBCvHzD,mBAAmB,SAAS;;;iBAe5B,uBAAuB,SAAS,cAAc,SAAS;;;iBAavD,mCACd,SAAS,cACT,SAAS;;;iBAqBK,wBAAwB,iBAAiB,kBACvD,SAAS,cACT,QAAQ,eAAe,YACtB,SAAS,eAAe"}