zidane 8.2.3 → 8.2.5
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/dist/{acp-oYRjlh71.js → acp-BIInKhVI.js} +6 -6
- package/dist/{acp-oYRjlh71.js.map → acp-BIInKhVI.js.map} +1 -1
- package/dist/acp-cli.js +4 -4
- package/dist/acp.d.ts +2 -2
- package/dist/acp.js +1 -1
- package/dist/{agent-CBQglXtH.js → agent-CmhCOmyO.js} +10 -5
- package/dist/{agent-CBQglXtH.js.map → agent-CmhCOmyO.js.map} +1 -1
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +1 -1
- package/dist/chat/pure.d.ts +4 -4
- package/dist/chat/pure.js +7 -7
- package/dist/chat.d.ts +3 -3
- package/dist/chat.js +16 -16
- package/dist/{cli-shared-E5m_pI8A.js → cli-shared-GOehTeqk.js} +2 -2
- package/dist/{cli-shared-E5m_pI8A.js.map → cli-shared-GOehTeqk.js.map} +1 -1
- package/dist/{client-core-EEEX_u6D.d.ts → client-core-Dz8hELs4.d.ts} +15 -5
- package/dist/client-core-Dz8hELs4.d.ts.map +1 -0
- package/dist/codemode-worker.js +1 -1
- package/dist/codemode.js +1 -1
- package/dist/{connection-loop-CpgfUmuw.d.ts → connection-loop-dm_TN-QD.d.ts} +3 -3
- package/dist/{connection-loop-CpgfUmuw.d.ts.map → connection-loop-dm_TN-QD.d.ts.map} +1 -1
- package/dist/contexts/daytona.d.ts +1 -1
- package/dist/contexts/e2b.d.ts +1 -1
- package/dist/{credentials-B9DfBJP9.js → credentials-DxOQmset.js} +2 -2
- package/dist/{credentials-B9DfBJP9.js.map → credentials-DxOQmset.js.map} +1 -1
- package/dist/daemon-cli.js +2 -2
- package/dist/{dispatcher-Bv9-c6I2.js → dispatcher-D_9_QFO3.js} +22 -18
- package/dist/dispatcher-D_9_QFO3.js.map +1 -0
- package/dist/{engine-XmoPPB6U.js → engine-BsWBWgTB.js} +6 -6
- package/dist/{engine-XmoPPB6U.js.map → engine-BsWBWgTB.js.map} +1 -1
- package/dist/{eval-CfQlBR81.js → eval-CIHIF_Ns.js} +3 -3
- package/dist/{eval-CfQlBR81.js.map → eval-CIHIF_Ns.js.map} +1 -1
- package/dist/eval.d.ts +1 -1
- package/dist/eval.js +1 -1
- package/dist/{executor-BhthPE1q.js → executor-BSesPPcU.js} +3 -3
- package/dist/{executor-BhthPE1q.js.map → executor-BSesPPcU.js.map} +1 -1
- package/dist/{extensions-BgBwogRW.js → extensions-BJof-2mi.js} +3 -3
- package/dist/{extensions-BgBwogRW.js.map → extensions-BJof-2mi.js.map} +1 -1
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.js +1 -1
- package/dist/{fold-rules-DSypi36k.d.ts → fold-rules-CMpWNPqk.d.ts} +2 -2
- package/dist/{fold-rules-DSypi36k.d.ts.map → fold-rules-CMpWNPqk.d.ts.map} +1 -1
- package/dist/{headless-R4pbpTkm.js → headless-Bs9Lb4vs.js} +4 -4
- package/dist/{headless-R4pbpTkm.js.map → headless-Bs9Lb4vs.js.map} +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -1
- package/dist/history-worker.js +1 -1
- package/dist/{host-scoped-settings-C-Nmb6vr.js → host-scoped-settings-DxxI_yRo.js} +2 -2
- package/dist/{host-scoped-settings-C-Nmb6vr.js.map → host-scoped-settings-DxxI_yRo.js.map} +1 -1
- package/dist/{host-signals-BFudPyCT.js → host-signals-CUKPZZxC.js} +5 -5
- package/dist/{host-signals-BFudPyCT.js.map → host-signals-CUKPZZxC.js.map} +1 -1
- package/dist/{index-DyQyDLX1.d.ts → index-4mDRyTGJ.d.ts} +1722 -1691
- package/dist/index-4mDRyTGJ.d.ts.map +1 -0
- package/dist/{index-CDS7YdUC.d.ts → index-Dlmu8HnG.d.ts} +5 -5
- package/dist/{index-CDS7YdUC.d.ts.map → index-Dlmu8HnG.d.ts.map} +1 -1
- package/dist/{index-AqRZ3gEz.d.ts → index-QsAN9yjZ.d.ts} +3 -3
- package/dist/{index-AqRZ3gEz.d.ts.map → index-QsAN9yjZ.d.ts.map} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +8 -8
- package/dist/ipc/remote.d.ts +5 -5
- package/dist/ipc/remote.js +3 -3
- package/dist/ipc.d.ts +5 -5
- package/dist/ipc.js +9 -9
- package/dist/{links-rFaWqS2Y.js → links-Bto-5dVu.js} +10 -10
- package/dist/{links-rFaWqS2Y.js.map → links-Bto-5dVu.js.map} +1 -1
- package/dist/{mcp-allowlist-CLXweyxk.js → mcp-allowlist-BbnTBKNN.js} +2 -2
- package/dist/{mcp-allowlist-CLXweyxk.js.map → mcp-allowlist-BbnTBKNN.js.map} +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/{oauth-7_48zR7n.js → oauth-BwPiX0hL.js} +66 -32
- package/dist/oauth-BwPiX0hL.js.map +1 -0
- package/dist/output/stream-json.d.ts +1 -1
- package/dist/output/terminal.d.ts +1 -1
- package/dist/plugins.d.ts +1 -1
- package/dist/{prelude-HzY_JEGq.js → prelude-qjPUkw4f.js} +26 -2
- package/dist/prelude-qjPUkw4f.js.map +1 -0
- package/dist/{presets-DXeHsd24.js → presets-C4hkykN-.js} +2 -2
- package/dist/{presets-DXeHsd24.js.map → presets-C4hkykN-.js.map} +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -1
- package/dist/{protocol-BIv1Yuvl.js → protocol-Do_i6Ras.js} +3 -1
- package/dist/protocol-Do_i6Ras.js.map +1 -0
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/arcee.d.ts +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/google.d.ts +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/neuralwatt.d.ts +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/{registry-eourRLY2.js → registry-DxPP_tAt.js} +3 -3
- package/dist/{registry-eourRLY2.js.map → registry-DxPP_tAt.js.map} +1 -1
- package/dist/{remote-hosts-DY2J07ut.js → remote-hosts-DcCh7fqp.js} +4 -4
- package/dist/{remote-hosts-DY2J07ut.js.map → remote-hosts-DcCh7fqp.js.map} +1 -1
- package/dist/restate.d.ts +1 -1
- package/dist/{secret-shapes-BjW4l6U0.js → secret-shapes-HvaYVzwc.js} +10 -2
- package/dist/secret-shapes-HvaYVzwc.js.map +1 -0
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/{session-7TUHs42_.js → session-CCsKXID6.js} +6 -2
- package/dist/session-CCsKXID6.js.map +1 -0
- package/dist/{session-factory-CMwIXE-7.js → session-factory-Ct7J9CK1.js} +6 -6
- package/dist/{session-factory-CMwIXE-7.js.map → session-factory-Ct7J9CK1.js.map} +1 -1
- package/dist/session.d.ts +2 -2
- package/dist/session.js +1 -1
- package/dist/{settings-keys-CPdmkTz7.js → settings-keys-CnrJgT1T.js} +4 -4
- package/dist/{settings-keys-CPdmkTz7.js.map → settings-keys-CnrJgT1T.js.map} +1 -1
- package/dist/{shell-path-B8b3EOtK.js → shell-path-rJDa0OMv.js} +4 -4
- package/dist/{shell-path-B8b3EOtK.js.map → shell-path-rJDa0OMv.js.map} +1 -1
- package/dist/skills.d.ts +1 -1
- package/dist/{spaces-CyjMh5Zf.js → spaces-C_x2bvEl.js} +14 -4
- package/dist/spaces-C_x2bvEl.js.map +1 -0
- package/dist/{store-L01W0gGI.js → store-BpkWIaSH.js} +10 -30
- package/dist/store-BpkWIaSH.js.map +1 -0
- package/dist/{todo-edits-BERpCRPj.js → todo-edits-DKoxu7Ss.js} +3 -3
- package/dist/{todo-edits-BERpCRPj.js.map → todo-edits-DKoxu7Ss.js.map} +1 -1
- package/dist/tools/fetch-url.d.ts +1 -1
- package/dist/tools/web-search.d.ts +1 -1
- package/dist/{tools-pZVFIJ_K.js → tools-FHEIKGkh.js} +2 -2
- package/dist/{tools-pZVFIJ_K.js.map → tools-FHEIKGkh.js.map} +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +2 -2
- package/dist/{transcript-anchors-jHrg-r-H.js → transcript-anchors-BcFLh3ZA.js} +10 -10
- package/dist/{transcript-anchors-jHrg-r-H.js.map → transcript-anchors-BcFLh3ZA.js.map} +1 -1
- package/dist/{transcript-cache-DXdgVuoy.js → transcript-cache-CdHKtx9y.js} +4 -4
- package/dist/{transcript-cache-DXdgVuoy.js.map → transcript-cache-CdHKtx9y.js.map} +1 -1
- package/dist/{transcript-reconcile-CPdrNbbR.js → transcript-reconcile-D_SWw6dX.js} +11 -3
- package/dist/transcript-reconcile-D_SWw6dX.js.map +1 -0
- package/dist/tui.d.ts +7 -7
- package/dist/tui.js +24 -23
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-DuGtKuc_.d.ts → turn-operations-Dbk3xPKu.d.ts} +11 -3
- package/dist/{turn-operations-DuGtKuc_.d.ts.map → turn-operations-Dbk3xPKu.d.ts.map} +1 -1
- package/dist/{types-C0PJmBaO.d.ts → types-CMXR7A0b.d.ts} +2 -2
- package/dist/{types-C0PJmBaO.d.ts.map → types-CMXR7A0b.d.ts.map} +1 -1
- package/dist/types-CzmghX7C.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/{url-D8KZ7Edw.js → url-D4vG7lzO.js} +2 -2
- package/dist/{url-D8KZ7Edw.js.map → url-D4vG7lzO.js.map} +1 -1
- package/dist/{version-bd3DQJkc.js → version-DOvIuU8M.js} +2 -2
- package/dist/{version-bd3DQJkc.js.map → version-DOvIuU8M.js.map} +1 -1
- package/dist/{workspace-exec-stream-CyfYgqAh.js → workspace-exec-stream-Bzxczzu2.js} +5 -5
- package/dist/{workspace-exec-stream-CyfYgqAh.js.map → workspace-exec-stream-Bzxczzu2.js.map} +1 -1
- package/dist/{write-file-QYrcDdl3.js → write-file-ChtRPdEL.js} +3 -3
- package/dist/{write-file-QYrcDdl3.js.map → write-file-ChtRPdEL.js.map} +1 -1
- package/dist/{ws-CURQ2igk.js → ws-CrD-4Mx6.js} +6 -6
- package/dist/{ws-CURQ2igk.js.map → ws-CrD-4Mx6.js.map} +1 -1
- package/dist/{ws-client-BVljYbdb.js → ws-client-Dond8vT3.js} +4 -4
- package/dist/{ws-client-BVljYbdb.js.map → ws-client-Dond8vT3.js.map} +1 -1
- package/docs/CODEMODE.md +6 -0
- package/docs/IPC.md +2 -0
- package/docs/ONBOARDING.md +1 -1
- package/package.json +1 -1
- package/dist/client-core-EEEX_u6D.d.ts.map +0 -1
- package/dist/dispatcher-Bv9-c6I2.js.map +0 -1
- package/dist/index-DyQyDLX1.d.ts.map +0 -1
- package/dist/oauth-7_48zR7n.js.map +0 -1
- package/dist/prelude-HzY_JEGq.js.map +0 -1
- package/dist/protocol-BIv1Yuvl.js.map +0 -1
- package/dist/secret-shapes-BjW4l6U0.js.map +0 -1
- package/dist/session-7TUHs42_.js.map +0 -1
- package/dist/spaces-CyjMh5Zf.js.map +0 -1
- package/dist/store-L01W0gGI.js.map +0 -1
- package/dist/transcript-reconcile-CPdrNbbR.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval-CfQlBR81.js","names":["shellQuote"],"sources":["../src/eval-artifacts.ts","../src/eval-metrics.ts","../src/eval-summary.ts","../src/eval-report.ts","../src/eval-scorers.ts","../src/eval-trajectory.ts","../src/eval-workspace.ts","../src/eval-execution.ts","../src/eval-agent.ts","../src/eval-judge.ts","../src/eval-registry.ts","../src/eval.ts"],"sourcesContent":["import type { EvalArtifacts, EvalCaseResult } from './eval-types'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { join, relative, resolve } from 'node:path'\nimport { headlessEventToJsonl } from './headless-format'\n\nexport async function writeEvalArtifacts(dir: string, result: EvalCaseResult): Promise<EvalArtifacts> {\n await mkdir(dir, { recursive: true })\n const resultPath = join(dir, 'result.json')\n const eventsPath = join(dir, 'events.jsonl')\n const transcriptPath = join(dir, 'transcript.json')\n const workspacePath = result.workspace ? join(dir, 'workspace.json') : undefined\n\n await writeFile(resultPath, `${JSON.stringify(result, null, 2)}\\n`)\n await writeFile(eventsPath, result.events.map(headlessEventToJsonl).join(''))\n await writeFile(transcriptPath, `${JSON.stringify(result.result.transcript, null, 2)}\\n`)\n if (workspacePath)\n await writeFile(workspacePath, `${JSON.stringify(result.workspace, null, 2)}\\n`)\n\n return {\n dir,\n result: resultPath,\n events: eventsPath,\n transcript: transcriptPath,\n ...(workspacePath ? { workspace: workspacePath } : {}),\n }\n}\n\nexport function safeSegment(value: string): string {\n const sanitized = value.replace(/[^\\w.-]+/g, '-').replace(/^-+|-+$/g, '')\n // If sanitizing changed the value, distinct ids can collapse to the same\n // segment (e.g. `a b`, `a/b`, `a@b` → `a-b`) and overwrite each other's\n // artifacts. Append a short, stable hash of the original to disambiguate.\n if (sanitized === value && sanitized.length > 0)\n return sanitized\n return `${sanitized || 'eval'}-${shortHash(value)}`\n}\n\nfunction shortHash(value: string): string {\n // Tiny FNV-1a; only used to disambiguate filesystem segments, not security.\n let hash = 0x811C9DC5\n for (let i = 0; i < value.length; i++) {\n hash ^= value.charCodeAt(i)\n hash = Math.imul(hash, 0x01000193)\n }\n return (hash >>> 0).toString(36).padStart(7, '0').slice(0, 7)\n}\n\n/**\n * Resolves the artifact directory of a case: `<root>/<suite>/<id>`. Characters that are unsafe in a path segment are replaced.\n *\n * @param root - Root artifact directory.\n * @param result - Case result that names the suite and id.\n */\nexport function artifactPath(root: string, result: EvalCaseResult): string {\n return resolve(root, safeSegment(result.suite ?? 'eval'), safeSegment(result.id))\n}\n\n/**\n * Returns `path` relative to `root`.\n *\n * @param root - Root artifact directory.\n * @param path - Path inside the artifact tree.\n */\nexport function relativeArtifactPath(root: string, path: string): string {\n return relative(root, path)\n}\n","import type { HeadlessResult } from './headless'\n\n/** Whether a larger raw value is better or worse. */\nexport type MetricDirection = 'higher-is-better' | 'lower-is-better'\n\n/** Declared metric: a raw signal plus how to normalize it to a `0..1` score. */\nexport interface MetricSpec {\n /** Lower bound of the raw range. Raw values below it are clamped. */\n min: number\n /** Upper bound of the raw range. Raw values above it are clamped. */\n max: number\n /** Whether higher or lower raw values score better. */\n direction: MetricDirection\n /** Grouping tags, e.g. `@efficiency`, `@functionality`, `@quality`. */\n tags?: string[]\n /** Human-readable description of the metric. */\n description?: string\n}\n\n/** Metric specs keyed by metric id. */\nexport type MetricSpecMap = Record<string, MetricSpec>\n\n/** A normalized metric value attached to one eval case. */\nexport interface EvalMetric {\n /** Metric id, the key in the {@link MetricSpecMap}. */\n id: string\n /** Raw value the run emitted. `0` when the metric is missing. */\n raw: number\n /** Score from `0` to `1`. `0` when the metric is missing. */\n normalized: number\n /** Whether higher or lower raw values score better. */\n direction: MetricDirection\n /** Lower bound of the raw range, from the spec. */\n min: number\n /** Upper bound of the raw range, from the spec. */\n max: number\n /** Grouping tags, from the spec. Empty when the spec has none. */\n tags: string[]\n /** Human-readable description, from the spec. */\n description?: string\n /**\n * True when the metric was declared but never emitted (e.g. its scorer threw\n * before calling `ctx.metric`). Recorded as `normalized: 0` so the run still\n * produces results instead of crashing.\n */\n missing?: boolean\n}\n\n/** Emit a raw metric value during a run. */\nexport type MetricEmitter = (id: string, raw: number) => void\n\n/**\n * Declare an eval's metric set. Returns the same map, typed; pass it to\n * `EvalCaseOptions.metrics`. Declared metrics that are not emitted are recorded\n * as missing with a normalized score of 0; emitting an undeclared metric is an\n * authoring error and throws.\n *\n * @param spec - Metric specs keyed by metric id.\n */\nexport function defineMetrics<T extends MetricSpecMap>(spec: T): T {\n return spec\n}\n\n/** Always-available efficiency metrics derived from `HeadlessResult`. */\nexport const EFFICIENCY_METRICS = {\n 'execution-time': { min: 0, max: 300_000, direction: 'lower-is-better', tags: ['@efficiency'], description: 'Wall-clock run time (ms).' },\n 'provider-tokens': { min: 0, max: 200_000, direction: 'lower-is-better', tags: ['@efficiency'], description: 'Input + output tokens.' },\n 'cache-read-rate': { min: 0, max: 1, direction: 'higher-is-better', tags: ['@efficiency'], description: 'Cache-read tokens / input tokens.' },\n} satisfies MetricSpecMap\n\n/**\n * Maps a raw value to a score from `0` to `1`, clamped to the spec's range and flipped for `'lower-is-better'`. Returns `1` when `min` equals `max`.\n *\n * @param raw - Raw metric value.\n * @param spec - Range and direction of the metric.\n */\nexport function normalizeMetric(raw: number, spec: MetricSpec): number {\n const span = spec.max - spec.min\n if (span === 0)\n return 1\n const clamped = Math.min(spec.max, Math.max(spec.min, raw))\n const normalized = (clamped - spec.min) / span\n return spec.direction === 'lower-is-better' ? 1 - normalized : normalized\n}\n\n/**\n * Thrown by `runEvalCase` when a scorer emits a metric id that was not declared\n * in `defineMetrics`. This is an authoring error (a typo'd or stale metric id),\n * not a low score — it fails the eval test rather than being recorded as a\n * failed scorer. Exported so downstream harnesses can type-narrow on it.\n */\nexport class EvalMetricError extends Error {\n /**\n * Creates the error.\n *\n * @param message - Error message.\n */\n constructor(message: string) {\n super(message)\n this.name = 'EvalMetricError'\n }\n}\n\n/**\n * Computes the raw values of the {@link EFFICIENCY_METRICS} for a run: wall-clock time, input plus output tokens, and the share of input read from cache.\n *\n * @param result - Result of the run.\n */\nexport function efficiencyMetricValues(result: HeadlessResult): Record<keyof typeof EFFICIENCY_METRICS, number> {\n const u = result.usage\n // Fraction of read-side input served from cache. cacheRead is reported on top\n // of `input`, so the denominator is cacheRead + input (not input alone).\n const readTotal = u.input + u.cacheRead\n return {\n 'execution-time': result.durationMs,\n 'provider-tokens': u.input + u.output,\n 'cache-read-rate': readTotal > 0 ? u.cacheRead / readTotal : 0,\n }\n}\n\n/**\n * Emits every efficiency metric for a run through `emit`.\n *\n * @param emit - Callback that receives each metric id and raw value.\n * @param result - Result of the run.\n */\nexport function emitEfficiencyMetrics(emit: MetricEmitter, result: HeadlessResult): void {\n const values = efficiencyMetricValues(result)\n for (const [id, raw] of Object.entries(values))\n emit(id, raw)\n}\n\n/**\n * Builds the normalized metrics of a case. A declared metric that was never emitted is recorded as missing with a score of `0`.\n *\n * @param specs - Declared metric specs.\n * @param raw - Raw values emitted during the run, keyed by metric id.\n */\nexport function finalizeEvalMetrics(\n specs: MetricSpecMap,\n raw: Map<string, number>,\n): EvalMetric[] {\n // A declared-but-unemitted metric (e.g. a judge that threw mid-run) records\n // as a missing 0 rather than crashing the whole case — evals score what they\n // can and surface the gap, they don't abort the run.\n return Object.entries(specs).map(([metricId, spec]) => {\n const emitted = raw.has(metricId)\n const value = emitted ? raw.get(metricId)! : spec.min\n return {\n id: metricId,\n raw: emitted ? value : 0,\n normalized: emitted ? normalizeMetric(value, spec) : 0,\n direction: spec.direction,\n min: spec.min,\n max: spec.max,\n tags: spec.tags ?? [],\n ...(spec.description ? { description: spec.description } : {}),\n ...(emitted ? {} : { missing: true }),\n }\n })\n}\n\n/**\n * Computes the mean normalized score for each tag across the given metrics.\n *\n * @param metrics - Metrics of one case.\n */\nexport function computeEvalTagScores(metrics: EvalMetric[]): Record<string, number> {\n const byTag = new Map<string, number[]>()\n for (const metric of metrics) {\n for (const tag of metric.tags) {\n const list = byTag.get(tag) ?? []\n list.push(metric.normalized)\n byTag.set(tag, list)\n }\n }\n const out: Record<string, number> = {}\n for (const [tag, values] of byTag)\n out[tag] = mean(values)\n return out\n}\n\nexport function meanNormalized(metrics: EvalMetric[]): number {\n return metrics.length === 0 ? 0 : mean(metrics.map(m => m.normalized))\n}\n\nexport function mean(values: number[]): number {\n return values.length === 0 ? 0 : values.reduce((a, b) => a + b, 0) / values.length\n}\n","import type { EvalMetric } from './eval-metrics'\nimport type { EvalCaseResult, EvalRunMetricAggregate, EvalRunSummary, EvalVariantSummary, MetricStats } from './eval-types'\nimport { mean } from './eval-metrics'\n\n/** Stable ordering by `variant`, then `suite/id`, so parallel completion order doesn't shuffle output. */\nexport function sortCases(results: readonly EvalCaseResult[]): EvalCaseResult[] {\n return [...results].sort((a, b) => {\n const va = a.variant ?? ''\n const vb = b.variant ?? ''\n if (va !== vb)\n return va.localeCompare(vb)\n const ka = `${a.suite ?? ''}/${a.id}`\n const kb = `${b.suite ?? ''}/${b.id}`\n return ka.localeCompare(kb)\n })\n}\n\n/** Distinct variant labels across results, in sorted order. */\nexport function distinctVariants(results: readonly EvalCaseResult[]): string[] {\n return [...new Set(results.map(r => r.variant).filter((v): v is string => Boolean(v)))].sort()\n}\n\n/**\n * Builds the summary of an eval run: case counts, mean score, duration and usage totals, one row per case, metric and tag aggregates, and per-variant summaries when cases have variants.\n *\n * @param input - Case results in any order. They are sorted by variant, then suite and id.\n */\nexport function buildEvalRunSummary(input: readonly EvalCaseResult[]): EvalRunSummary {\n const results = sortCases(input)\n const usage = results.reduce((acc, result) => {\n acc.input += result.result.usage.input\n acc.output += result.result.usage.output\n acc.cacheRead += result.result.usage.cacheRead\n acc.cacheCreation += result.result.usage.cacheCreation\n acc.cost += result.result.usage.cost ?? 0\n return acc\n }, { input: 0, output: 0, cacheRead: 0, cacheCreation: 0, cost: 0 })\n const totalScore = results.reduce((sum, result) => sum + result.score, 0)\n\n return {\n count: results.length,\n passed: results.filter(result => result.passed).length,\n score: results.length > 0 ? totalScore / results.length : 0,\n durationMs: results.reduce((sum, result) => sum + result.result.durationMs, 0),\n usage,\n cases: results.map(result => ({\n id: result.id,\n ...(result.suite ? { suite: result.suite } : {}),\n ...(result.variant ? { variant: result.variant } : {}),\n passed: result.passed,\n score: result.score,\n status: result.result.status,\n durationMs: result.result.durationMs,\n scores: result.scores,\n metrics: result.metrics,\n tagScores: result.tagScores,\n trajectory: result.trajectory,\n })),\n metrics: aggregateMetrics(results),\n tagScores: aggregateTagScores(results),\n ...(distinctVariants(results).length > 0 ? { variants: aggregateVariants(results) } : {}),\n }\n}\n\nexport function aggregateVariants(results: readonly EvalCaseResult[]): EvalVariantSummary[] {\n return distinctVariants(results).map((variant) => {\n const group = results.filter(r => r.variant === variant)\n const usage = group.reduce((acc, result) => {\n acc.input += result.result.usage.input\n acc.output += result.result.usage.output\n acc.cacheRead += result.result.usage.cacheRead\n acc.cacheCreation += result.result.usage.cacheCreation\n acc.cost += result.result.usage.cost ?? 0\n return acc\n }, { input: 0, output: 0, cacheRead: 0, cacheCreation: 0, cost: 0 })\n return {\n variant,\n count: group.length,\n passed: group.filter(r => r.passed).length,\n score: mean(group.map(r => r.score)),\n durationMs: group.reduce((sum, r) => sum + r.result.durationMs, 0),\n usage,\n turns: group.reduce((sum, r) => sum + r.result.turns, 0),\n toolCalls: group.reduce((sum, r) => sum + r.result.numToolCalls, 0),\n }\n })\n}\n\nfunction aggregateMetrics(results: readonly EvalCaseResult[]): EvalRunMetricAggregate[] {\n const byId = new Map<string, EvalMetric[]>()\n for (const result of results) {\n for (const metric of result.metrics) {\n const list = byId.get(metric.id) ?? []\n list.push(metric)\n byId.set(metric.id, list)\n }\n }\n return [...byId.entries()].map(([id, metrics]) => ({\n id,\n direction: metrics[0].direction,\n tags: metrics[0].tags,\n raw: metricStats(metrics.map(m => m.raw)),\n normalized: metricStats(metrics.map(m => m.normalized)),\n }))\n}\n\nfunction aggregateTagScores(results: readonly EvalCaseResult[]): Record<string, number> {\n const byTag = new Map<string, number[]>()\n for (const result of results) {\n for (const [tag, value] of Object.entries(result.tagScores)) {\n const list = byTag.get(tag) ?? []\n list.push(value)\n byTag.set(tag, list)\n }\n }\n const out: Record<string, number> = {}\n for (const [tag, values] of byTag)\n out[tag] = mean(values)\n return out\n}\n\nfunction metricStats(values: number[]): MetricStats {\n const sorted = [...values].sort((a, b) => a - b)\n return {\n mean: mean(values),\n min: sorted[0] ?? 0,\n max: sorted[sorted.length - 1] ?? 0,\n p50: percentile(sorted, 0.5),\n p90: percentile(sorted, 0.9),\n zeroCount: values.filter(v => v === 0).length,\n values,\n }\n}\n\nfunction percentile(sorted: number[], q: number): number {\n if (sorted.length === 0)\n return 0\n const idx = Math.min(sorted.length - 1, Math.max(0, Math.ceil(q * sorted.length) - 1))\n return sorted[idx]\n}\n","import type { EvalMetric } from './eval-metrics'\nimport type { Trajectory, TrajectoryStepKind } from './eval-trajectory'\nimport type { EvalCaseResult, EvalRunSummary, EvalScore, EvalVariantSummary } from './eval-types'\nimport { resolve } from 'node:path'\nimport chalk from 'chalk'\nimport { mean } from './eval-metrics'\nimport { aggregateVariants, buildEvalRunSummary, distinctVariants, sortCases } from './eval-summary'\n\n/**\n * Formats one case result as plain text: status, score, duration, usage, workspace and artifact info, and per-scorer results.\n *\n * @param result - Case result to format.\n */\nexport function formatEvalCaseSummary(result: EvalCaseResult): string {\n const lines = [\n `Eval ${result.suite ? `${result.suite}/` : ''}${result.id}`,\n ...(result.variant ? [`variant: ${result.variant}`] : []),\n `status: ${result.result.status}`,\n `passed: ${result.passed}`,\n `score: ${result.score.toFixed(2)}`,\n `duration: ${result.result.durationMs}ms`,\n `turns: ${result.result.turns}`,\n `tool calls: ${result.result.numToolCalls}`,\n `usage: input=${result.result.usage.input} output=${result.result.usage.output} cacheRead=${result.result.usage.cacheRead} cacheCreation=${result.result.usage.cacheCreation}${result.result.usage.cost !== undefined ? ` cost=$${result.result.usage.cost.toFixed(6)}` : ''}`,\n ]\n\n if (result.workspace) {\n lines.push(`workspace files: ${result.workspace.files.length}`)\n }\n if (result.workspaceError) {\n lines.push(`workspace error: ${result.workspaceError}`)\n }\n if (result.artifacts) {\n lines.push(`artifacts: ${result.artifacts.dir}`)\n }\n\n if (result.scores.length > 0) {\n lines.push('scores:')\n for (const score of result.scores) {\n const value = score.score !== undefined ? score.score.toFixed(2) : score.passed ? '1.00' : '0.00'\n lines.push(` - ${score.name}: ${value} ${score.passed ? 'pass' : 'fail'}`)\n if (typeof score.details === 'string' && score.details.length > 0)\n lines.push(` ${score.details}`)\n else if (isRecord(score.details) && typeof score.details.reasoning === 'string')\n lines.push(` ${score.details.reasoning}`)\n }\n }\n\n return lines.join('\\n')\n}\n\n/**\n * Formats an eval run as a terminal table, with a comparison matrix when the cases have more than one variant.\n *\n * @param results - Case results in any order.\n */\nexport function formatEvalRunSummary(results: readonly EvalCaseResult[]): string {\n return formatEvalRunSummaryWithOptions(results)\n}\n\nexport function formatEvalRunSummaryWithOptions(\n input: readonly EvalCaseResult[],\n options: { color?: boolean } = {},\n): string {\n const results = sortCases(input)\n const color = createEvalColors(options.color)\n if (results.length === 0)\n return `${color.heading('Eval run summary')}\\n${color.muted('no evals ran')}`\n\n const summary = buildEvalRunSummary(results)\n const out: string[] = []\n const variants = distinctVariants(results)\n\n out.push(color.heading('Eval run summary'))\n if (variants.length > 1) {\n // Multi-target run: lead with the cross-variant comparison matrix, then\n // one results table per variant so each target stays fully inspectable.\n out.push(renderComparisonTable(results, variants, color))\n for (const variant of variants) {\n const group = results.filter(r => r.variant === variant)\n out.push('')\n out.push(color.heading(variant))\n out.push(renderResultsTable(group, buildEvalRunSummary(group), color))\n }\n }\n else {\n out.push(renderResultsTable(results, summary, color))\n }\n\n const tagTable = renderTagTable(summary.tagScores, color)\n if (tagTable) {\n out.push('')\n out.push(tagTable)\n }\n out.push('')\n\n // Per-eval breakdown beneath the tables.\n const hyperlinks = options.color !== false\n const linkText = (target: string): string => {\n const abs = absPath(target)\n return hyperlinks ? oscLink(abs, abs) : abs\n }\n\n for (const result of results) {\n const caseLabel = `${result.suite ? `${result.suite}/` : ''}${result.id}`\n const label = result.variant ? `[${result.variant}] ${caseLabel}` : caseLabel\n out.push(`${color.dot(result.passed)} ${color.caseStatus(result.passed, label)}`)\n out.push(`${color.muted('score')} ${color.score(result.score)}`)\n\n const tagEntries = Object.entries(result.tagScores)\n if (tagEntries.length > 0)\n out.push(`${color.muted('tags:')} ${tagEntries.map(([tag, value]) => `${color.tag(tag)} ${color.score(value)}`).join(' ')}`)\n\n for (const metric of result.metrics) {\n const note = metric.missing ? color.fail(' (not emitted)') : color.muted(` (${formatMetricRaw(metric)})`)\n out.push(`${color.muted(padEnd(metric.id, 28))} ${color.score(metric.normalized)}${note}`)\n }\n\n for (const score of result.scores) {\n const detail = scoreDetailLine(score)\n if (!score.passed && detail)\n out.push(`${color.dot(score.passed)} ${color.muted(`${score.name}: ${truncate(detail, 140)}`)}`)\n }\n\n // Links — full absolute paths so they work in every terminal.\n if (result.sourceFile)\n out.push(`${color.muted('case:')} ${color.muted(linkText(result.sourceFile))}`)\n const resultTarget = caseLinkTarget(result)\n if (resultTarget)\n out.push(`${color.muted('result:')} ${color.muted(linkText(resultTarget))}`)\n\n // Turns last — can be very long.\n if (result.trajectory.steps.length > 0)\n out.push(`${color.muted(`turns: ${result.trajectory.totalBlocks}`)} ${formatTrajectoryColored(result.trajectory, color)}`)\n\n out.push('')\n }\n\n return out.join('\\n').replace(/\\n+$/, '')\n}\n\nfunction renderTagTable(tagScores: Record<string, number>, color: EvalColors): string | undefined {\n const entries = Object.entries(tagScores)\n if (entries.length === 0)\n return undefined\n const tagWidth = Math.max('TAG'.length, ...entries.map(([tag]) => tag.length))\n const top = `┌${'─'.repeat(tagWidth + 2)}┬${'─'.repeat(9)}┐`\n const mid = `├${'─'.repeat(tagWidth + 2)}┼${'─'.repeat(9)}┤`\n const bot = `└${'─'.repeat(tagWidth + 2)}┴${'─'.repeat(9)}┘`\n const lines = [\n top,\n `│ ${color.heading(padEnd('TAG', tagWidth))} │ ${color.heading('SCORE')} │`,\n mid,\n ...entries.map(([tag, value]) => `│ ${color.muted(padEnd(tag, tagWidth))} │ ${color.score(value)} │`),\n bot,\n ]\n return lines.join('\\n')\n}\n\nfunction formatMetricRaw(metric: EvalMetric): string {\n const raw = Number.isInteger(metric.raw) ? formatInt(metric.raw) : metric.raw.toFixed(3)\n const arrow = metric.direction === 'lower-is-better' ? '↓' : '↑'\n return `raw ${raw} ${arrow}`\n}\n\n/**\n * Resolve a filesystem target to link an eval case to. Prefers the written\n * artifact (`result.json` → its dir), so the link opens the case's output.\n * Returns `undefined` when no artifacts were written.\n */\nfunction caseLinkTarget(result: EvalCaseResult): string | undefined {\n return result.artifacts?.result ?? result.artifacts?.dir\n}\n\n/** Wrap text in an OSC 8 terminal hyperlink to a local path or URL. */\nfunction oscLink(target: string, text: string): string {\n const url = /^(?:file|https?):\\/\\//.test(target)\n ? target\n : `file://${resolve(target)}`\n const OSC = '\\u001B]8;;'\n const ST = '\\u001B\\\\'\n return `${OSC}${url}${ST}${text}${OSC}${ST}`\n}\n\n/** Absolute filesystem path (strips any `file://` prefix, resolves relatives). */\nfunction absPath(target: string): string {\n const clean = target.replace(/^file:\\/\\//, '')\n return resolve(clean)\n}\n\n/**\n * Case key used to line up the same eval across variants in the comparison\n * matrix. Strips the `-repeat-N` suffix `registerEvalTests` appends so a\n * repeated case aggregates into one row (mean score, x/y passed).\n */\nfunction comparisonCaseKey(result: EvalCaseResult): string {\n const id = result.id.replace(/-repeat-\\d+$/, '')\n return `${result.suite ? `${result.suite}/` : ''}${id}`\n}\n\n/**\n * Cross-variant comparison matrix: one row per eval case, one column per\n * variant (provider/model target), plus rollup rows (score / passed / cost /\n * time) so two models can be read side by side at a glance.\n */\nfunction renderComparisonTable(\n input: readonly EvalCaseResult[],\n variants: string[],\n color: EvalColors,\n): string {\n const results = sortCases(input)\n const caseKeys = [...new Set(results.map(comparisonCaseKey))].sort()\n const byCell = new Map<string, EvalCaseResult[]>()\n for (const result of results) {\n const key = `${comparisonCaseKey(result)}\\u0000${result.variant ?? ''}`\n const list = byCell.get(key) ?? []\n list.push(result)\n byCell.set(key, list)\n }\n\n interface Cell { text: string, score?: number, passed?: boolean }\n const cellFor = (caseKey: string, variant: string): Cell => {\n const group = byCell.get(`${caseKey}\\u0000${variant}`)\n if (!group || group.length === 0)\n return { text: '-' }\n const score = mean(group.map(r => r.score))\n const passedCount = group.filter(r => r.passed).length\n const allPassed = passedCount === group.length\n const status = group.length > 1\n ? `${passedCount}/${group.length}`\n : allPassed ? 'pass' : 'fail'\n return { text: `${score.toFixed(2)} ${status}`, score, passed: allPassed }\n }\n\n const variantSummaries = aggregateVariants(results)\n const summaryOf = (variant: string): EvalVariantSummary | undefined =>\n variantSummaries.find(s => s.variant === variant)\n\n /*\n * Two variants (e.g. `build` vs `codemode`): a Δ column reads the second\n * against the first, green when it is better, red when worse, so the\n * comparison doesn't need mental arithmetic.\n */\n const pair = variants.length === 2\n const header = ['EVAL', ...variants, ...(pair ? [`Δ ${variants[1]}`] : [])]\n\n const rows: Array<{ label: string, cells: Cell[], rollup?: boolean }> = caseKeys.map((key) => {\n const cells = variants.map(variant => cellFor(key, variant))\n if (pair)\n cells.push(deltaCell(cells[0]?.score, cells[1]?.score, 'higher', 'points'))\n return { label: key, cells }\n })\n\n interface Rollup {\n label: string\n value: (s: EvalVariantSummary) => number\n format: (value: number, s: EvalVariantSummary) => string\n better: 'higher' | 'lower'\n /** Score-like rows show an absolute difference; counts and amounts a relative one. */\n delta: 'points' | 'percent'\n /** Paint the value cells (score / pass status) like the per-case cells. */\n paint?: (s: EvalVariantSummary) => Pick<Cell, 'score' | 'passed'>\n }\n // Efficiency rows are summed per variant like COST / TIME: what a setup\n // (e.g. build vs codemode) or model costs in tokens and round-trips.\n const rollupDefs: Rollup[] = [\n { label: 'SCORE', value: s => s.score, format: v => v.toFixed(2), better: 'higher', delta: 'points', paint: s => ({ score: s.score }) },\n { label: 'PASSED', value: s => s.passed, format: (v, s) => `${v}/${s.count}`, better: 'higher', delta: 'points', paint: s => ({ passed: s.passed === s.count }) },\n { label: 'COST', value: s => s.usage.cost, format: v => formatCost(v), better: 'lower', delta: 'percent' },\n { label: 'TIME', value: s => s.durationMs, format: v => formatDuration(v), better: 'lower', delta: 'percent' },\n { label: 'TOKENS', value: s => s.usage.input + s.usage.output, format: v => formatInt(v), better: 'lower', delta: 'percent' },\n { label: 'CACHE R', value: s => s.usage.cacheRead, format: v => formatInt(v), better: 'lower', delta: 'percent' },\n { label: 'TURNS', value: s => s.turns, format: v => String(v), better: 'lower', delta: 'percent' },\n { label: 'TOOL CALLS', value: s => s.toolCalls, format: v => String(v), better: 'lower', delta: 'percent' },\n ]\n const rollups: Array<{ label: string, cells: Cell[], rollup: true }> = rollupDefs.map((def) => {\n const summaries = variants.map(summaryOf)\n const cells: Cell[] = summaries.map(s => s ? { text: def.format(def.value(s), s), ...def.paint?.(s) } : { text: '-' })\n if (pair) {\n const [a, b] = summaries\n cells.push(deltaCell(a ? def.value(a) : undefined, b ? def.value(b) : undefined, def.better, def.delta))\n }\n return { label: def.label, cells, rollup: true }\n })\n\n const allRows = [...rows, ...rollups]\n const widths = header.map((h, i) => Math.max(\n h.length,\n ...allRows.map(row => (i === 0 ? row.label : row.cells[i - 1].text).length),\n ))\n\n const top = `┌${widths.map(w => '─'.repeat(w + 2)).join('┬')}┐`\n const mid = `├${widths.map(w => '─'.repeat(w + 2)).join('┼')}┤`\n const bot = `└${widths.map(w => '─'.repeat(w + 2)).join('┴')}┘`\n\n const paintComparisonCell = (cell: Cell, padded: string): string => {\n if (cell.score === undefined && cell.passed === undefined)\n return color.muted(padded)\n // Re-render the score fragment colored; status colored by pass/fail.\n if (cell.score !== undefined) {\n const scoreText = cell.score.toFixed(2)\n const rest = cell.text.slice(scoreText.length)\n const coloredRest = cell.passed === undefined\n ? color.muted(rest)\n : cell.passed ? color.pass(rest) : color.fail(rest)\n return padded.replace(cell.text, `${color.score(cell.score)}${coloredRest}`)\n }\n return padded.replace(cell.text, cell.passed ? color.pass(cell.text) : color.fail(cell.text))\n }\n\n const renderRow = (row: { label: string, cells: Cell[], rollup?: boolean }): string => {\n const labelPadded = padEnd(row.label, widths[0])\n const labelPainted = row.rollup ? color.heading(labelPadded) : color.muted(labelPadded)\n const cellParts = row.cells.map((cell, i) => {\n const padded = padStart(cell.text, widths[i + 1])\n return ` ${paintComparisonCell(cell, padded)} `\n })\n return `│ ${labelPainted} │${cellParts.join('│')}│`\n }\n\n const lines = [\n top,\n `│ ${color.heading(padEnd(header[0], widths[0]))} │${header.slice(1).map((v, i) => ` ${color.heading(padStart(v, widths[i + 1]))} `).join('│')}│`,\n mid,\n ...rows.map(renderRow),\n mid,\n ...rollups.map(renderRow),\n bot,\n ]\n return lines.join('\\n')\n}\n\n/**\n * The Δ cell of a two-variant comparison: `b` against `a`, as an absolute\n * difference (`points`, for scores and counts of passes) or a relative one\n * (`percent`). Painted pass/fail by whether the change goes the `better` way;\n * unchanged values and missing sides stay muted.\n */\nfunction deltaCell(a: number | undefined, b: number | undefined, better: 'higher' | 'lower', kind: 'points' | 'percent'): { text: string, passed?: boolean } {\n if (a === undefined || b === undefined)\n return { text: '-' }\n const diff = b - a\n if (Math.abs(diff) < 1e-9)\n return { text: '=' }\n const sign = diff > 0 ? '+' : '−'\n const improved = better === 'higher' ? diff > 0 : diff < 0\n if (kind === 'points') {\n const magnitude = Math.abs(diff)\n return { text: `${sign}${Number.isInteger(magnitude) ? magnitude : magnitude.toFixed(2)}`, passed: improved }\n }\n if (a === 0)\n return { text: `${sign}∞`, passed: improved }\n return { text: `${sign}${Math.round(Math.abs(diff / a) * 100)}%`, passed: improved }\n}\n\nfunction renderResultsTable(\n results: readonly EvalCaseResult[],\n summary: EvalRunSummary,\n color: EvalColors,\n): string {\n const header = ['EVAL', 'STATUS', 'SCORE', 'IN', 'OUT', 'CACHE R', 'CACHE W', 'COST', 'TIME']\n const rows = results.map((result) => {\n const label = `${result.suite ? `${result.suite}/` : ''}${result.id}`\n const u = result.result.usage\n return {\n passed: result.passed,\n cells: [\n label,\n result.passed ? 'pass' : 'fail',\n result.score.toFixed(2),\n formatInt(u.input),\n formatInt(u.output),\n formatInt(u.cacheRead),\n formatInt(u.cacheCreation),\n formatCost(u.cost ?? 0),\n formatDuration(result.result.durationMs),\n ],\n score: result.score,\n }\n })\n\n const totals = {\n cells: [\n `TOTAL (${summary.passed}/${summary.count})`,\n summary.passed === summary.count ? 'pass' : 'fail',\n summary.score.toFixed(2),\n formatInt(summary.usage.input),\n formatInt(summary.usage.output),\n formatInt(summary.usage.cacheRead),\n formatInt(summary.usage.cacheCreation),\n formatCost(summary.usage.cost),\n formatDuration(summary.durationMs),\n ],\n passed: summary.passed === summary.count,\n score: summary.score,\n }\n\n // Right-align numeric columns (everything after STATUS).\n const aligns: Array<'left' | 'right'> = ['left', 'left', 'right', 'right', 'right', 'right', 'right', 'right', 'right']\n const widths = header.map((h, i) =>\n Math.max(h.length, ...rows.map(r => r.cells[i].length), totals.cells[i].length),\n )\n\n const top = `┌${widths.map(w => '─'.repeat(w + 2)).join('┬')}┐`\n const mid = `├${widths.map(w => '─'.repeat(w + 2)).join('┼')}┤`\n const bot = `└${widths.map(w => '─'.repeat(w + 2)).join('┴')}┘`\n\n const renderRow = (cells: string[], paint?: (i: number, raw: string, padded: string) => string): string => {\n const parts = cells.map((cell, i) => {\n const padded = aligns[i] === 'right' ? padStart(cell, widths[i]) : padEnd(cell, widths[i])\n return ` ${paint ? paint(i, cell, padded) : padded} `\n })\n return `│${parts.join('│')}│`\n }\n\n const lines = [\n top,\n renderRow(header, (_i, _raw, padded) => color.heading(padded)),\n mid,\n ...rows.map(r => renderRow(r.cells, (i, raw, padded) => paintCell(i, raw, padded, r.passed, r.score, color))),\n mid,\n renderRow(totals.cells, (i, raw, padded) => paintCell(i, raw, padded, totals.passed, totals.score, color, true)),\n bot,\n ]\n return lines.join('\\n')\n}\n\nfunction paintCell(\n col: number,\n raw: string,\n padded: string,\n passed: boolean,\n score: number,\n color: EvalColors,\n bold = false,\n): string {\n // EVAL\n if (col === 0)\n return bold ? color.heading(padded) : color.caseStatus(passed, padded)\n // STATUS\n if (col === 1)\n return padded.replace(raw, color.status(passed))\n // SCORE\n if (col === 2)\n return padded.replace(raw, color.score(score))\n // COST\n if (col === 7)\n return color.cost(padded)\n return color.muted(padded)\n}\n\nfunction scoreDetailLine(score: EvalScore): string | undefined {\n if (typeof score.details === 'string')\n return score.details\n if (isRecord(score.details) && typeof score.details.reasoning === 'string')\n return score.details.reasoning\n return undefined\n}\n\nfunction formatInt(value: number): string {\n return value.toLocaleString('en-US')\n}\n\nfunction formatCost(value: number): string {\n return value > 0 ? `$${value.toFixed(4)}` : '-'\n}\n\nfunction formatDuration(ms: number): string {\n const rounded = Math.round(ms)\n if (rounded < 1000)\n return `${rounded}ms`\n const s = rounded / 1000\n // Drop a trailing `.0` so `4.0s` reads as `4s`.\n return `${Number.isInteger(s) ? s : s.toFixed(1)}s`\n}\n\nfunction padEnd(value: string, width: number): string {\n return value.length >= width ? value : value + ' '.repeat(width - value.length)\n}\n\nfunction padStart(value: string, width: number): string {\n return value.length >= width ? value : ' '.repeat(width - value.length) + value\n}\n\nfunction truncate(value: string, max: number): string {\n const oneLine = value.replace(/\\s+/g, ' ').trim()\n return oneLine.length > max ? `${oneLine.slice(0, max - 1)}…` : oneLine\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null\n}\n\ninterface EvalColors {\n heading: (value: string) => string\n pass: (value: string) => string\n fail: (value: string) => string\n muted: (value: string) => string\n cost: (value: string) => string\n status: (passed: boolean) => string\n score: (value: number) => string\n caseStatus: (passed: boolean, value: string) => string\n dot: (passed: boolean) => string\n tag: (value: string) => string\n step: (kind: TrajectoryStepKind, value: string) => string\n}\n\nfunction createEvalColors(enabled = shouldUseColor()): EvalColors {\n if (!enabled) {\n return {\n heading: value => value,\n pass: value => value,\n fail: value => value,\n muted: value => value,\n cost: value => value,\n status: passed => passed ? 'pass' : 'fail',\n score: value => value.toFixed(2),\n caseStatus: (_passed, value) => value,\n dot: passed => passed ? '+' : 'x',\n tag: value => value,\n step: (_kind, value) => value,\n }\n }\n return {\n heading: value => chalk.bold(value),\n pass: value => chalk.green(value),\n fail: value => chalk.red(value),\n muted: value => chalk.gray(value),\n cost: value => chalk.cyan(value),\n status: passed => passed ? chalk.green('pass') : chalk.red('fail'),\n score: value => value >= 0.9 ? chalk.green(value.toFixed(2)) : value >= 0.7 ? chalk.yellow(value.toFixed(2)) : chalk.red(value.toFixed(2)),\n caseStatus: (passed, value) => passed ? chalk.green(value) : chalk.red(value),\n dot: passed => passed ? chalk.green('●') : chalk.red('●'),\n // Distinct from the step palette (which uses magenta/blue/cyan/yellow/green).\n tag: value => chalk.bold(chalk.whiteBright(value)),\n step: (kind, value) => paintStep(kind, value),\n }\n}\n\n/** Per-kind trajectory colors: think=magenta, text=blue, tools by family. */\nfunction paintStep(kind: TrajectoryStepKind, value: string): string {\n if (kind === 'think')\n return chalk.magenta(value)\n if (kind === 'text')\n return chalk.blue(value)\n // tool step — color by intent so a timeline reads at a glance.\n if (/write|edit|create/.test(value))\n return chalk.green(value)\n if (/read|list|glob|grep|search/.test(value))\n return chalk.cyan(value)\n if (/shell|bash|exec|run/.test(value))\n return chalk.yellow(value)\n if (/spawn|task|agent/.test(value))\n return chalk.magentaBright(value)\n return chalk.white(value)\n}\n\nfunction formatTrajectoryColored(trajectory: Trajectory, color: EvalColors): string {\n return trajectory.steps\n .map((step) => {\n const base = step.kind === 'tool' ? (step.name ?? 'tool') : step.kind\n const labelWithCount = step.count > 1 ? `${base} ×${step.count}` : base\n const painted = color.step(step.kind, labelWithCount)\n const timing = step.durationMs && step.durationMs >= 100 ? color.muted(`(${formatDuration(step.durationMs)})`) : ''\n return timing ? `${painted} ${timing}` : painted\n })\n .join(color.muted(' → '))\n}\n\nfunction shouldUseColor(): boolean {\n return Boolean(process.stdout.isTTY && !process.env.NO_COLOR)\n}\n","import type { EvalScore, EvalScorer, EvalScorerContext } from './eval-types'\nimport { EvalMetricError } from './eval-metrics'\n\n/**\n * Creates a scorer that passes when the run status is `'completed'`.\n *\n * @param name - Scorer name. Defaults to `'status.completed'`.\n */\nexport function statusCompleted(name = 'status.completed'): EvalScorer {\n return ({ result }) => ({\n name,\n passed: result.status === 'completed',\n score: result.status === 'completed' ? 1 : 0,\n details: result.status === 'completed' ? undefined : { status: result.status, error: result.error },\n })\n}\n\n/**\n * Creates a scorer that passes when the workspace snapshot contains `path`.\n *\n * @param path - Path relative to the workspace root.\n * @param name - Scorer name. Defaults to `file.exists:<path>`.\n */\nexport function fileExists(path: string, name = `file.exists:${path}`): EvalScorer {\n return ({ workspace }) => {\n const found = workspace?.files.some(file => file.path === path) ?? false\n return {\n name,\n passed: found,\n score: found ? 1 : 0,\n details: found ? undefined : `Missing ${path}`,\n }\n }\n}\n\n/**\n * Creates a scorer that passes when the workspace snapshot contains at least one of `paths`.\n *\n * @param paths - Paths relative to the workspace root.\n * @param name - Scorer name. Defaults to `file.existsOneOf:<paths joined by |>`.\n */\nexport function fileExistsOneOf(paths: string[], name = `file.existsOneOf:${paths.join('|')}`): EvalScorer {\n return ({ workspace }) => {\n const found = paths.find(path => workspace?.files.some(file => file.path === path))\n return {\n name,\n passed: Boolean(found),\n score: found ? 1 : 0,\n details: found ? undefined : `Missing one of: ${paths.join(', ')}`,\n }\n }\n}\n\n/**\n * Creates a scorer that passes when the captured content of `path` contains `expected`. A missing file fails.\n *\n * @param path - Path relative to the workspace root.\n * @param expected - Substring, or a pattern the content must match.\n * @param name - Scorer name. Defaults to `file.contains:<path>`.\n */\nexport function fileContains(path: string, expected: string | RegExp, name = `file.contains:${path}`): EvalScorer {\n return ({ workspace }) => {\n const file = workspace?.files.find(file => file.path === path)\n const content = file?.content ?? ''\n const passed = typeof expected === 'string' ? content.includes(expected) : expected.test(content)\n return {\n name,\n passed,\n score: passed ? 1 : 0,\n details: passed\n ? undefined\n : file\n ? `Expected ${path} to contain ${String(expected)}`\n : `Missing ${path}`,\n }\n }\n}\n\n/**\n * Creates a scorer that grades how closely a file matches `expected`: 1 for an exact match after trimming, 0.75 when the trimmed content contains `expected`, 0.5 when the raw content does, otherwise 0. It passes at 0.75 or more.\n *\n * @param path - Path relative to the workspace root.\n * @param expected - Text the file should match.\n * @param name - Scorer name. Defaults to `file.quality:<path>`.\n */\nexport function fileContentQuality(\n path: string,\n expected: string,\n name = `file.quality:${path}`,\n): EvalScorer {\n return ({ workspace }) => {\n const file = workspace?.files.find(file => file.path === path)\n const content = file?.content\n if (content === undefined) {\n return {\n name,\n passed: false,\n score: 0,\n details: `Missing ${path}`,\n }\n }\n\n const normalized = content.trim()\n const expectedNormalized = expected.trim()\n const score = normalized === expectedNormalized\n ? 1\n : normalized.includes(expectedNormalized)\n ? 0.75\n : content.includes(expected)\n ? 0.5\n : 0\n\n return {\n name,\n passed: score >= 0.75,\n score,\n details: score >= 0.75 ? undefined : `Expected ${path} to closely match ${JSON.stringify(expectedNormalized)}`,\n }\n }\n}\n\n/**\n * Aggregate a group of boolean scorers into a single `0..1` functionality\n * metric (fraction passed) and emit it. Useful for \"N of M files present\".\n *\n * @param metricId - Declared metric id that receives the fraction.\n * @param scorers - Boolean scorers to run and count.\n * @param name - Scorer name. Defaults to `metricId`.\n */\nexport function functionalityMetric(metricId: string, scorers: EvalScorer[], name = metricId): EvalScorer {\n return async (ctx) => {\n const results = await runScorers(ctx, scorers)\n const passed = results.filter(r => r.passed).length\n const fraction = results.length === 0 ? 1 : passed / results.length\n ctx.metric(metricId, fraction)\n return {\n name,\n passed: passed === results.length,\n score: fraction,\n details: { passed, total: results.length, checks: results.map(r => ({ name: r.name, passed: r.passed })) },\n }\n }\n}\n\nexport async function runScorers(ctx: EvalScorerContext, scorers: EvalScorer[]): Promise<EvalScore[]> {\n const scores: EvalScore[] = []\n for (const scorer of scorers) {\n try {\n scores.push(await scorer(ctx))\n }\n catch (err) {\n if (err instanceof EvalMetricError)\n throw err\n scores.push({\n name: scorer.name || 'anonymous-scorer',\n passed: false,\n score: 0,\n details: err instanceof Error ? err.message : String(err),\n })\n }\n }\n return scores\n}\n\nexport function aggregateScore(scores: EvalScore[]): number {\n if (scores.length === 0)\n return 1\n const total = scores.reduce((sum, score) => sum + (score.score ?? (score.passed ? 1 : 0)), 0)\n return total / scores.length\n}\n","import type { SessionTurn } from './types'\n\n// ---------------------------------------------------------------------------\n// Trajectory\n// ---------------------------------------------------------------------------\n\n/** Kind of a trajectory step: thinking, text output, or a tool call. */\nexport type TrajectoryStepKind = 'think' | 'text' | 'tool'\n\n/**\n * One grouped step in an eval trajectory. Consecutive blocks of the same kind\n * (and, for tools, the same tool name) collapse into a single step with a\n * `count`. A different kind interrupting the run breaks the group.\n *\n * Serializable by design so trajectories round-trip to disk and can be diffed\n * or replayed by other tooling.\n */\nexport interface TrajectoryStep {\n /** What the grouped blocks are. */\n kind: TrajectoryStepKind\n /** Tool name for `kind: 'tool'` steps (canonical, e.g. `read_file`). */\n name?: string\n /** Number of consecutive occurrences grouped into this step. */\n count: number\n /** Approx wall-clock ms attributed to this step's turns, when derivable. */\n durationMs?: number\n}\n\n/** Ordered, grouped view of what an agent did during an eval run. */\nexport interface Trajectory {\n /** Grouped steps in the order they happened. */\n steps: TrajectoryStep[]\n /** Total blocks across all steps (sum of `count`). */\n totalBlocks: number\n}\n\n/**\n * Build an ordered, grouped trajectory from a transcript. Walks assistant\n * turns in order, emitting `think` / `text` / `tool:<name>` steps, grouping\n * only consecutive identical kinds. Per-step duration is approximated from the\n * owning turn's `createdAt` delta to the next turn.\n *\n * @param transcript - Session turns of the run. Only assistant turns contribute steps.\n */\nexport function buildTrajectory(transcript: SessionTurn[]): Trajectory {\n const steps: TrajectoryStep[] = []\n let total = 0\n\n const push = (kind: TrajectoryStepKind, name: string | undefined, durationMs: number): void => {\n total++\n const last = steps[steps.length - 1]\n if (last && last.kind === kind && last.name === name) {\n last.count++\n if (durationMs > 0)\n last.durationMs = (last.durationMs ?? 0) + durationMs\n return\n }\n steps.push({ kind, ...(name ? { name } : {}), count: 1, ...(durationMs > 0 ? { durationMs } : {}) })\n }\n\n for (let i = 0; i < transcript.length; i++) {\n const turn = transcript[i]\n if (turn.role !== 'assistant')\n continue\n const next = transcript[i + 1]\n const turnDuration = next ? Math.max(0, next.createdAt - turn.createdAt) : 0\n const blocks = turn.content.filter(b => b.type === 'thinking' || b.type === 'redacted_thinking' || b.type === 'text' || b.type === 'tool_call')\n // Attribute the turn's elapsed time to its tool calls — that's where the\n // wall-clock actually goes (provider stream + tool execution). think/text\n // blocks within the turn carry no separate timing. Split evenly across the\n // turn's tool calls and round to whole ms so the timeline reads cleanly.\n const toolBlocks = blocks.filter(b => b.type === 'tool_call').length\n const perTool = toolBlocks > 0 ? Math.round(turnDuration / toolBlocks) : 0\n for (const block of blocks) {\n if (block.type === 'thinking' || block.type === 'redacted_thinking')\n push('think', undefined, 0)\n else if (block.type === 'text')\n push('text', undefined, 0)\n else if (block.type === 'tool_call')\n push('tool', block.name, perTool)\n }\n }\n\n return { steps, totalBlocks: total }\n}\n\n/**\n * Render a trajectory as a one-line timeline string (no color).\n *\n * @param trajectory - Trajectory to render.\n */\nexport function formatTrajectoryLine(trajectory: Trajectory): string {\n return trajectory.steps.map(stepLabel).join(' → ')\n}\n\nfunction stepLabel(step: TrajectoryStep): string {\n const base = step.kind === 'tool' ? (step.name ?? 'tool') : step.kind\n return step.count > 1 ? `${base} ×${step.count}` : base\n}\n","import type { ExecutionContext, ExecutionHandle } from './contexts'\nimport type { EvalWorkspaceFile, EvalWorkspaceOptions, EvalWorkspaceSnapshot } from './eval-types'\nimport { mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { createProcessContext } from './contexts'\nimport { alwaysQuote as shellQuote } from './tools/shell-quote'\n\ninterface WorkspaceState {\n execution?: ExecutionContext\n snapshot: () => EvalWorkspaceSnapshot | undefined\n error: () => string | undefined\n cleanup: () => Promise<void>\n}\n\nexport async function prepareWorkspace(\n execution: ExecutionContext | undefined,\n workspace: EvalWorkspaceOptions | undefined,\n): Promise<WorkspaceState> {\n if (!workspace) {\n return {\n snapshot: () => undefined,\n error: () => undefined,\n cleanup: async () => {},\n }\n }\n\n let tempDir: string | undefined\n let baseExecution = execution\n if (!baseExecution) {\n const cwd = workspace.cwd ?? await mkdtemp(join(tmpdir(), 'zidane-eval-'))\n if (!workspace.cwd)\n tempDir = cwd\n baseExecution = createProcessContext({ cwd })\n }\n\n const captured: { snapshot?: EvalWorkspaceSnapshot, error?: string } = {}\n const wrapped = withWorkspaceLifecycle(baseExecution, workspace, captured)\n\n return {\n execution: wrapped,\n snapshot: () => captured.snapshot,\n error: () => captured.error,\n cleanup: async () => {\n if (tempDir && !workspace.retain)\n await rm(tempDir, { recursive: true, force: true })\n },\n }\n}\n\nfunction withWorkspaceLifecycle(\n execution: ExecutionContext,\n workspace: EvalWorkspaceOptions,\n captured: { snapshot?: EvalWorkspaceSnapshot, error?: string },\n): ExecutionContext {\n return {\n ...execution,\n async spawn(config) {\n const handle = await execution.spawn({\n ...config,\n ...(workspace.cwd && !config?.cwd ? { cwd: workspace.cwd } : {}),\n })\n if (workspace.seedDir)\n await seedWorkspace(execution, handle, workspace)\n return handle\n },\n async destroy(handle) {\n try {\n captured.snapshot = await captureWorkspace(execution, handle, workspace)\n }\n catch (err) {\n captured.error = err instanceof Error ? err.message : String(err)\n }\n finally {\n await execution.destroy(handle)\n }\n },\n }\n}\n\nasync function seedWorkspace(\n execution: ExecutionContext,\n handle: ExecutionHandle,\n workspace: EvalWorkspaceOptions,\n): Promise<void> {\n const target = workspace.seedTarget ?? '.'\n const result = await execution.exec(\n handle,\n `mkdir -p ${shellQuote(target)} && cp -R ${shellQuote(`${workspace.seedDir!}/.`)} ${shellQuote(target)}`,\n )\n if (result.exitCode !== 0)\n throw new Error(`Failed to seed eval workspace: ${result.stderr || result.stdout}`)\n}\n\nasync function captureWorkspace(\n execution: ExecutionContext,\n handle: ExecutionHandle,\n workspace: EvalWorkspaceOptions,\n): Promise<EvalWorkspaceSnapshot> {\n const capturePaths = workspace.capture?.length ? workspace.capture : ['.']\n // `-print0` (NUL-delimited) so filenames containing newlines or spaces don't\n // corrupt the listing. Dedup in JS rather than `sort -u`, which has no\n // portable NUL-record mode across GNU (`-z`) and BSD `sort`.\n const command = [\n `cd ${shellQuote(handle.cwd)}`,\n '&&',\n 'for p in',\n capturePaths.map(shellQuote).join(' '),\n '; do',\n 'if [ -e \"$p\" ]; then',\n 'find \"$p\" \\\\( -path \"*/node_modules/*\" -o -path \"*/.git/*\" \\\\) -prune -o -type f -print0',\n '; fi',\n 'done',\n ].join(' ')\n\n const listed = await execution.exec(handle, command)\n if (listed.exitCode !== 0)\n throw new Error(`Failed to list eval workspace: ${listed.stderr || listed.stdout}`)\n\n const maxFileChars = workspace.maxFileChars ?? 256 * 1024\n const files: EvalWorkspaceFile[] = []\n const seen = new Set<string>()\n for (const rawPath of listed.stdout.split('\\0').filter(Boolean)) {\n const path = normalizeSnapshotPath(rawPath)\n if (seen.has(path))\n continue\n seen.add(path)\n const content = await execution.readFile(handle, path)\n const binary = content.includes('\\0')\n const truncated = content.length > maxFileChars\n files.push({\n path,\n size: content.length,\n ...(binary ? { binary: true } : { content: truncated ? content.slice(0, maxFileChars) : content }),\n ...(truncated ? { truncated: true } : {}),\n })\n }\n\n return { cwd: handle.cwd, files }\n}\n\nfunction normalizeSnapshotPath(path: string): string {\n const normalized = path.startsWith('./') ? path.slice(2) : path\n return normalized === '' ? '.' : normalized\n}\n","import type { ExecutionContext, ExecutionHandle } from './contexts'\n\n/** Execution context that shares one handle across runs, plus the hooks to inspect and dispose it. Created by {@link createReusableExecutionContext}. */\nexport interface ReusableExecutionContext {\n /**\n * Execution context facade that reuses one underlying handle. Its\n * `destroy()` is intentionally a no-op; call `dispose()` when the surrounding\n * fixture/run owns teardown.\n */\n execution: ExecutionContext\n /** Destroy the underlying handle if it was spawned. Idempotent. */\n dispose: () => Promise<void>\n /** Current underlying handle, if the agent has spawned one. */\n handle: () => ExecutionHandle | undefined\n}\n\n/**\n * Wrap an execution context so repeated agent runs share one handle until the\n * caller disposes it. This is useful for eval fixtures that want per-test\n * Docker/process lifetime while still using `runHeadless()` per turn.\n *\n * @param base - Execution context to wrap.\n */\nexport function createReusableExecutionContext(base: ExecutionContext): ReusableExecutionContext {\n let handle: ExecutionHandle | undefined\n let spawnPromise: Promise<ExecutionHandle> | undefined\n let disposed = false\n let disposePromise: Promise<void> | undefined\n\n const ensureHandle = (config?: Parameters<ExecutionContext['spawn']>[0]): Promise<ExecutionHandle> => {\n if (disposed)\n throw new Error('Reusable execution context has been disposed')\n if (handle)\n return Promise.resolve(handle)\n spawnPromise ??= base.spawn(config).then((next) => {\n handle = next\n return next\n }, (err) => {\n spawnPromise = undefined\n throw err\n })\n return spawnPromise\n }\n\n const execution: ExecutionContext = {\n ...base,\n async spawn(config) {\n return ensureHandle(config)\n },\n async destroy() {\n // Agent-level destroy means \"end this turn\"; the eval fixture owns the\n // actual execution lifetime and calls dispose() at test teardown.\n },\n }\n\n return {\n execution,\n // Memoize so concurrent dispose()/asyncDispose() calls share one teardown\n // and never run base.destroy twice or orphan an in-flight spawn.\n dispose() {\n disposePromise ??= (async () => {\n disposed = true\n const active = handle ?? await spawnPromise?.catch(() => undefined)\n handle = undefined\n spawnPromise = undefined\n if (active)\n await base.destroy(active)\n })()\n return disposePromise\n },\n handle: () => handle,\n }\n}\n","import type { ExecutionContext } from './contexts'\nimport type { EvalRunUsage } from './eval-types'\nimport type { HeadlessEvent, HeadlessOptions, HeadlessResult } from './headless'\nimport type { Provider } from './providers'\nimport type { Session, SessionStore } from './session'\nimport type { McpServerConfig, SessionTurn } from './types'\nimport { createProcessContext } from './contexts'\nimport { createReusableExecutionContext } from './eval-execution'\nimport { runHeadless } from './headless'\nimport { createMemoryStore, createSession } from './session'\n\n/** Usage and counters of one {@link EvalAgent} run. */\nexport interface EvalAgentRunStats extends EvalRunUsage {\n /** Wall-clock duration of the run in milliseconds. */\n durationMs: number\n /** Number of turns of the run. */\n turns: number\n /** Number of tool calls in the run's transcript. */\n toolCalls: number\n}\n\n/** Totals across every run of an {@link EvalAgent}. */\nexport interface EvalAgentStats extends EvalRunUsage {\n /** Number of completed `run()` calls. */\n runs: number\n /** Sum of per-run agent turns. */\n turns: number\n /** Sum of per-run tool calls. */\n toolCalls: number\n /** Sum of per-run wall-clock durations. */\n durationMs: number\n}\n\n/** Result of one {@link EvalAgent} run. */\nexport interface EvalAgentRunResult {\n /** Full headless result. Its transcript is scoped to this run. */\n result: HeadlessResult\n /** Per-run usage and trajectory counters. */\n stats: EvalAgentRunStats\n /** Transcript turns added by this run (same view as `result.transcript`). */\n newTranscript: SessionTurn[]\n}\n\n/** MCP servers for an {@link EvalAgent}: a fixed list, or a function that returns the list before each run. */\nexport type EvalAgentMcpServers\n = | readonly McpServerConfig[]\n | (() => readonly McpServerConfig[] | Promise<readonly McpServerConfig[]>)\n\n/** Options for {@link createEvalAgent}. The {@link HeadlessOptions} fields set here are the defaults for every run. */\nexport interface CreateEvalAgentOptions extends Omit<HeadlessOptions, 'prompt' | 'provider' | 'execution' | 'cwd' | 'session' | 'store' | 'mcpServers' | 'onEvent' | 'signal'> {\n /** Provider that drives the agent. */\n provider: Provider\n /**\n * Working directory for the default process context. Ignored when\n * `execution` is supplied.\n */\n cwd?: string\n /**\n * Execution context for agent tools. Wrapped with\n * `createReusableExecutionContext` so runs share one handle until `dispose`.\n */\n execution?: ExecutionContext\n /** Session to reuse across runs. When omitted, one in-memory session is created. */\n session?: Session\n /** Store used for the auto-created session. Defaults to an in-memory store. */\n store?: SessionStore\n /** Static or lazily resolved MCP servers. Resolved fresh before each run. */\n mcpServers?: EvalAgentMcpServers\n /** Live event callback for every run. */\n onEvent?: (event: HeadlessEvent) => void\n}\n\n/** Options for one {@link EvalAgent.run} call. Overrides the defaults set in {@link createEvalAgent}; `mcpServers` are added to the agent's own. */\nexport interface EvalAgentRunOptions extends Omit<HeadlessOptions, 'provider' | 'execution' | 'cwd' | 'session' | 'store'> {\n prompt: HeadlessOptions['prompt']\n}\n\n/** Multi-turn agent for evals. Every run shares one session and one execution handle. */\nexport interface EvalAgent {\n /** Runs one prompt in the shared session. Throws when a run is already in progress or the agent is disposed. */\n run: (options: EvalAgentRunOptions) => Promise<EvalAgentRunResult>\n /** Totals across the runs so far. */\n readonly stats: EvalAgentStats\n /** Returns the shared session, creating it on the first call. Throws after `dispose`. */\n session: () => Promise<Session>\n /** Destroys the shared execution handle. Safe to call more than once. */\n dispose: () => Promise<void>\n /** Same as `dispose`, for `await using`. */\n [Symbol.asyncDispose]: () => Promise<void>\n}\n\n/**\n * Multi-turn eval agent over the low-level headless runner. It keeps session\n * and execution lifetime outside any Playwright-specific fixture layer,\n * so downstream platforms can wrap it with their own `agent.run(...)` shape.\n *\n * @param options - Provider plus {@link HeadlessOptions} defaults for every run. `cwd`, `execution`, `session` and `store` set up the shared environment.\n *\n * @example\n * ~~~ts\n * import { createEvalAgent } from 'zidane/eval'\n * import { anthropic } from 'zidane/providers/anthropic'\n *\n * const agent = createEvalAgent({\n * provider: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }),\n * maxTurns: 8,\n * })\n *\n * await agent.run({ prompt: 'Create hello.txt containing \"hi\".' })\n * const second = await agent.run({ prompt: 'Append \" there\" to hello.txt.' })\n *\n * console.log(second.stats.turns, agent.stats.runs)\n * await agent.dispose()\n * ~~~\n */\nexport function createEvalAgent(options: CreateEvalAgentOptions): EvalAgent {\n const {\n cwd,\n execution,\n session: initialSession,\n store: initialStore,\n mcpServers: baseMcpServers,\n onEvent: baseOnEvent,\n ...headlessDefaults\n } = options\n const executionOwner = createReusableExecutionContext(execution ?? createProcessContext({ cwd }))\n const store = initialStore ?? createMemoryStore()\n let sessionPromise: Promise<Session> | undefined = initialSession ? Promise.resolve(initialSession) : undefined\n let disposed = false\n let runInFlight = false\n let disposePromise: Promise<void> | undefined\n\n const stats: EvalAgentStats = {\n runs: 0,\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheCreation: 0,\n cost: 0,\n turns: 0,\n toolCalls: 0,\n durationMs: 0,\n }\n\n async function getSession(): Promise<Session> {\n if (disposed)\n throw new Error('Eval agent has been disposed')\n sessionPromise ??= createSession({ store })\n return sessionPromise\n }\n\n async function resolveMcpServers(\n runServers: HeadlessOptions['mcpServers'] | undefined,\n ): Promise<McpServerConfig[] | undefined> {\n const base = typeof baseMcpServers === 'function'\n ? await baseMcpServers()\n : baseMcpServers\n const merged = [\n ...(base ?? []),\n ...(runServers ?? []),\n ]\n return merged.length > 0 ? [...merged] : undefined\n }\n\n async function run(runOptions: EvalAgentRunOptions): Promise<EvalAgentRunResult> {\n if (runInFlight)\n throw new Error('Eval agent already has a run in progress')\n runInFlight = true\n try {\n const session = await getSession()\n const { mcpServers: runMcpServers, onEvent: runOnEvent, ...restRunOptions } = runOptions\n const mcpServers = await resolveMcpServers(runMcpServers)\n\n const result = await runHeadless({\n ...headlessDefaults,\n ...restRunOptions,\n session,\n execution: executionOwner.execution,\n ...(mcpServers ? { mcpServers } : {}),\n onEvent(event) {\n baseOnEvent?.(event)\n runOnEvent?.(event)\n },\n })\n\n // `result.transcript` is already scoped to this run (runHeadless slices\n // from the resumed session's prior length), so it IS the new turns.\n const newTranscript = result.transcript.slice()\n const runStats: EvalAgentRunStats = {\n input: result.usage.input,\n output: result.usage.output,\n cacheRead: result.usage.cacheRead,\n cacheCreation: result.usage.cacheCreation,\n cost: result.usage.cost ?? 0,\n durationMs: result.durationMs,\n turns: result.turns,\n toolCalls: countToolCallsInTurns(newTranscript),\n }\n accumulateEvalAgentStats(stats, runStats)\n\n return { result, stats: runStats, newTranscript }\n }\n finally {\n runInFlight = false\n }\n }\n\n function dispose(): Promise<void> {\n // Memoize: concurrent dispose()/asyncDispose() share one teardown.\n disposePromise ??= (async () => {\n disposed = true\n await executionOwner.dispose()\n })()\n return disposePromise\n }\n\n return {\n run,\n stats,\n session: getSession,\n dispose,\n [Symbol.asyncDispose]: dispose,\n }\n}\n\nfunction accumulateEvalAgentStats(acc: EvalAgentStats, turn: EvalAgentRunStats): void {\n acc.runs += 1\n acc.input += turn.input\n acc.output += turn.output\n acc.cacheRead += turn.cacheRead\n acc.cacheCreation += turn.cacheCreation\n acc.cost += turn.cost\n acc.turns += turn.turns\n acc.toolCalls += turn.toolCalls\n acc.durationMs += turn.durationMs\n}\n\nfunction countToolCallsInTurns(turns: readonly SessionTurn[]): number {\n let count = 0\n for (const turn of turns) {\n if (turn.role !== 'assistant')\n continue\n count += turn.content.filter(block => block.type === 'tool_call').length\n }\n return count\n}\n","import type { EvalScorer, EvalScorerContext } from './eval-types'\nimport type { Provider, ToolCall, ToolSpec } from './providers'\n\n/** Options for {@link llmJudge}. */\nexport interface LlmJudgeOptions {\n /** Scorer name. Defaults to `'llm.judge'`. */\n name?: string\n /** Provider that runs the judge model. */\n provider: Provider\n /** Judge model id. Defaults to the provider's default model. */\n model?: string\n /** System prompt for the judge. Defaults to a strict grading prompt. */\n system?: string\n /** Rubric the output is graded against. */\n rubric: string\n /**\n * Output budget for the grade call. Default {@link DEFAULT_JUDGE_MAX_TOKENS}.\n * A judge that runs out mid-`submit_grade` loses the whole call (providers\n * drop an unfinished tool call), so it is retried once with twice the budget.\n */\n maxTokens?: number\n /** Wall-clock cap for the judge provider call. Defaults to 60s. */\n timeoutMs?: number\n /** Select what the judge sees. Defaults to final text plus captured workspace files. */\n input?: (ctx: EvalScorerContext) => string\n /** Declared metric id to emit the judge's `0..1` score into. */\n metric?: string\n}\n\n/**\n * Room for the reasoning on a real app: at 600 the judge of a multi-file\n * workspace ran out mid-`submit_grade` and the case scored `0` (\"no parseable\n * score\") while the shorter evals graded fine.\n */\nexport const DEFAULT_JUDGE_MAX_TOKENS = 4000\n\nconst UNPARSEABLE_REASONING = 'Judge did not return a parseable score.'\n\nconst DEFAULT_JUDGE_SYSTEM = [\n 'You are a strict software eval judge.',\n 'Grade only the supplied output against the rubric.',\n 'Call the `submit_grade` tool with your score and reasoning.',\n 'The score must be between 0 and 1.',\n].join('\\n')\n\n/** Forced-output tool the judge must call — the schema-enforcement path. */\nconst JUDGE_TOOL: ToolSpec = {\n name: 'submit_grade',\n description: 'Submit the grade for the output under evaluation.',\n inputSchema: {\n type: 'object',\n properties: {\n score: { type: 'number', minimum: 0, maximum: 1, description: 'Quality score from 0 (worst) to 1 (best).' },\n reasoning: { type: 'string', description: 'Brief justification for the score.' },\n feedback: { type: 'string', description: 'Optional actionable feedback.' },\n },\n required: ['score', 'reasoning'],\n additionalProperties: false,\n },\n}\n\n/**\n * Creates a scorer that asks a model to grade the run against a rubric. The judge answers through a forced `submit_grade` tool call with a score from 0 to 1 and a short reasoning. The scorer passes at a score of 0.7 or more.\n *\n * @param options - Judge provider, rubric and optional model, prompt and limits.\n */\nexport function llmJudge(options: LlmJudgeOptions): EvalScorer {\n const name = options.name ?? 'llm.judge'\n const model = options.model ?? options.provider.meta.defaultModel\n return async (ctx) => {\n const userMessage = options.provider.userMessage(renderJudgePrompt({\n rubric: options.rubric,\n input: options.input?.(ctx) ?? defaultJudgeInput(ctx),\n }))\n\n // Primary: forced structured output via a single tool call. This is the\n // same enforcement the agent loop uses for `schema`, and it works on any\n // tool-calling provider (Anthropic, OpenAI, Cerebras, OpenRouter, ...).\n let text = ''\n const controller = new AbortController()\n const timeoutMs = options.timeoutMs ?? 60_000\n let timedOut = false\n const timer = timeoutMs > 0\n ? setTimeout(() => {\n timedOut = true\n controller.abort(new Error(`LLM judge timed out after ${timeoutMs}ms`))\n }, timeoutMs)\n : undefined\n\n const timeoutPromise = timeoutMs > 0\n ? new Promise<never>((_resolve, reject) => {\n controller.signal.addEventListener('abort', () => {\n if (timedOut)\n reject(new Error(`LLM judge timed out after ${timeoutMs}ms`))\n }, { once: true })\n })\n : undefined\n // Swallowed when the race already settled, so a late abort is not an unhandled rejection.\n timeoutPromise?.catch(() => {})\n\n const grade = async (maxTokens: number) => {\n text = ''\n const streamPromise = options.provider.stream({\n model,\n system: options.system ?? DEFAULT_JUDGE_SYSTEM,\n tools: options.provider.formatTools([JUDGE_TOOL]),\n messages: [userMessage],\n maxTokens,\n cache: false,\n signal: controller.signal,\n toolChoice: { type: 'tool', name: JUDGE_TOOL.name },\n }, {\n onText(delta) {\n text += delta\n },\n })\n return timeoutPromise ? await Promise.race([streamPromise, timeoutPromise]) : await streamPromise\n }\n\n try {\n const budget = options.maxTokens ?? DEFAULT_JUDGE_MAX_TOKENS\n let result = await grade(budget)\n const submitted = (r: typeof result) => r.toolCalls.some(tc => tc.name === JUDGE_TOOL.name)\n if (!submitted(result) && result.usage.finishReason === 'length')\n result = await grade(budget * 2)\n\n const parsed = readJudgeResult(result.toolCalls, text || result.text)\n if (!submitted(result) && parsed.reasoning === UNPARSEABLE_REASONING && result.usage.finishReason)\n parsed.reasoning = `${UNPARSEABLE_REASONING} (finish reason: ${result.usage.finishReason})`\n if (options.metric)\n ctx.metric(options.metric, parsed.score)\n return {\n name,\n passed: parsed.score >= 0.7,\n score: parsed.score,\n details: {\n reasoning: parsed.reasoning,\n ...(parsed.feedback ? { feedback: parsed.feedback } : {}),\n ...(parsed.raw ? { raw: parsed.raw } : {}),\n usage: result.usage,\n },\n }\n }\n finally {\n if (timer)\n clearTimeout(timer)\n }\n }\n}\n\nfunction readJudgeResult(\n toolCalls: ToolCall[],\n fallbackText: string,\n): { score: number, reasoning: string, feedback?: string, raw?: string } {\n // Preferred: the forced tool call carries typed fields.\n const call = toolCalls.find(tc => tc.name === JUDGE_TOOL.name)\n if (call) {\n const input = call.input as { score?: unknown, reasoning?: unknown, feedback?: unknown }\n return {\n score: clampScore(input.score),\n reasoning: typeof input.reasoning === 'string' ? input.reasoning : '',\n ...(typeof input.feedback === 'string' ? { feedback: input.feedback } : {}),\n }\n }\n // Fallback: a provider that ignored tool-forcing and returned text. The\n // lenient parser recovers a score from JSON/prose/bare-number output.\n return parseJudgeOutput(fallbackText)\n}\n\nfunction renderJudgePrompt(input: { rubric: string, input: string }): string {\n return [\n 'Rubric:',\n input.rubric,\n '',\n 'Output to grade:',\n input.input,\n '',\n 'Return JSON only.',\n ].join('\\n')\n}\n\nfunction defaultJudgeInput(ctx: EvalScorerContext): string {\n const chunks = [\n `Final answer:\\n${ctx.result.finalText}`,\n ]\n if (ctx.workspace) {\n chunks.push(`Workspace files:\\n${ctx.workspace.files.map(file => [\n `--- ${file.path}${file.truncated ? ' (truncated)' : ''} ---`,\n file.binary ? '[binary omitted]' : file.content ?? '',\n ].join('\\n')).join('\\n')}`)\n }\n return chunks.join('\\n\\n')\n}\n\nfunction parseJudgeOutput(raw: string): { score: number, reasoning: string, feedback?: string, raw?: string } {\n const trimmed = stripCodeFences(raw.trim())\n\n // Preferred path: a JSON object somewhere in the output.\n const jsonText = extractJsonObject(trimmed)\n if (jsonText) {\n try {\n const parsed = JSON.parse(jsonText) as Record<string, unknown>\n if (parsed.score !== undefined || parsed.reasoning !== undefined) {\n return {\n score: clampScore(parsed.score),\n reasoning: typeof parsed.reasoning === 'string' ? parsed.reasoning : '',\n ...(typeof parsed.feedback === 'string' ? { feedback: parsed.feedback } : {}),\n ...(jsonText === trimmed ? {} : { raw: trimmed }),\n }\n }\n }\n catch {\n // fall through to lenient parsing\n }\n }\n\n // Lenient fallbacks for models that don't honor strict JSON:\n // 1) a `\"score\": 0.8` / `score = 0.8` fragment anywhere.\n const scoreFragment = trimmed.match(/score[\"']?\\s*[:=]\\s*(-?\\d+(?:\\.\\d+)?)/i)\n if (scoreFragment) {\n return { score: clampScore(Number(scoreFragment[1])), reasoning: trimmed.slice(0, 500), raw: trimmed }\n }\n // 2) the whole output is just a number (`0.8` or `8/10`).\n const bareFraction = trimmed.match(/^(-?\\d+(?:\\.\\d+)?)\\s*\\/\\s*(\\d+(?:\\.\\d+)?)$/)\n if (bareFraction) {\n const denom = Number(bareFraction[2])\n return { score: clampScore(denom === 0 ? 0 : Number(bareFraction[1]) / denom), reasoning: trimmed, raw: trimmed }\n }\n const bareNumber = trimmed.match(/^-?\\d+(?:\\.\\d+)?$/)\n if (bareNumber) {\n return { score: clampScore(Number(trimmed)), reasoning: '', raw: trimmed }\n }\n\n return { score: 0, reasoning: UNPARSEABLE_REASONING, raw: trimmed }\n}\n\n/** Strip a leading/trailing markdown code fence (``` or ```json). */\nfunction stripCodeFences(text: string): string {\n const fence = text.match(/^```(?:json)?[ \\t]*\\n([\\s\\S]*?)\\n```$/i)\n return fence ? fence[1].trim() : text\n}\n\n/** Extract the first balanced `{...}` object, ignoring braces inside strings. */\nfunction extractJsonObject(text: string): string | undefined {\n const start = text.indexOf('{')\n if (start === -1)\n return undefined\n let depth = 0\n let inString = false\n let escaped = false\n for (let i = start; i < text.length; i++) {\n const ch = text[i]\n if (inString) {\n if (escaped)\n escaped = false\n else if (ch === '\\\\')\n escaped = true\n else if (ch === '\"')\n inString = false\n continue\n }\n if (ch === '\"') {\n inString = true\n }\n else if (ch === '{') {\n depth++\n }\n else if (ch === '}') {\n depth--\n if (depth === 0)\n return text.slice(start, i + 1)\n }\n }\n return undefined\n}\n\nfunction clampScore(value: unknown): number {\n const n = typeof value === 'number' ? value : Number(value)\n if (!Number.isFinite(n))\n return 0\n return Math.max(0, Math.min(1, n))\n}\n","import type { EvalCaseOptions, EvalDefinition, EvalDefinitionContext } from './eval-types'\nimport type { Provider } from './providers'\n\ninterface RegisteredEval {\n id: string\n define: EvalDefinition\n}\n\nconst evalRegistry: RegisteredEval[] = []\n\nconst STUB_PROVIDER = {\n name: 'stub',\n meta: { defaultModel: 'stub' },\n formatTools: (tools: unknown[]) => tools,\n userMessage: () => ({ role: 'user' as const, content: [] }),\n assistantMessage: () => ({ role: 'assistant' as const, content: [] }),\n toolResultsMessage: () => ({ role: 'user' as const, content: [] }),\n stream: async () => {\n throw new Error('stub provider is not runnable')\n },\n} as unknown as Provider\n\n/**\n * Register an eval definition. Eval files call this at module load; the harness\n * (`buildRegisteredEvals`) materializes them with a provider at run time. The\n * factory keeps definitions lazy so a single registry serves any provider/judge\n * pairing without re-importing eval files.\n *\n * Returns the same factory so a file can also `export default` it for direct,\n * registry-free use (e.g. hermetic unit tests).\n *\n * @param define - Function that builds the eval case from the provider and judge.\n *\n * @example\n * ~~~ts\n * import { defineEval, fileExists, statusCompleted } from 'zidane/eval'\n *\n * export default defineEval(({ provider, model }) => ({\n * id: 'creates-readme',\n * suite: 'files',\n * prompt: 'Create README.md with a one-line project description.',\n * provider,\n * model,\n * workspace: { capture: ['.'] },\n * scorers: [statusCompleted(), fileExists('README.md')],\n * }))\n * ~~~\n */\nexport function defineEval(define: EvalDefinition): EvalDefinition {\n // De-dupe by materializing once with a stub provider to read the id. The stub\n // is never streamed; it only exists so the registry can key on suite/id and a\n // re-imported module doesn't double-register.\n const id = safeRegistryId(define)\n if (!evalRegistry.some(entry => entry.id === id))\n evalRegistry.push({ id, define })\n return define\n}\n\n/**\n * Snapshot of every registered eval, materialized for one provider/judge pair.\n *\n * @param ctx - Provider and judge to build the eval cases with.\n */\nexport function buildRegisteredEvals(ctx: EvalDefinitionContext): EvalCaseOptions[] {\n return evalRegistry.map(entry => entry.define(ctx))\n}\n\n/** Drop every registered eval — test isolation helper. */\nexport function clearRegisteredEvals(): void {\n evalRegistry.length = 0\n}\n\nfunction safeRegistryId(define: EvalDefinition): string {\n try {\n const stub = define({ provider: STUB_PROVIDER, judge: STUB_PROVIDER })\n return `${stub.suite ?? 'eval'}/${stub.id}`\n }\n catch {\n return `eval/${evalRegistry.length}`\n }\n}\n","import type { MetricEmitter, MetricSpecMap } from './eval-metrics'\nimport type { EvalCaseOptions, EvalCaseResult, EvalRunReporter, EvalRunReporterOptions, EvalScorerContext } from './eval-types'\nimport type { HeadlessEvent } from './headless'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { safeSegment, writeEvalArtifacts } from './eval-artifacts'\nimport { computeEvalTagScores, EFFICIENCY_METRICS, emitEfficiencyMetrics, EvalMetricError, finalizeEvalMetrics, meanNormalized } from './eval-metrics'\nimport { formatEvalRunSummaryWithOptions } from './eval-report'\nimport { aggregateScore, runScorers } from './eval-scorers'\nimport { buildEvalRunSummary } from './eval-summary'\nimport { buildTrajectory } from './eval-trajectory'\nimport { prepareWorkspace } from './eval-workspace'\nimport { runHeadless } from './headless'\n\nexport type { CreateEvalAgentOptions, EvalAgent, EvalAgentMcpServers, EvalAgentRunOptions, EvalAgentRunResult, EvalAgentRunStats, EvalAgentStats } from './eval-agent'\nexport { createEvalAgent } from './eval-agent'\nexport { artifactPath, relativeArtifactPath } from './eval-artifacts'\nexport type { ReusableExecutionContext } from './eval-execution'\nexport { createReusableExecutionContext } from './eval-execution'\nexport type { LlmJudgeOptions } from './eval-judge'\nexport { llmJudge } from './eval-judge'\nexport type { EvalMetric, MetricDirection, MetricEmitter, MetricSpec, MetricSpecMap } from './eval-metrics'\nexport { computeEvalTagScores, defineMetrics, EFFICIENCY_METRICS, efficiencyMetricValues, emitEfficiencyMetrics, EvalMetricError, finalizeEvalMetrics, normalizeMetric } from './eval-metrics'\nexport { buildRegisteredEvals, clearRegisteredEvals, defineEval } from './eval-registry'\nexport { formatEvalCaseSummary, formatEvalRunSummary } from './eval-report'\nexport { fileContains, fileContentQuality, fileExists, fileExistsOneOf, functionalityMetric, statusCompleted } from './eval-scorers'\nexport { buildEvalRunSummary } from './eval-summary'\nexport type { Trajectory, TrajectoryStep, TrajectoryStepKind } from './eval-trajectory'\nexport { buildTrajectory, formatTrajectoryLine } from './eval-trajectory'\nexport type { EvalArtifacts, EvalCaseOptions, EvalCaseResult, EvalDefinition, EvalDefinitionContext, EvalRunMetricAggregate, EvalRunReporter, EvalRunReporterOptions, EvalRunSummary, EvalRunSummaryCase, EvalRunUsage, EvalScore, EvalScorer, EvalScorerContext, EvalVariantSummary, EvalWorkspaceFile, EvalWorkspaceOptions, EvalWorkspaceSnapshot, MetricStats } from './eval-types'\n\n/**\n * Runs one eval case: prepares the workspace, runs the agent headless, runs the scorers, computes metrics and the trajectory, and writes artifacts when `artifactDir` is set. The workspace is cleaned up when the run ends.\n *\n * Throws {@link EvalMetricError} when a scorer emits a metric that was not declared or a non-finite value. Other scorer failures are recorded as failed scores.\n *\n * @param options - Case definition: headless options plus `id`, `scorers`, `metrics` and `workspace`.\n * @returns The case result. A run that did not complete resolves with `passed` set to `false`.\n *\n * @example\n * ~~~ts\n * import { fileExists, runEvalCase, statusCompleted } from 'zidane/eval'\n * import { anthropic } from 'zidane/providers/anthropic'\n *\n * const result = await runEvalCase({\n * id: 'creates-readme',\n * suite: 'files',\n * prompt: 'Create README.md with a one-line project description.',\n * provider: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }),\n * maxTurns: 8,\n * workspace: { capture: ['.'] },\n * scorers: [statusCompleted(), fileExists('README.md')],\n * })\n *\n * console.log(result.passed, result.score)\n * ~~~\n */\nexport async function runEvalCase(options: EvalCaseOptions): Promise<EvalCaseResult> {\n const {\n id,\n suite,\n variant,\n tags = [],\n artifactDir,\n workspace,\n scorers = [],\n onEvent,\n ...headless\n } = options\n\n const { metrics: declaredMetrics, sourceFile, ...headlessRest } = headless\n const events: HeadlessEvent[] = []\n // Variant-aware artifact layout: <dir>[/<variant>]/<suite>/<id> so the same\n // case run against two models never overwrites its own output.\n const caseArtifactDir = artifactDir\n ? join(artifactDir, ...(variant ? [safeSegment(variant)] : []), safeSegment(suite ?? 'eval'), safeSegment(id))\n : undefined\n const workspaceState = await prepareWorkspace(headlessRest.execution, workspace)\n const caseMetricIds = new Set(Object.keys(declaredMetrics ?? {}))\n const hasCaseMetrics = caseMetricIds.size > 0\n\n // Merge declared metrics with the always-on efficiency set.\n const metricSpecs: MetricSpecMap = { ...EFFICIENCY_METRICS, ...declaredMetrics }\n const rawMetrics = new Map<string, number>()\n const emitMetric: MetricEmitter = (metricId, raw) => {\n if (!(metricId in metricSpecs))\n throw new EvalMetricError(`Eval ${id}: metric \"${metricId}\" emitted but not declared in defineMetrics`)\n if (!Number.isFinite(raw))\n throw new EvalMetricError(`Eval ${id}: metric \"${metricId}\" emitted a non-finite value (${raw}); scores require finite numbers`)\n rawMetrics.set(metricId, raw)\n }\n\n try {\n const result = await runHeadless({\n ...headlessRest,\n ...(workspaceState.execution ? { execution: workspaceState.execution } : {}),\n onEvent(event) {\n events.push(event)\n onEvent?.(event)\n },\n })\n\n // Auto-emit efficiency metrics from the headless result.\n emitEfficiencyMetrics(emitMetric, result)\n\n const workspaceSnapshot = workspaceState.snapshot()\n const workspaceError = workspaceState.error()\n const scorerContext: EvalScorerContext = {\n id,\n ...(suite ? { suite } : {}),\n tags,\n result,\n events,\n metric: emitMetric,\n ...(workspaceSnapshot ? { workspace: workspaceSnapshot } : {}),\n ...(caseArtifactDir ? { artifactDir: caseArtifactDir } : {}),\n }\n const scores = await runScorers(scorerContext, scorers)\n\n const metrics = finalizeEvalMetrics(metricSpecs, rawMetrics)\n const tagScores = computeEvalTagScores(metrics)\n // Score is metric-driven when metrics are declared beyond efficiency;\n // otherwise it is the scorer aggregate. If the declared set somehow filters\n // to empty, use the scorer aggregate too (avoid a meaningless 0 score).\n const caseMetrics = metrics.filter(metric => caseMetricIds.has(metric.id))\n const score = hasCaseMetrics && caseMetrics.length > 0\n ? meanNormalized(caseMetrics)\n : aggregateScore(scores)\n\n const evalResult: EvalCaseResult = {\n id,\n ...(suite ? { suite } : {}),\n ...(variant ? { variant } : {}),\n tags,\n result,\n score,\n passed: result.status === 'completed' && scores.every(score => score.passed),\n scores,\n metrics,\n tagScores,\n trajectory: buildTrajectory(result.transcript),\n events,\n ...(sourceFile ? { sourceFile } : {}),\n ...(workspaceSnapshot ? { workspace: workspaceSnapshot } : {}),\n ...(workspaceError ? { workspaceError } : {}),\n }\n\n const artifacts = caseArtifactDir\n ? await writeEvalArtifacts(caseArtifactDir, evalResult)\n : undefined\n\n return {\n ...evalResult,\n ...(artifacts ? { artifacts } : {}),\n }\n }\n finally {\n await workspaceState.cleanup()\n }\n}\n\n/** Minimal subset of a test runner's API the eval harness needs. */\nexport interface EvalTestRunner {\n /** Registers one test. */\n it: (name: string, fn: () => Promise<void> | void) => void\n /** Registers a callback that runs once after every test. */\n afterAll: (fn: () => Promise<void> | void) => void\n}\n\n/** Options for {@link registerEvalTests}. */\nexport interface RegisterEvalTestsOptions {\n /** Eval cases to register, one test each. */\n cases: EvalCaseOptions[]\n /** Test runner API the tests are registered on, for example `{ it, afterAll }` from `bun:test`. */\n runner: EvalTestRunner\n /** Reporter that collects the results. A new one is created when omitted. */\n reporter?: EvalRunReporter\n /** Directory where per-case artifacts are written. Nothing is written when omitted. */\n artifactDir?: string\n /**\n * When true (default), each case asserts only that the agent run reached a\n * terminal `completed` status — scores are recorded but never fail the test.\n * Evals are scoring tools, not deterministic assertions.\n */\n failOnIncomplete?: boolean\n /** Print the aggregated run summary after all cases. Default true. */\n printSummary?: boolean\n /** Repeat each case N times (each repetition is its own test). Default 1. */\n repeat?: number\n /** Teardown run once after all cases (e.g. dispose a shared container). */\n dispose?: () => Promise<void> | void\n /**\n * Max eval cases to run concurrently. Each case keeps its own workspace dir,\n * so a shared container runs them in parallel safely. Default 1 (sequential).\n */\n concurrency?: number\n}\n\n/**\n * Register one test per eval case against a test runner, funnel every result\n * into a shared reporter, and print the aggregated summary once after all cases.\n *\n * A failing test means the agent run itself broke (provider/tool/timeout). Low\n * scores are reported, not asserted — see {@link RegisterEvalTestsOptions.failOnIncomplete}.\n *\n * @param options - Cases, test runner and optional reporter, artifact directory, repeat count and concurrency.\n * @returns The reporter that receives every case result.\n *\n * @example\n * ~~~ts\n * import { afterAll, it } from 'bun:test'\n * import { fileExists, registerEvalTests, statusCompleted } from 'zidane/eval'\n * import { anthropic } from 'zidane/providers/anthropic'\n *\n * registerEvalTests({\n * runner: { it, afterAll },\n * artifactDir: 'eval-artifacts',\n * cases: [{\n * id: 'creates-readme',\n * suite: 'files',\n * prompt: 'Create README.md with a one-line project description.',\n * provider: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }),\n * workspace: { capture: ['.'] },\n * scorers: [statusCompleted(), fileExists('README.md')],\n * }],\n * })\n * ~~~\n */\nexport function registerEvalTests(options: RegisterEvalTestsOptions): EvalRunReporter {\n const reporter = options.reporter ?? createEvalRunReporter()\n const failOnIncomplete = options.failOnIncomplete ?? true\n const printSummary = options.printSummary ?? true\n const repeat = Math.max(1, options.repeat ?? 1)\n const concurrency = Math.max(1, options.concurrency ?? 1)\n\n options.runner.afterAll(async () => {\n await reporter.flush()\n if (printSummary)\n console.log(`\\n${reporter.format()}\\n`)\n if (options.dispose)\n await options.dispose()\n })\n\n // Build the (case × repeat) work list. Each entry runs exactly once; the\n // matching `it` test awaits its already-scheduled promise so bun still shows\n // per-case pass/fail while the pool drives real parallelism.\n const work: Array<{ label: string, run: () => Promise<EvalCaseResult> }> = []\n for (const evalCase of options.cases) {\n const caseLabel = `${evalCase.suite ? `${evalCase.suite}/` : ''}${evalCase.id}`\n const baseLabel = evalCase.variant ? `[${evalCase.variant}] ${caseLabel}` : caseLabel\n for (let run = 1; run <= repeat; run++) {\n const label = repeat > 1 ? `${baseLabel} #${run}` : baseLabel\n const caseId = repeat > 1 ? `${evalCase.id}-repeat-${run}` : evalCase.id\n work.push({\n label,\n run: () => runEvalCase({\n ...evalCase,\n id: caseId,\n ...(options.artifactDir ? { artifactDir: options.artifactDir } : {}),\n }),\n })\n }\n }\n\n const schedule = createLazyPool(concurrency)\n\n work.forEach((w) => {\n options.runner.it(w.label, async () => {\n const result = await schedule(w.run)\n await reporter.record(result)\n if (failOnIncomplete && result.result.status !== 'completed') {\n throw new Error(`Eval ${w.label} did not complete: ${JSON.stringify(result.result.error ?? { status: result.result.status }, null, 2)}`)\n }\n })\n })\n\n return reporter\n}\n\n/**\n * Lazily run tasks with a bounded concurrency `limit`. Nothing starts until a\n * runner invokes the corresponding test callback, so filtered/skipped tests do\n * not leak model or Docker work in the background.\n */\nfunction createLazyPool(limit: number): <T>(task: () => Promise<T>) => Promise<T> {\n const queue: Array<() => void> = []\n let active = 0\n\n const drain = (): void => {\n const available = Math.min(limit - active, queue.length)\n for (let i = 0; i < available; i++)\n queue.shift()?.()\n }\n\n return <T>(task: () => Promise<T>) => new Promise<T>((resolve, reject) => {\n const run = async (): Promise<void> => {\n active++\n try {\n resolve(await task())\n }\n catch (err) {\n reject(err)\n }\n finally {\n active--\n drain()\n }\n }\n queue.push(() => void run())\n drain()\n })\n}\n\n/**\n * Creates a reporter that collects case results, builds the run summary and formats it as a terminal table.\n *\n * @param options - Output directory and color setting. All fields are optional.\n */\nexport function createEvalRunReporter(options: EvalRunReporterOptions = {}): EvalRunReporter {\n const results: EvalCaseResult[] = []\n\n return {\n get results() {\n return results\n },\n async record(result) {\n results.push(result)\n if (options.outputDir) {\n const segments = [\n ...(result.variant ? [safeSegment(result.variant)] : []),\n safeSegment(result.suite ?? 'eval'),\n safeSegment(result.id),\n ]\n const casePath = join(options.outputDir, 'cases', `${segments.join('--')}.json`)\n await mkdir(join(options.outputDir, 'cases'), { recursive: true })\n await writeFile(casePath, `${JSON.stringify(result, null, 2)}\\n`)\n }\n },\n async flush() {\n const summary = buildEvalRunSummary(results)\n if (options.outputDir) {\n await mkdir(options.outputDir, { recursive: true })\n await writeFile(join(options.outputDir, 'run-summary.json'), `${JSON.stringify(summary, null, 2)}\\n`)\n }\n return summary\n },\n format() {\n return formatEvalRunSummaryWithOptions(results, { color: options.color })\n },\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"eval-CIHIF_Ns.js","names":["shellQuote"],"sources":["../src/eval-artifacts.ts","../src/eval-metrics.ts","../src/eval-summary.ts","../src/eval-report.ts","../src/eval-scorers.ts","../src/eval-trajectory.ts","../src/eval-workspace.ts","../src/eval-execution.ts","../src/eval-agent.ts","../src/eval-judge.ts","../src/eval-registry.ts","../src/eval.ts"],"sourcesContent":["import type { EvalArtifacts, EvalCaseResult } from './eval-types'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { join, relative, resolve } from 'node:path'\nimport { headlessEventToJsonl } from './headless-format'\n\nexport async function writeEvalArtifacts(dir: string, result: EvalCaseResult): Promise<EvalArtifacts> {\n await mkdir(dir, { recursive: true })\n const resultPath = join(dir, 'result.json')\n const eventsPath = join(dir, 'events.jsonl')\n const transcriptPath = join(dir, 'transcript.json')\n const workspacePath = result.workspace ? join(dir, 'workspace.json') : undefined\n\n await writeFile(resultPath, `${JSON.stringify(result, null, 2)}\\n`)\n await writeFile(eventsPath, result.events.map(headlessEventToJsonl).join(''))\n await writeFile(transcriptPath, `${JSON.stringify(result.result.transcript, null, 2)}\\n`)\n if (workspacePath)\n await writeFile(workspacePath, `${JSON.stringify(result.workspace, null, 2)}\\n`)\n\n return {\n dir,\n result: resultPath,\n events: eventsPath,\n transcript: transcriptPath,\n ...(workspacePath ? { workspace: workspacePath } : {}),\n }\n}\n\nexport function safeSegment(value: string): string {\n const sanitized = value.replace(/[^\\w.-]+/g, '-').replace(/^-+|-+$/g, '')\n // If sanitizing changed the value, distinct ids can collapse to the same\n // segment (e.g. `a b`, `a/b`, `a@b` → `a-b`) and overwrite each other's\n // artifacts. Append a short, stable hash of the original to disambiguate.\n if (sanitized === value && sanitized.length > 0)\n return sanitized\n return `${sanitized || 'eval'}-${shortHash(value)}`\n}\n\nfunction shortHash(value: string): string {\n // Tiny FNV-1a; only used to disambiguate filesystem segments, not security.\n let hash = 0x811C9DC5\n for (let i = 0; i < value.length; i++) {\n hash ^= value.charCodeAt(i)\n hash = Math.imul(hash, 0x01000193)\n }\n return (hash >>> 0).toString(36).padStart(7, '0').slice(0, 7)\n}\n\n/**\n * Resolves the artifact directory of a case: `<root>/<suite>/<id>`. Characters that are unsafe in a path segment are replaced.\n *\n * @param root - Root artifact directory.\n * @param result - Case result that names the suite and id.\n */\nexport function artifactPath(root: string, result: EvalCaseResult): string {\n return resolve(root, safeSegment(result.suite ?? 'eval'), safeSegment(result.id))\n}\n\n/**\n * Returns `path` relative to `root`.\n *\n * @param root - Root artifact directory.\n * @param path - Path inside the artifact tree.\n */\nexport function relativeArtifactPath(root: string, path: string): string {\n return relative(root, path)\n}\n","import type { HeadlessResult } from './headless'\n\n/** Whether a larger raw value is better or worse. */\nexport type MetricDirection = 'higher-is-better' | 'lower-is-better'\n\n/** Declared metric: a raw signal plus how to normalize it to a `0..1` score. */\nexport interface MetricSpec {\n /** Lower bound of the raw range. Raw values below it are clamped. */\n min: number\n /** Upper bound of the raw range. Raw values above it are clamped. */\n max: number\n /** Whether higher or lower raw values score better. */\n direction: MetricDirection\n /** Grouping tags, e.g. `@efficiency`, `@functionality`, `@quality`. */\n tags?: string[]\n /** Human-readable description of the metric. */\n description?: string\n}\n\n/** Metric specs keyed by metric id. */\nexport type MetricSpecMap = Record<string, MetricSpec>\n\n/** A normalized metric value attached to one eval case. */\nexport interface EvalMetric {\n /** Metric id, the key in the {@link MetricSpecMap}. */\n id: string\n /** Raw value the run emitted. `0` when the metric is missing. */\n raw: number\n /** Score from `0` to `1`. `0` when the metric is missing. */\n normalized: number\n /** Whether higher or lower raw values score better. */\n direction: MetricDirection\n /** Lower bound of the raw range, from the spec. */\n min: number\n /** Upper bound of the raw range, from the spec. */\n max: number\n /** Grouping tags, from the spec. Empty when the spec has none. */\n tags: string[]\n /** Human-readable description, from the spec. */\n description?: string\n /**\n * True when the metric was declared but never emitted (e.g. its scorer threw\n * before calling `ctx.metric`). Recorded as `normalized: 0` so the run still\n * produces results instead of crashing.\n */\n missing?: boolean\n}\n\n/** Emit a raw metric value during a run. */\nexport type MetricEmitter = (id: string, raw: number) => void\n\n/**\n * Declare an eval's metric set. Returns the same map, typed; pass it to\n * `EvalCaseOptions.metrics`. Declared metrics that are not emitted are recorded\n * as missing with a normalized score of 0; emitting an undeclared metric is an\n * authoring error and throws.\n *\n * @param spec - Metric specs keyed by metric id.\n */\nexport function defineMetrics<T extends MetricSpecMap>(spec: T): T {\n return spec\n}\n\n/** Always-available efficiency metrics derived from `HeadlessResult`. */\nexport const EFFICIENCY_METRICS = {\n 'execution-time': { min: 0, max: 300_000, direction: 'lower-is-better', tags: ['@efficiency'], description: 'Wall-clock run time (ms).' },\n 'provider-tokens': { min: 0, max: 200_000, direction: 'lower-is-better', tags: ['@efficiency'], description: 'Input + output tokens.' },\n 'cache-read-rate': { min: 0, max: 1, direction: 'higher-is-better', tags: ['@efficiency'], description: 'Cache-read tokens / input tokens.' },\n} satisfies MetricSpecMap\n\n/**\n * Maps a raw value to a score from `0` to `1`, clamped to the spec's range and flipped for `'lower-is-better'`. Returns `1` when `min` equals `max`.\n *\n * @param raw - Raw metric value.\n * @param spec - Range and direction of the metric.\n */\nexport function normalizeMetric(raw: number, spec: MetricSpec): number {\n const span = spec.max - spec.min\n if (span === 0)\n return 1\n const clamped = Math.min(spec.max, Math.max(spec.min, raw))\n const normalized = (clamped - spec.min) / span\n return spec.direction === 'lower-is-better' ? 1 - normalized : normalized\n}\n\n/**\n * Thrown by `runEvalCase` when a scorer emits a metric id that was not declared\n * in `defineMetrics`. This is an authoring error (a typo'd or stale metric id),\n * not a low score — it fails the eval test rather than being recorded as a\n * failed scorer. Exported so downstream harnesses can type-narrow on it.\n */\nexport class EvalMetricError extends Error {\n /**\n * Creates the error.\n *\n * @param message - Error message.\n */\n constructor(message: string) {\n super(message)\n this.name = 'EvalMetricError'\n }\n}\n\n/**\n * Computes the raw values of the {@link EFFICIENCY_METRICS} for a run: wall-clock time, input plus output tokens, and the share of input read from cache.\n *\n * @param result - Result of the run.\n */\nexport function efficiencyMetricValues(result: HeadlessResult): Record<keyof typeof EFFICIENCY_METRICS, number> {\n const u = result.usage\n // Fraction of read-side input served from cache. cacheRead is reported on top\n // of `input`, so the denominator is cacheRead + input (not input alone).\n const readTotal = u.input + u.cacheRead\n return {\n 'execution-time': result.durationMs,\n 'provider-tokens': u.input + u.output,\n 'cache-read-rate': readTotal > 0 ? u.cacheRead / readTotal : 0,\n }\n}\n\n/**\n * Emits every efficiency metric for a run through `emit`.\n *\n * @param emit - Callback that receives each metric id and raw value.\n * @param result - Result of the run.\n */\nexport function emitEfficiencyMetrics(emit: MetricEmitter, result: HeadlessResult): void {\n const values = efficiencyMetricValues(result)\n for (const [id, raw] of Object.entries(values))\n emit(id, raw)\n}\n\n/**\n * Builds the normalized metrics of a case. A declared metric that was never emitted is recorded as missing with a score of `0`.\n *\n * @param specs - Declared metric specs.\n * @param raw - Raw values emitted during the run, keyed by metric id.\n */\nexport function finalizeEvalMetrics(\n specs: MetricSpecMap,\n raw: Map<string, number>,\n): EvalMetric[] {\n // A declared-but-unemitted metric (e.g. a judge that threw mid-run) records\n // as a missing 0 rather than crashing the whole case — evals score what they\n // can and surface the gap, they don't abort the run.\n return Object.entries(specs).map(([metricId, spec]) => {\n const emitted = raw.has(metricId)\n const value = emitted ? raw.get(metricId)! : spec.min\n return {\n id: metricId,\n raw: emitted ? value : 0,\n normalized: emitted ? normalizeMetric(value, spec) : 0,\n direction: spec.direction,\n min: spec.min,\n max: spec.max,\n tags: spec.tags ?? [],\n ...(spec.description ? { description: spec.description } : {}),\n ...(emitted ? {} : { missing: true }),\n }\n })\n}\n\n/**\n * Computes the mean normalized score for each tag across the given metrics.\n *\n * @param metrics - Metrics of one case.\n */\nexport function computeEvalTagScores(metrics: EvalMetric[]): Record<string, number> {\n const byTag = new Map<string, number[]>()\n for (const metric of metrics) {\n for (const tag of metric.tags) {\n const list = byTag.get(tag) ?? []\n list.push(metric.normalized)\n byTag.set(tag, list)\n }\n }\n const out: Record<string, number> = {}\n for (const [tag, values] of byTag)\n out[tag] = mean(values)\n return out\n}\n\nexport function meanNormalized(metrics: EvalMetric[]): number {\n return metrics.length === 0 ? 0 : mean(metrics.map(m => m.normalized))\n}\n\nexport function mean(values: number[]): number {\n return values.length === 0 ? 0 : values.reduce((a, b) => a + b, 0) / values.length\n}\n","import type { EvalMetric } from './eval-metrics'\nimport type { EvalCaseResult, EvalRunMetricAggregate, EvalRunSummary, EvalVariantSummary, MetricStats } from './eval-types'\nimport { mean } from './eval-metrics'\n\n/** Stable ordering by `variant`, then `suite/id`, so parallel completion order doesn't shuffle output. */\nexport function sortCases(results: readonly EvalCaseResult[]): EvalCaseResult[] {\n return [...results].sort((a, b) => {\n const va = a.variant ?? ''\n const vb = b.variant ?? ''\n if (va !== vb)\n return va.localeCompare(vb)\n const ka = `${a.suite ?? ''}/${a.id}`\n const kb = `${b.suite ?? ''}/${b.id}`\n return ka.localeCompare(kb)\n })\n}\n\n/** Distinct variant labels across results, in sorted order. */\nexport function distinctVariants(results: readonly EvalCaseResult[]): string[] {\n return [...new Set(results.map(r => r.variant).filter((v): v is string => Boolean(v)))].sort()\n}\n\n/**\n * Builds the summary of an eval run: case counts, mean score, duration and usage totals, one row per case, metric and tag aggregates, and per-variant summaries when cases have variants.\n *\n * @param input - Case results in any order. They are sorted by variant, then suite and id.\n */\nexport function buildEvalRunSummary(input: readonly EvalCaseResult[]): EvalRunSummary {\n const results = sortCases(input)\n const usage = results.reduce((acc, result) => {\n acc.input += result.result.usage.input\n acc.output += result.result.usage.output\n acc.cacheRead += result.result.usage.cacheRead\n acc.cacheCreation += result.result.usage.cacheCreation\n acc.cost += result.result.usage.cost ?? 0\n return acc\n }, { input: 0, output: 0, cacheRead: 0, cacheCreation: 0, cost: 0 })\n const totalScore = results.reduce((sum, result) => sum + result.score, 0)\n\n return {\n count: results.length,\n passed: results.filter(result => result.passed).length,\n score: results.length > 0 ? totalScore / results.length : 0,\n durationMs: results.reduce((sum, result) => sum + result.result.durationMs, 0),\n usage,\n cases: results.map(result => ({\n id: result.id,\n ...(result.suite ? { suite: result.suite } : {}),\n ...(result.variant ? { variant: result.variant } : {}),\n passed: result.passed,\n score: result.score,\n status: result.result.status,\n durationMs: result.result.durationMs,\n scores: result.scores,\n metrics: result.metrics,\n tagScores: result.tagScores,\n trajectory: result.trajectory,\n })),\n metrics: aggregateMetrics(results),\n tagScores: aggregateTagScores(results),\n ...(distinctVariants(results).length > 0 ? { variants: aggregateVariants(results) } : {}),\n }\n}\n\nexport function aggregateVariants(results: readonly EvalCaseResult[]): EvalVariantSummary[] {\n return distinctVariants(results).map((variant) => {\n const group = results.filter(r => r.variant === variant)\n const usage = group.reduce((acc, result) => {\n acc.input += result.result.usage.input\n acc.output += result.result.usage.output\n acc.cacheRead += result.result.usage.cacheRead\n acc.cacheCreation += result.result.usage.cacheCreation\n acc.cost += result.result.usage.cost ?? 0\n return acc\n }, { input: 0, output: 0, cacheRead: 0, cacheCreation: 0, cost: 0 })\n return {\n variant,\n count: group.length,\n passed: group.filter(r => r.passed).length,\n score: mean(group.map(r => r.score)),\n durationMs: group.reduce((sum, r) => sum + r.result.durationMs, 0),\n usage,\n turns: group.reduce((sum, r) => sum + r.result.turns, 0),\n toolCalls: group.reduce((sum, r) => sum + r.result.numToolCalls, 0),\n }\n })\n}\n\nfunction aggregateMetrics(results: readonly EvalCaseResult[]): EvalRunMetricAggregate[] {\n const byId = new Map<string, EvalMetric[]>()\n for (const result of results) {\n for (const metric of result.metrics) {\n const list = byId.get(metric.id) ?? []\n list.push(metric)\n byId.set(metric.id, list)\n }\n }\n return [...byId.entries()].map(([id, metrics]) => ({\n id,\n direction: metrics[0].direction,\n tags: metrics[0].tags,\n raw: metricStats(metrics.map(m => m.raw)),\n normalized: metricStats(metrics.map(m => m.normalized)),\n }))\n}\n\nfunction aggregateTagScores(results: readonly EvalCaseResult[]): Record<string, number> {\n const byTag = new Map<string, number[]>()\n for (const result of results) {\n for (const [tag, value] of Object.entries(result.tagScores)) {\n const list = byTag.get(tag) ?? []\n list.push(value)\n byTag.set(tag, list)\n }\n }\n const out: Record<string, number> = {}\n for (const [tag, values] of byTag)\n out[tag] = mean(values)\n return out\n}\n\nfunction metricStats(values: number[]): MetricStats {\n const sorted = [...values].sort((a, b) => a - b)\n return {\n mean: mean(values),\n min: sorted[0] ?? 0,\n max: sorted[sorted.length - 1] ?? 0,\n p50: percentile(sorted, 0.5),\n p90: percentile(sorted, 0.9),\n zeroCount: values.filter(v => v === 0).length,\n values,\n }\n}\n\nfunction percentile(sorted: number[], q: number): number {\n if (sorted.length === 0)\n return 0\n const idx = Math.min(sorted.length - 1, Math.max(0, Math.ceil(q * sorted.length) - 1))\n return sorted[idx]\n}\n","import type { EvalMetric } from './eval-metrics'\nimport type { Trajectory, TrajectoryStepKind } from './eval-trajectory'\nimport type { EvalCaseResult, EvalRunSummary, EvalScore, EvalVariantSummary } from './eval-types'\nimport { resolve } from 'node:path'\nimport chalk from 'chalk'\nimport { mean } from './eval-metrics'\nimport { aggregateVariants, buildEvalRunSummary, distinctVariants, sortCases } from './eval-summary'\n\n/**\n * Formats one case result as plain text: status, score, duration, usage, workspace and artifact info, and per-scorer results.\n *\n * @param result - Case result to format.\n */\nexport function formatEvalCaseSummary(result: EvalCaseResult): string {\n const lines = [\n `Eval ${result.suite ? `${result.suite}/` : ''}${result.id}`,\n ...(result.variant ? [`variant: ${result.variant}`] : []),\n `status: ${result.result.status}`,\n `passed: ${result.passed}`,\n `score: ${result.score.toFixed(2)}`,\n `duration: ${result.result.durationMs}ms`,\n `turns: ${result.result.turns}`,\n `tool calls: ${result.result.numToolCalls}`,\n `usage: input=${result.result.usage.input} output=${result.result.usage.output} cacheRead=${result.result.usage.cacheRead} cacheCreation=${result.result.usage.cacheCreation}${result.result.usage.cost !== undefined ? ` cost=$${result.result.usage.cost.toFixed(6)}` : ''}`,\n ]\n\n if (result.workspace) {\n lines.push(`workspace files: ${result.workspace.files.length}`)\n }\n if (result.workspaceError) {\n lines.push(`workspace error: ${result.workspaceError}`)\n }\n if (result.artifacts) {\n lines.push(`artifacts: ${result.artifacts.dir}`)\n }\n\n if (result.scores.length > 0) {\n lines.push('scores:')\n for (const score of result.scores) {\n const value = score.score !== undefined ? score.score.toFixed(2) : score.passed ? '1.00' : '0.00'\n lines.push(` - ${score.name}: ${value} ${score.passed ? 'pass' : 'fail'}`)\n if (typeof score.details === 'string' && score.details.length > 0)\n lines.push(` ${score.details}`)\n else if (isRecord(score.details) && typeof score.details.reasoning === 'string')\n lines.push(` ${score.details.reasoning}`)\n }\n }\n\n return lines.join('\\n')\n}\n\n/**\n * Formats an eval run as a terminal table, with a comparison matrix when the cases have more than one variant.\n *\n * @param results - Case results in any order.\n */\nexport function formatEvalRunSummary(results: readonly EvalCaseResult[]): string {\n return formatEvalRunSummaryWithOptions(results)\n}\n\nexport function formatEvalRunSummaryWithOptions(\n input: readonly EvalCaseResult[],\n options: { color?: boolean } = {},\n): string {\n const results = sortCases(input)\n const color = createEvalColors(options.color)\n if (results.length === 0)\n return `${color.heading('Eval run summary')}\\n${color.muted('no evals ran')}`\n\n const summary = buildEvalRunSummary(results)\n const out: string[] = []\n const variants = distinctVariants(results)\n\n out.push(color.heading('Eval run summary'))\n if (variants.length > 1) {\n // Multi-target run: lead with the cross-variant comparison matrix, then\n // one results table per variant so each target stays fully inspectable.\n out.push(renderComparisonTable(results, variants, color))\n for (const variant of variants) {\n const group = results.filter(r => r.variant === variant)\n out.push('')\n out.push(color.heading(variant))\n out.push(renderResultsTable(group, buildEvalRunSummary(group), color))\n }\n }\n else {\n out.push(renderResultsTable(results, summary, color))\n }\n\n const tagTable = renderTagTable(summary.tagScores, color)\n if (tagTable) {\n out.push('')\n out.push(tagTable)\n }\n out.push('')\n\n // Per-eval breakdown beneath the tables.\n const hyperlinks = options.color !== false\n const linkText = (target: string): string => {\n const abs = absPath(target)\n return hyperlinks ? oscLink(abs, abs) : abs\n }\n\n for (const result of results) {\n const caseLabel = `${result.suite ? `${result.suite}/` : ''}${result.id}`\n const label = result.variant ? `[${result.variant}] ${caseLabel}` : caseLabel\n out.push(`${color.dot(result.passed)} ${color.caseStatus(result.passed, label)}`)\n out.push(`${color.muted('score')} ${color.score(result.score)}`)\n\n const tagEntries = Object.entries(result.tagScores)\n if (tagEntries.length > 0)\n out.push(`${color.muted('tags:')} ${tagEntries.map(([tag, value]) => `${color.tag(tag)} ${color.score(value)}`).join(' ')}`)\n\n for (const metric of result.metrics) {\n const note = metric.missing ? color.fail(' (not emitted)') : color.muted(` (${formatMetricRaw(metric)})`)\n out.push(`${color.muted(padEnd(metric.id, 28))} ${color.score(metric.normalized)}${note}`)\n }\n\n for (const score of result.scores) {\n const detail = scoreDetailLine(score)\n if (!score.passed && detail)\n out.push(`${color.dot(score.passed)} ${color.muted(`${score.name}: ${truncate(detail, 140)}`)}`)\n }\n\n // Links — full absolute paths so they work in every terminal.\n if (result.sourceFile)\n out.push(`${color.muted('case:')} ${color.muted(linkText(result.sourceFile))}`)\n const resultTarget = caseLinkTarget(result)\n if (resultTarget)\n out.push(`${color.muted('result:')} ${color.muted(linkText(resultTarget))}`)\n\n // Turns last — can be very long.\n if (result.trajectory.steps.length > 0)\n out.push(`${color.muted(`turns: ${result.trajectory.totalBlocks}`)} ${formatTrajectoryColored(result.trajectory, color)}`)\n\n out.push('')\n }\n\n return out.join('\\n').replace(/\\n+$/, '')\n}\n\nfunction renderTagTable(tagScores: Record<string, number>, color: EvalColors): string | undefined {\n const entries = Object.entries(tagScores)\n if (entries.length === 0)\n return undefined\n const tagWidth = Math.max('TAG'.length, ...entries.map(([tag]) => tag.length))\n const top = `┌${'─'.repeat(tagWidth + 2)}┬${'─'.repeat(9)}┐`\n const mid = `├${'─'.repeat(tagWidth + 2)}┼${'─'.repeat(9)}┤`\n const bot = `└${'─'.repeat(tagWidth + 2)}┴${'─'.repeat(9)}┘`\n const lines = [\n top,\n `│ ${color.heading(padEnd('TAG', tagWidth))} │ ${color.heading('SCORE')} │`,\n mid,\n ...entries.map(([tag, value]) => `│ ${color.muted(padEnd(tag, tagWidth))} │ ${color.score(value)} │`),\n bot,\n ]\n return lines.join('\\n')\n}\n\nfunction formatMetricRaw(metric: EvalMetric): string {\n const raw = Number.isInteger(metric.raw) ? formatInt(metric.raw) : metric.raw.toFixed(3)\n const arrow = metric.direction === 'lower-is-better' ? '↓' : '↑'\n return `raw ${raw} ${arrow}`\n}\n\n/**\n * Resolve a filesystem target to link an eval case to. Prefers the written\n * artifact (`result.json` → its dir), so the link opens the case's output.\n * Returns `undefined` when no artifacts were written.\n */\nfunction caseLinkTarget(result: EvalCaseResult): string | undefined {\n return result.artifacts?.result ?? result.artifacts?.dir\n}\n\n/** Wrap text in an OSC 8 terminal hyperlink to a local path or URL. */\nfunction oscLink(target: string, text: string): string {\n const url = /^(?:file|https?):\\/\\//.test(target)\n ? target\n : `file://${resolve(target)}`\n const OSC = '\\u001B]8;;'\n const ST = '\\u001B\\\\'\n return `${OSC}${url}${ST}${text}${OSC}${ST}`\n}\n\n/** Absolute filesystem path (strips any `file://` prefix, resolves relatives). */\nfunction absPath(target: string): string {\n const clean = target.replace(/^file:\\/\\//, '')\n return resolve(clean)\n}\n\n/**\n * Case key used to line up the same eval across variants in the comparison\n * matrix. Strips the `-repeat-N` suffix `registerEvalTests` appends so a\n * repeated case aggregates into one row (mean score, x/y passed).\n */\nfunction comparisonCaseKey(result: EvalCaseResult): string {\n const id = result.id.replace(/-repeat-\\d+$/, '')\n return `${result.suite ? `${result.suite}/` : ''}${id}`\n}\n\n/**\n * Cross-variant comparison matrix: one row per eval case, one column per\n * variant (provider/model target), plus rollup rows (score / passed / cost /\n * time) so two models can be read side by side at a glance.\n */\nfunction renderComparisonTable(\n input: readonly EvalCaseResult[],\n variants: string[],\n color: EvalColors,\n): string {\n const results = sortCases(input)\n const caseKeys = [...new Set(results.map(comparisonCaseKey))].sort()\n const byCell = new Map<string, EvalCaseResult[]>()\n for (const result of results) {\n const key = `${comparisonCaseKey(result)}\\u0000${result.variant ?? ''}`\n const list = byCell.get(key) ?? []\n list.push(result)\n byCell.set(key, list)\n }\n\n interface Cell { text: string, score?: number, passed?: boolean }\n const cellFor = (caseKey: string, variant: string): Cell => {\n const group = byCell.get(`${caseKey}\\u0000${variant}`)\n if (!group || group.length === 0)\n return { text: '-' }\n const score = mean(group.map(r => r.score))\n const passedCount = group.filter(r => r.passed).length\n const allPassed = passedCount === group.length\n const status = group.length > 1\n ? `${passedCount}/${group.length}`\n : allPassed ? 'pass' : 'fail'\n return { text: `${score.toFixed(2)} ${status}`, score, passed: allPassed }\n }\n\n const variantSummaries = aggregateVariants(results)\n const summaryOf = (variant: string): EvalVariantSummary | undefined =>\n variantSummaries.find(s => s.variant === variant)\n\n /*\n * Two variants (e.g. `build` vs `codemode`): a Δ column reads the second\n * against the first, green when it is better, red when worse, so the\n * comparison doesn't need mental arithmetic.\n */\n const pair = variants.length === 2\n const header = ['EVAL', ...variants, ...(pair ? [`Δ ${variants[1]}`] : [])]\n\n const rows: Array<{ label: string, cells: Cell[], rollup?: boolean }> = caseKeys.map((key) => {\n const cells = variants.map(variant => cellFor(key, variant))\n if (pair)\n cells.push(deltaCell(cells[0]?.score, cells[1]?.score, 'higher', 'points'))\n return { label: key, cells }\n })\n\n interface Rollup {\n label: string\n value: (s: EvalVariantSummary) => number\n format: (value: number, s: EvalVariantSummary) => string\n better: 'higher' | 'lower'\n /** Score-like rows show an absolute difference; counts and amounts a relative one. */\n delta: 'points' | 'percent'\n /** Paint the value cells (score / pass status) like the per-case cells. */\n paint?: (s: EvalVariantSummary) => Pick<Cell, 'score' | 'passed'>\n }\n // Efficiency rows are summed per variant like COST / TIME: what a setup\n // (e.g. build vs codemode) or model costs in tokens and round-trips.\n const rollupDefs: Rollup[] = [\n { label: 'SCORE', value: s => s.score, format: v => v.toFixed(2), better: 'higher', delta: 'points', paint: s => ({ score: s.score }) },\n { label: 'PASSED', value: s => s.passed, format: (v, s) => `${v}/${s.count}`, better: 'higher', delta: 'points', paint: s => ({ passed: s.passed === s.count }) },\n { label: 'COST', value: s => s.usage.cost, format: v => formatCost(v), better: 'lower', delta: 'percent' },\n { label: 'TIME', value: s => s.durationMs, format: v => formatDuration(v), better: 'lower', delta: 'percent' },\n { label: 'TOKENS', value: s => s.usage.input + s.usage.output, format: v => formatInt(v), better: 'lower', delta: 'percent' },\n { label: 'CACHE R', value: s => s.usage.cacheRead, format: v => formatInt(v), better: 'lower', delta: 'percent' },\n { label: 'TURNS', value: s => s.turns, format: v => String(v), better: 'lower', delta: 'percent' },\n { label: 'TOOL CALLS', value: s => s.toolCalls, format: v => String(v), better: 'lower', delta: 'percent' },\n ]\n const rollups: Array<{ label: string, cells: Cell[], rollup: true }> = rollupDefs.map((def) => {\n const summaries = variants.map(summaryOf)\n const cells: Cell[] = summaries.map(s => s ? { text: def.format(def.value(s), s), ...def.paint?.(s) } : { text: '-' })\n if (pair) {\n const [a, b] = summaries\n cells.push(deltaCell(a ? def.value(a) : undefined, b ? def.value(b) : undefined, def.better, def.delta))\n }\n return { label: def.label, cells, rollup: true }\n })\n\n const allRows = [...rows, ...rollups]\n const widths = header.map((h, i) => Math.max(\n h.length,\n ...allRows.map(row => (i === 0 ? row.label : row.cells[i - 1].text).length),\n ))\n\n const top = `┌${widths.map(w => '─'.repeat(w + 2)).join('┬')}┐`\n const mid = `├${widths.map(w => '─'.repeat(w + 2)).join('┼')}┤`\n const bot = `└${widths.map(w => '─'.repeat(w + 2)).join('┴')}┘`\n\n const paintComparisonCell = (cell: Cell, padded: string): string => {\n if (cell.score === undefined && cell.passed === undefined)\n return color.muted(padded)\n // Re-render the score fragment colored; status colored by pass/fail.\n if (cell.score !== undefined) {\n const scoreText = cell.score.toFixed(2)\n const rest = cell.text.slice(scoreText.length)\n const coloredRest = cell.passed === undefined\n ? color.muted(rest)\n : cell.passed ? color.pass(rest) : color.fail(rest)\n return padded.replace(cell.text, `${color.score(cell.score)}${coloredRest}`)\n }\n return padded.replace(cell.text, cell.passed ? color.pass(cell.text) : color.fail(cell.text))\n }\n\n const renderRow = (row: { label: string, cells: Cell[], rollup?: boolean }): string => {\n const labelPadded = padEnd(row.label, widths[0])\n const labelPainted = row.rollup ? color.heading(labelPadded) : color.muted(labelPadded)\n const cellParts = row.cells.map((cell, i) => {\n const padded = padStart(cell.text, widths[i + 1])\n return ` ${paintComparisonCell(cell, padded)} `\n })\n return `│ ${labelPainted} │${cellParts.join('│')}│`\n }\n\n const lines = [\n top,\n `│ ${color.heading(padEnd(header[0], widths[0]))} │${header.slice(1).map((v, i) => ` ${color.heading(padStart(v, widths[i + 1]))} `).join('│')}│`,\n mid,\n ...rows.map(renderRow),\n mid,\n ...rollups.map(renderRow),\n bot,\n ]\n return lines.join('\\n')\n}\n\n/**\n * The Δ cell of a two-variant comparison: `b` against `a`, as an absolute\n * difference (`points`, for scores and counts of passes) or a relative one\n * (`percent`). Painted pass/fail by whether the change goes the `better` way;\n * unchanged values and missing sides stay muted.\n */\nfunction deltaCell(a: number | undefined, b: number | undefined, better: 'higher' | 'lower', kind: 'points' | 'percent'): { text: string, passed?: boolean } {\n if (a === undefined || b === undefined)\n return { text: '-' }\n const diff = b - a\n if (Math.abs(diff) < 1e-9)\n return { text: '=' }\n const sign = diff > 0 ? '+' : '−'\n const improved = better === 'higher' ? diff > 0 : diff < 0\n if (kind === 'points') {\n const magnitude = Math.abs(diff)\n return { text: `${sign}${Number.isInteger(magnitude) ? magnitude : magnitude.toFixed(2)}`, passed: improved }\n }\n if (a === 0)\n return { text: `${sign}∞`, passed: improved }\n return { text: `${sign}${Math.round(Math.abs(diff / a) * 100)}%`, passed: improved }\n}\n\nfunction renderResultsTable(\n results: readonly EvalCaseResult[],\n summary: EvalRunSummary,\n color: EvalColors,\n): string {\n const header = ['EVAL', 'STATUS', 'SCORE', 'IN', 'OUT', 'CACHE R', 'CACHE W', 'COST', 'TIME']\n const rows = results.map((result) => {\n const label = `${result.suite ? `${result.suite}/` : ''}${result.id}`\n const u = result.result.usage\n return {\n passed: result.passed,\n cells: [\n label,\n result.passed ? 'pass' : 'fail',\n result.score.toFixed(2),\n formatInt(u.input),\n formatInt(u.output),\n formatInt(u.cacheRead),\n formatInt(u.cacheCreation),\n formatCost(u.cost ?? 0),\n formatDuration(result.result.durationMs),\n ],\n score: result.score,\n }\n })\n\n const totals = {\n cells: [\n `TOTAL (${summary.passed}/${summary.count})`,\n summary.passed === summary.count ? 'pass' : 'fail',\n summary.score.toFixed(2),\n formatInt(summary.usage.input),\n formatInt(summary.usage.output),\n formatInt(summary.usage.cacheRead),\n formatInt(summary.usage.cacheCreation),\n formatCost(summary.usage.cost),\n formatDuration(summary.durationMs),\n ],\n passed: summary.passed === summary.count,\n score: summary.score,\n }\n\n // Right-align numeric columns (everything after STATUS).\n const aligns: Array<'left' | 'right'> = ['left', 'left', 'right', 'right', 'right', 'right', 'right', 'right', 'right']\n const widths = header.map((h, i) =>\n Math.max(h.length, ...rows.map(r => r.cells[i].length), totals.cells[i].length),\n )\n\n const top = `┌${widths.map(w => '─'.repeat(w + 2)).join('┬')}┐`\n const mid = `├${widths.map(w => '─'.repeat(w + 2)).join('┼')}┤`\n const bot = `└${widths.map(w => '─'.repeat(w + 2)).join('┴')}┘`\n\n const renderRow = (cells: string[], paint?: (i: number, raw: string, padded: string) => string): string => {\n const parts = cells.map((cell, i) => {\n const padded = aligns[i] === 'right' ? padStart(cell, widths[i]) : padEnd(cell, widths[i])\n return ` ${paint ? paint(i, cell, padded) : padded} `\n })\n return `│${parts.join('│')}│`\n }\n\n const lines = [\n top,\n renderRow(header, (_i, _raw, padded) => color.heading(padded)),\n mid,\n ...rows.map(r => renderRow(r.cells, (i, raw, padded) => paintCell(i, raw, padded, r.passed, r.score, color))),\n mid,\n renderRow(totals.cells, (i, raw, padded) => paintCell(i, raw, padded, totals.passed, totals.score, color, true)),\n bot,\n ]\n return lines.join('\\n')\n}\n\nfunction paintCell(\n col: number,\n raw: string,\n padded: string,\n passed: boolean,\n score: number,\n color: EvalColors,\n bold = false,\n): string {\n // EVAL\n if (col === 0)\n return bold ? color.heading(padded) : color.caseStatus(passed, padded)\n // STATUS\n if (col === 1)\n return padded.replace(raw, color.status(passed))\n // SCORE\n if (col === 2)\n return padded.replace(raw, color.score(score))\n // COST\n if (col === 7)\n return color.cost(padded)\n return color.muted(padded)\n}\n\nfunction scoreDetailLine(score: EvalScore): string | undefined {\n if (typeof score.details === 'string')\n return score.details\n if (isRecord(score.details) && typeof score.details.reasoning === 'string')\n return score.details.reasoning\n return undefined\n}\n\nfunction formatInt(value: number): string {\n return value.toLocaleString('en-US')\n}\n\nfunction formatCost(value: number): string {\n return value > 0 ? `$${value.toFixed(4)}` : '-'\n}\n\nfunction formatDuration(ms: number): string {\n const rounded = Math.round(ms)\n if (rounded < 1000)\n return `${rounded}ms`\n const s = rounded / 1000\n // Drop a trailing `.0` so `4.0s` reads as `4s`.\n return `${Number.isInteger(s) ? s : s.toFixed(1)}s`\n}\n\nfunction padEnd(value: string, width: number): string {\n return value.length >= width ? value : value + ' '.repeat(width - value.length)\n}\n\nfunction padStart(value: string, width: number): string {\n return value.length >= width ? value : ' '.repeat(width - value.length) + value\n}\n\nfunction truncate(value: string, max: number): string {\n const oneLine = value.replace(/\\s+/g, ' ').trim()\n return oneLine.length > max ? `${oneLine.slice(0, max - 1)}…` : oneLine\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null\n}\n\ninterface EvalColors {\n heading: (value: string) => string\n pass: (value: string) => string\n fail: (value: string) => string\n muted: (value: string) => string\n cost: (value: string) => string\n status: (passed: boolean) => string\n score: (value: number) => string\n caseStatus: (passed: boolean, value: string) => string\n dot: (passed: boolean) => string\n tag: (value: string) => string\n step: (kind: TrajectoryStepKind, value: string) => string\n}\n\nfunction createEvalColors(enabled = shouldUseColor()): EvalColors {\n if (!enabled) {\n return {\n heading: value => value,\n pass: value => value,\n fail: value => value,\n muted: value => value,\n cost: value => value,\n status: passed => passed ? 'pass' : 'fail',\n score: value => value.toFixed(2),\n caseStatus: (_passed, value) => value,\n dot: passed => passed ? '+' : 'x',\n tag: value => value,\n step: (_kind, value) => value,\n }\n }\n return {\n heading: value => chalk.bold(value),\n pass: value => chalk.green(value),\n fail: value => chalk.red(value),\n muted: value => chalk.gray(value),\n cost: value => chalk.cyan(value),\n status: passed => passed ? chalk.green('pass') : chalk.red('fail'),\n score: value => value >= 0.9 ? chalk.green(value.toFixed(2)) : value >= 0.7 ? chalk.yellow(value.toFixed(2)) : chalk.red(value.toFixed(2)),\n caseStatus: (passed, value) => passed ? chalk.green(value) : chalk.red(value),\n dot: passed => passed ? chalk.green('●') : chalk.red('●'),\n // Distinct from the step palette (which uses magenta/blue/cyan/yellow/green).\n tag: value => chalk.bold(chalk.whiteBright(value)),\n step: (kind, value) => paintStep(kind, value),\n }\n}\n\n/** Per-kind trajectory colors: think=magenta, text=blue, tools by family. */\nfunction paintStep(kind: TrajectoryStepKind, value: string): string {\n if (kind === 'think')\n return chalk.magenta(value)\n if (kind === 'text')\n return chalk.blue(value)\n // tool step — color by intent so a timeline reads at a glance.\n if (/write|edit|create/.test(value))\n return chalk.green(value)\n if (/read|list|glob|grep|search/.test(value))\n return chalk.cyan(value)\n if (/shell|bash|exec|run/.test(value))\n return chalk.yellow(value)\n if (/spawn|task|agent/.test(value))\n return chalk.magentaBright(value)\n return chalk.white(value)\n}\n\nfunction formatTrajectoryColored(trajectory: Trajectory, color: EvalColors): string {\n return trajectory.steps\n .map((step) => {\n const base = step.kind === 'tool' ? (step.name ?? 'tool') : step.kind\n const labelWithCount = step.count > 1 ? `${base} ×${step.count}` : base\n const painted = color.step(step.kind, labelWithCount)\n const timing = step.durationMs && step.durationMs >= 100 ? color.muted(`(${formatDuration(step.durationMs)})`) : ''\n return timing ? `${painted} ${timing}` : painted\n })\n .join(color.muted(' → '))\n}\n\nfunction shouldUseColor(): boolean {\n return Boolean(process.stdout.isTTY && !process.env.NO_COLOR)\n}\n","import type { EvalScore, EvalScorer, EvalScorerContext } from './eval-types'\nimport { EvalMetricError } from './eval-metrics'\n\n/**\n * Creates a scorer that passes when the run status is `'completed'`.\n *\n * @param name - Scorer name. Defaults to `'status.completed'`.\n */\nexport function statusCompleted(name = 'status.completed'): EvalScorer {\n return ({ result }) => ({\n name,\n passed: result.status === 'completed',\n score: result.status === 'completed' ? 1 : 0,\n details: result.status === 'completed' ? undefined : { status: result.status, error: result.error },\n })\n}\n\n/**\n * Creates a scorer that passes when the workspace snapshot contains `path`.\n *\n * @param path - Path relative to the workspace root.\n * @param name - Scorer name. Defaults to `file.exists:<path>`.\n */\nexport function fileExists(path: string, name = `file.exists:${path}`): EvalScorer {\n return ({ workspace }) => {\n const found = workspace?.files.some(file => file.path === path) ?? false\n return {\n name,\n passed: found,\n score: found ? 1 : 0,\n details: found ? undefined : `Missing ${path}`,\n }\n }\n}\n\n/**\n * Creates a scorer that passes when the workspace snapshot contains at least one of `paths`.\n *\n * @param paths - Paths relative to the workspace root.\n * @param name - Scorer name. Defaults to `file.existsOneOf:<paths joined by |>`.\n */\nexport function fileExistsOneOf(paths: string[], name = `file.existsOneOf:${paths.join('|')}`): EvalScorer {\n return ({ workspace }) => {\n const found = paths.find(path => workspace?.files.some(file => file.path === path))\n return {\n name,\n passed: Boolean(found),\n score: found ? 1 : 0,\n details: found ? undefined : `Missing one of: ${paths.join(', ')}`,\n }\n }\n}\n\n/**\n * Creates a scorer that passes when the captured content of `path` contains `expected`. A missing file fails.\n *\n * @param path - Path relative to the workspace root.\n * @param expected - Substring, or a pattern the content must match.\n * @param name - Scorer name. Defaults to `file.contains:<path>`.\n */\nexport function fileContains(path: string, expected: string | RegExp, name = `file.contains:${path}`): EvalScorer {\n return ({ workspace }) => {\n const file = workspace?.files.find(file => file.path === path)\n const content = file?.content ?? ''\n const passed = typeof expected === 'string' ? content.includes(expected) : expected.test(content)\n return {\n name,\n passed,\n score: passed ? 1 : 0,\n details: passed\n ? undefined\n : file\n ? `Expected ${path} to contain ${String(expected)}`\n : `Missing ${path}`,\n }\n }\n}\n\n/**\n * Creates a scorer that grades how closely a file matches `expected`: 1 for an exact match after trimming, 0.75 when the trimmed content contains `expected`, 0.5 when the raw content does, otherwise 0. It passes at 0.75 or more.\n *\n * @param path - Path relative to the workspace root.\n * @param expected - Text the file should match.\n * @param name - Scorer name. Defaults to `file.quality:<path>`.\n */\nexport function fileContentQuality(\n path: string,\n expected: string,\n name = `file.quality:${path}`,\n): EvalScorer {\n return ({ workspace }) => {\n const file = workspace?.files.find(file => file.path === path)\n const content = file?.content\n if (content === undefined) {\n return {\n name,\n passed: false,\n score: 0,\n details: `Missing ${path}`,\n }\n }\n\n const normalized = content.trim()\n const expectedNormalized = expected.trim()\n const score = normalized === expectedNormalized\n ? 1\n : normalized.includes(expectedNormalized)\n ? 0.75\n : content.includes(expected)\n ? 0.5\n : 0\n\n return {\n name,\n passed: score >= 0.75,\n score,\n details: score >= 0.75 ? undefined : `Expected ${path} to closely match ${JSON.stringify(expectedNormalized)}`,\n }\n }\n}\n\n/**\n * Aggregate a group of boolean scorers into a single `0..1` functionality\n * metric (fraction passed) and emit it. Useful for \"N of M files present\".\n *\n * @param metricId - Declared metric id that receives the fraction.\n * @param scorers - Boolean scorers to run and count.\n * @param name - Scorer name. Defaults to `metricId`.\n */\nexport function functionalityMetric(metricId: string, scorers: EvalScorer[], name = metricId): EvalScorer {\n return async (ctx) => {\n const results = await runScorers(ctx, scorers)\n const passed = results.filter(r => r.passed).length\n const fraction = results.length === 0 ? 1 : passed / results.length\n ctx.metric(metricId, fraction)\n return {\n name,\n passed: passed === results.length,\n score: fraction,\n details: { passed, total: results.length, checks: results.map(r => ({ name: r.name, passed: r.passed })) },\n }\n }\n}\n\nexport async function runScorers(ctx: EvalScorerContext, scorers: EvalScorer[]): Promise<EvalScore[]> {\n const scores: EvalScore[] = []\n for (const scorer of scorers) {\n try {\n scores.push(await scorer(ctx))\n }\n catch (err) {\n if (err instanceof EvalMetricError)\n throw err\n scores.push({\n name: scorer.name || 'anonymous-scorer',\n passed: false,\n score: 0,\n details: err instanceof Error ? err.message : String(err),\n })\n }\n }\n return scores\n}\n\nexport function aggregateScore(scores: EvalScore[]): number {\n if (scores.length === 0)\n return 1\n const total = scores.reduce((sum, score) => sum + (score.score ?? (score.passed ? 1 : 0)), 0)\n return total / scores.length\n}\n","import type { SessionTurn } from './types'\n\n// ---------------------------------------------------------------------------\n// Trajectory\n// ---------------------------------------------------------------------------\n\n/** Kind of a trajectory step: thinking, text output, or a tool call. */\nexport type TrajectoryStepKind = 'think' | 'text' | 'tool'\n\n/**\n * One grouped step in an eval trajectory. Consecutive blocks of the same kind\n * (and, for tools, the same tool name) collapse into a single step with a\n * `count`. A different kind interrupting the run breaks the group.\n *\n * Serializable by design so trajectories round-trip to disk and can be diffed\n * or replayed by other tooling.\n */\nexport interface TrajectoryStep {\n /** What the grouped blocks are. */\n kind: TrajectoryStepKind\n /** Tool name for `kind: 'tool'` steps (canonical, e.g. `read_file`). */\n name?: string\n /** Number of consecutive occurrences grouped into this step. */\n count: number\n /** Approx wall-clock ms attributed to this step's turns, when derivable. */\n durationMs?: number\n}\n\n/** Ordered, grouped view of what an agent did during an eval run. */\nexport interface Trajectory {\n /** Grouped steps in the order they happened. */\n steps: TrajectoryStep[]\n /** Total blocks across all steps (sum of `count`). */\n totalBlocks: number\n}\n\n/**\n * Build an ordered, grouped trajectory from a transcript. Walks assistant\n * turns in order, emitting `think` / `text` / `tool:<name>` steps, grouping\n * only consecutive identical kinds. Per-step duration is approximated from the\n * owning turn's `createdAt` delta to the next turn.\n *\n * @param transcript - Session turns of the run. Only assistant turns contribute steps.\n */\nexport function buildTrajectory(transcript: SessionTurn[]): Trajectory {\n const steps: TrajectoryStep[] = []\n let total = 0\n\n const push = (kind: TrajectoryStepKind, name: string | undefined, durationMs: number): void => {\n total++\n const last = steps[steps.length - 1]\n if (last && last.kind === kind && last.name === name) {\n last.count++\n if (durationMs > 0)\n last.durationMs = (last.durationMs ?? 0) + durationMs\n return\n }\n steps.push({ kind, ...(name ? { name } : {}), count: 1, ...(durationMs > 0 ? { durationMs } : {}) })\n }\n\n for (let i = 0; i < transcript.length; i++) {\n const turn = transcript[i]\n if (turn.role !== 'assistant')\n continue\n const next = transcript[i + 1]\n const turnDuration = next ? Math.max(0, next.createdAt - turn.createdAt) : 0\n const blocks = turn.content.filter(b => b.type === 'thinking' || b.type === 'redacted_thinking' || b.type === 'text' || b.type === 'tool_call')\n // Attribute the turn's elapsed time to its tool calls — that's where the\n // wall-clock actually goes (provider stream + tool execution). think/text\n // blocks within the turn carry no separate timing. Split evenly across the\n // turn's tool calls and round to whole ms so the timeline reads cleanly.\n const toolBlocks = blocks.filter(b => b.type === 'tool_call').length\n const perTool = toolBlocks > 0 ? Math.round(turnDuration / toolBlocks) : 0\n for (const block of blocks) {\n if (block.type === 'thinking' || block.type === 'redacted_thinking')\n push('think', undefined, 0)\n else if (block.type === 'text')\n push('text', undefined, 0)\n else if (block.type === 'tool_call')\n push('tool', block.name, perTool)\n }\n }\n\n return { steps, totalBlocks: total }\n}\n\n/**\n * Render a trajectory as a one-line timeline string (no color).\n *\n * @param trajectory - Trajectory to render.\n */\nexport function formatTrajectoryLine(trajectory: Trajectory): string {\n return trajectory.steps.map(stepLabel).join(' → ')\n}\n\nfunction stepLabel(step: TrajectoryStep): string {\n const base = step.kind === 'tool' ? (step.name ?? 'tool') : step.kind\n return step.count > 1 ? `${base} ×${step.count}` : base\n}\n","import type { ExecutionContext, ExecutionHandle } from './contexts'\nimport type { EvalWorkspaceFile, EvalWorkspaceOptions, EvalWorkspaceSnapshot } from './eval-types'\nimport { mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { createProcessContext } from './contexts'\nimport { alwaysQuote as shellQuote } from './tools/shell-quote'\n\ninterface WorkspaceState {\n execution?: ExecutionContext\n snapshot: () => EvalWorkspaceSnapshot | undefined\n error: () => string | undefined\n cleanup: () => Promise<void>\n}\n\nexport async function prepareWorkspace(\n execution: ExecutionContext | undefined,\n workspace: EvalWorkspaceOptions | undefined,\n): Promise<WorkspaceState> {\n if (!workspace) {\n return {\n snapshot: () => undefined,\n error: () => undefined,\n cleanup: async () => {},\n }\n }\n\n let tempDir: string | undefined\n let baseExecution = execution\n if (!baseExecution) {\n const cwd = workspace.cwd ?? await mkdtemp(join(tmpdir(), 'zidane-eval-'))\n if (!workspace.cwd)\n tempDir = cwd\n baseExecution = createProcessContext({ cwd })\n }\n\n const captured: { snapshot?: EvalWorkspaceSnapshot, error?: string } = {}\n const wrapped = withWorkspaceLifecycle(baseExecution, workspace, captured)\n\n return {\n execution: wrapped,\n snapshot: () => captured.snapshot,\n error: () => captured.error,\n cleanup: async () => {\n if (tempDir && !workspace.retain)\n await rm(tempDir, { recursive: true, force: true })\n },\n }\n}\n\nfunction withWorkspaceLifecycle(\n execution: ExecutionContext,\n workspace: EvalWorkspaceOptions,\n captured: { snapshot?: EvalWorkspaceSnapshot, error?: string },\n): ExecutionContext {\n return {\n ...execution,\n async spawn(config) {\n const handle = await execution.spawn({\n ...config,\n ...(workspace.cwd && !config?.cwd ? { cwd: workspace.cwd } : {}),\n })\n if (workspace.seedDir)\n await seedWorkspace(execution, handle, workspace)\n return handle\n },\n async destroy(handle) {\n try {\n captured.snapshot = await captureWorkspace(execution, handle, workspace)\n }\n catch (err) {\n captured.error = err instanceof Error ? err.message : String(err)\n }\n finally {\n await execution.destroy(handle)\n }\n },\n }\n}\n\nasync function seedWorkspace(\n execution: ExecutionContext,\n handle: ExecutionHandle,\n workspace: EvalWorkspaceOptions,\n): Promise<void> {\n const target = workspace.seedTarget ?? '.'\n const result = await execution.exec(\n handle,\n `mkdir -p ${shellQuote(target)} && cp -R ${shellQuote(`${workspace.seedDir!}/.`)} ${shellQuote(target)}`,\n )\n if (result.exitCode !== 0)\n throw new Error(`Failed to seed eval workspace: ${result.stderr || result.stdout}`)\n}\n\nasync function captureWorkspace(\n execution: ExecutionContext,\n handle: ExecutionHandle,\n workspace: EvalWorkspaceOptions,\n): Promise<EvalWorkspaceSnapshot> {\n const capturePaths = workspace.capture?.length ? workspace.capture : ['.']\n // `-print0` (NUL-delimited) so filenames containing newlines or spaces don't\n // corrupt the listing. Dedup in JS rather than `sort -u`, which has no\n // portable NUL-record mode across GNU (`-z`) and BSD `sort`.\n const command = [\n `cd ${shellQuote(handle.cwd)}`,\n '&&',\n 'for p in',\n capturePaths.map(shellQuote).join(' '),\n '; do',\n 'if [ -e \"$p\" ]; then',\n 'find \"$p\" \\\\( -path \"*/node_modules/*\" -o -path \"*/.git/*\" \\\\) -prune -o -type f -print0',\n '; fi',\n 'done',\n ].join(' ')\n\n const listed = await execution.exec(handle, command)\n if (listed.exitCode !== 0)\n throw new Error(`Failed to list eval workspace: ${listed.stderr || listed.stdout}`)\n\n const maxFileChars = workspace.maxFileChars ?? 256 * 1024\n const files: EvalWorkspaceFile[] = []\n const seen = new Set<string>()\n for (const rawPath of listed.stdout.split('\\0').filter(Boolean)) {\n const path = normalizeSnapshotPath(rawPath)\n if (seen.has(path))\n continue\n seen.add(path)\n const content = await execution.readFile(handle, path)\n const binary = content.includes('\\0')\n const truncated = content.length > maxFileChars\n files.push({\n path,\n size: content.length,\n ...(binary ? { binary: true } : { content: truncated ? content.slice(0, maxFileChars) : content }),\n ...(truncated ? { truncated: true } : {}),\n })\n }\n\n return { cwd: handle.cwd, files }\n}\n\nfunction normalizeSnapshotPath(path: string): string {\n const normalized = path.startsWith('./') ? path.slice(2) : path\n return normalized === '' ? '.' : normalized\n}\n","import type { ExecutionContext, ExecutionHandle } from './contexts'\n\n/** Execution context that shares one handle across runs, plus the hooks to inspect and dispose it. Created by {@link createReusableExecutionContext}. */\nexport interface ReusableExecutionContext {\n /**\n * Execution context facade that reuses one underlying handle. Its\n * `destroy()` is intentionally a no-op; call `dispose()` when the surrounding\n * fixture/run owns teardown.\n */\n execution: ExecutionContext\n /** Destroy the underlying handle if it was spawned. Idempotent. */\n dispose: () => Promise<void>\n /** Current underlying handle, if the agent has spawned one. */\n handle: () => ExecutionHandle | undefined\n}\n\n/**\n * Wrap an execution context so repeated agent runs share one handle until the\n * caller disposes it. This is useful for eval fixtures that want per-test\n * Docker/process lifetime while still using `runHeadless()` per turn.\n *\n * @param base - Execution context to wrap.\n */\nexport function createReusableExecutionContext(base: ExecutionContext): ReusableExecutionContext {\n let handle: ExecutionHandle | undefined\n let spawnPromise: Promise<ExecutionHandle> | undefined\n let disposed = false\n let disposePromise: Promise<void> | undefined\n\n const ensureHandle = (config?: Parameters<ExecutionContext['spawn']>[0]): Promise<ExecutionHandle> => {\n if (disposed)\n throw new Error('Reusable execution context has been disposed')\n if (handle)\n return Promise.resolve(handle)\n spawnPromise ??= base.spawn(config).then((next) => {\n handle = next\n return next\n }, (err) => {\n spawnPromise = undefined\n throw err\n })\n return spawnPromise\n }\n\n const execution: ExecutionContext = {\n ...base,\n async spawn(config) {\n return ensureHandle(config)\n },\n async destroy() {\n // Agent-level destroy means \"end this turn\"; the eval fixture owns the\n // actual execution lifetime and calls dispose() at test teardown.\n },\n }\n\n return {\n execution,\n // Memoize so concurrent dispose()/asyncDispose() calls share one teardown\n // and never run base.destroy twice or orphan an in-flight spawn.\n dispose() {\n disposePromise ??= (async () => {\n disposed = true\n const active = handle ?? await spawnPromise?.catch(() => undefined)\n handle = undefined\n spawnPromise = undefined\n if (active)\n await base.destroy(active)\n })()\n return disposePromise\n },\n handle: () => handle,\n }\n}\n","import type { ExecutionContext } from './contexts'\nimport type { EvalRunUsage } from './eval-types'\nimport type { HeadlessEvent, HeadlessOptions, HeadlessResult } from './headless'\nimport type { Provider } from './providers'\nimport type { Session, SessionStore } from './session'\nimport type { McpServerConfig, SessionTurn } from './types'\nimport { createProcessContext } from './contexts'\nimport { createReusableExecutionContext } from './eval-execution'\nimport { runHeadless } from './headless'\nimport { createMemoryStore, createSession } from './session'\n\n/** Usage and counters of one {@link EvalAgent} run. */\nexport interface EvalAgentRunStats extends EvalRunUsage {\n /** Wall-clock duration of the run in milliseconds. */\n durationMs: number\n /** Number of turns of the run. */\n turns: number\n /** Number of tool calls in the run's transcript. */\n toolCalls: number\n}\n\n/** Totals across every run of an {@link EvalAgent}. */\nexport interface EvalAgentStats extends EvalRunUsage {\n /** Number of completed `run()` calls. */\n runs: number\n /** Sum of per-run agent turns. */\n turns: number\n /** Sum of per-run tool calls. */\n toolCalls: number\n /** Sum of per-run wall-clock durations. */\n durationMs: number\n}\n\n/** Result of one {@link EvalAgent} run. */\nexport interface EvalAgentRunResult {\n /** Full headless result. Its transcript is scoped to this run. */\n result: HeadlessResult\n /** Per-run usage and trajectory counters. */\n stats: EvalAgentRunStats\n /** Transcript turns added by this run (same view as `result.transcript`). */\n newTranscript: SessionTurn[]\n}\n\n/** MCP servers for an {@link EvalAgent}: a fixed list, or a function that returns the list before each run. */\nexport type EvalAgentMcpServers\n = | readonly McpServerConfig[]\n | (() => readonly McpServerConfig[] | Promise<readonly McpServerConfig[]>)\n\n/** Options for {@link createEvalAgent}. The {@link HeadlessOptions} fields set here are the defaults for every run. */\nexport interface CreateEvalAgentOptions extends Omit<HeadlessOptions, 'prompt' | 'provider' | 'execution' | 'cwd' | 'session' | 'store' | 'mcpServers' | 'onEvent' | 'signal'> {\n /** Provider that drives the agent. */\n provider: Provider\n /**\n * Working directory for the default process context. Ignored when\n * `execution` is supplied.\n */\n cwd?: string\n /**\n * Execution context for agent tools. Wrapped with\n * `createReusableExecutionContext` so runs share one handle until `dispose`.\n */\n execution?: ExecutionContext\n /** Session to reuse across runs. When omitted, one in-memory session is created. */\n session?: Session\n /** Store used for the auto-created session. Defaults to an in-memory store. */\n store?: SessionStore\n /** Static or lazily resolved MCP servers. Resolved fresh before each run. */\n mcpServers?: EvalAgentMcpServers\n /** Live event callback for every run. */\n onEvent?: (event: HeadlessEvent) => void\n}\n\n/** Options for one {@link EvalAgent.run} call. Overrides the defaults set in {@link createEvalAgent}; `mcpServers` are added to the agent's own. */\nexport interface EvalAgentRunOptions extends Omit<HeadlessOptions, 'provider' | 'execution' | 'cwd' | 'session' | 'store'> {\n prompt: HeadlessOptions['prompt']\n}\n\n/** Multi-turn agent for evals. Every run shares one session and one execution handle. */\nexport interface EvalAgent {\n /** Runs one prompt in the shared session. Throws when a run is already in progress or the agent is disposed. */\n run: (options: EvalAgentRunOptions) => Promise<EvalAgentRunResult>\n /** Totals across the runs so far. */\n readonly stats: EvalAgentStats\n /** Returns the shared session, creating it on the first call. Throws after `dispose`. */\n session: () => Promise<Session>\n /** Destroys the shared execution handle. Safe to call more than once. */\n dispose: () => Promise<void>\n /** Same as `dispose`, for `await using`. */\n [Symbol.asyncDispose]: () => Promise<void>\n}\n\n/**\n * Multi-turn eval agent over the low-level headless runner. It keeps session\n * and execution lifetime outside any Playwright-specific fixture layer,\n * so downstream platforms can wrap it with their own `agent.run(...)` shape.\n *\n * @param options - Provider plus {@link HeadlessOptions} defaults for every run. `cwd`, `execution`, `session` and `store` set up the shared environment.\n *\n * @example\n * ~~~ts\n * import { createEvalAgent } from 'zidane/eval'\n * import { anthropic } from 'zidane/providers/anthropic'\n *\n * const agent = createEvalAgent({\n * provider: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }),\n * maxTurns: 8,\n * })\n *\n * await agent.run({ prompt: 'Create hello.txt containing \"hi\".' })\n * const second = await agent.run({ prompt: 'Append \" there\" to hello.txt.' })\n *\n * console.log(second.stats.turns, agent.stats.runs)\n * await agent.dispose()\n * ~~~\n */\nexport function createEvalAgent(options: CreateEvalAgentOptions): EvalAgent {\n const {\n cwd,\n execution,\n session: initialSession,\n store: initialStore,\n mcpServers: baseMcpServers,\n onEvent: baseOnEvent,\n ...headlessDefaults\n } = options\n const executionOwner = createReusableExecutionContext(execution ?? createProcessContext({ cwd }))\n const store = initialStore ?? createMemoryStore()\n let sessionPromise: Promise<Session> | undefined = initialSession ? Promise.resolve(initialSession) : undefined\n let disposed = false\n let runInFlight = false\n let disposePromise: Promise<void> | undefined\n\n const stats: EvalAgentStats = {\n runs: 0,\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheCreation: 0,\n cost: 0,\n turns: 0,\n toolCalls: 0,\n durationMs: 0,\n }\n\n async function getSession(): Promise<Session> {\n if (disposed)\n throw new Error('Eval agent has been disposed')\n sessionPromise ??= createSession({ store })\n return sessionPromise\n }\n\n async function resolveMcpServers(\n runServers: HeadlessOptions['mcpServers'] | undefined,\n ): Promise<McpServerConfig[] | undefined> {\n const base = typeof baseMcpServers === 'function'\n ? await baseMcpServers()\n : baseMcpServers\n const merged = [\n ...(base ?? []),\n ...(runServers ?? []),\n ]\n return merged.length > 0 ? [...merged] : undefined\n }\n\n async function run(runOptions: EvalAgentRunOptions): Promise<EvalAgentRunResult> {\n if (runInFlight)\n throw new Error('Eval agent already has a run in progress')\n runInFlight = true\n try {\n const session = await getSession()\n const { mcpServers: runMcpServers, onEvent: runOnEvent, ...restRunOptions } = runOptions\n const mcpServers = await resolveMcpServers(runMcpServers)\n\n const result = await runHeadless({\n ...headlessDefaults,\n ...restRunOptions,\n session,\n execution: executionOwner.execution,\n ...(mcpServers ? { mcpServers } : {}),\n onEvent(event) {\n baseOnEvent?.(event)\n runOnEvent?.(event)\n },\n })\n\n // `result.transcript` is already scoped to this run (runHeadless slices\n // from the resumed session's prior length), so it IS the new turns.\n const newTranscript = result.transcript.slice()\n const runStats: EvalAgentRunStats = {\n input: result.usage.input,\n output: result.usage.output,\n cacheRead: result.usage.cacheRead,\n cacheCreation: result.usage.cacheCreation,\n cost: result.usage.cost ?? 0,\n durationMs: result.durationMs,\n turns: result.turns,\n toolCalls: countToolCallsInTurns(newTranscript),\n }\n accumulateEvalAgentStats(stats, runStats)\n\n return { result, stats: runStats, newTranscript }\n }\n finally {\n runInFlight = false\n }\n }\n\n function dispose(): Promise<void> {\n // Memoize: concurrent dispose()/asyncDispose() share one teardown.\n disposePromise ??= (async () => {\n disposed = true\n await executionOwner.dispose()\n })()\n return disposePromise\n }\n\n return {\n run,\n stats,\n session: getSession,\n dispose,\n [Symbol.asyncDispose]: dispose,\n }\n}\n\nfunction accumulateEvalAgentStats(acc: EvalAgentStats, turn: EvalAgentRunStats): void {\n acc.runs += 1\n acc.input += turn.input\n acc.output += turn.output\n acc.cacheRead += turn.cacheRead\n acc.cacheCreation += turn.cacheCreation\n acc.cost += turn.cost\n acc.turns += turn.turns\n acc.toolCalls += turn.toolCalls\n acc.durationMs += turn.durationMs\n}\n\nfunction countToolCallsInTurns(turns: readonly SessionTurn[]): number {\n let count = 0\n for (const turn of turns) {\n if (turn.role !== 'assistant')\n continue\n count += turn.content.filter(block => block.type === 'tool_call').length\n }\n return count\n}\n","import type { EvalScorer, EvalScorerContext } from './eval-types'\nimport type { Provider, ToolCall, ToolSpec } from './providers'\n\n/** Options for {@link llmJudge}. */\nexport interface LlmJudgeOptions {\n /** Scorer name. Defaults to `'llm.judge'`. */\n name?: string\n /** Provider that runs the judge model. */\n provider: Provider\n /** Judge model id. Defaults to the provider's default model. */\n model?: string\n /** System prompt for the judge. Defaults to a strict grading prompt. */\n system?: string\n /** Rubric the output is graded against. */\n rubric: string\n /**\n * Output budget for the grade call. Default {@link DEFAULT_JUDGE_MAX_TOKENS}.\n * A judge that runs out mid-`submit_grade` loses the whole call (providers\n * drop an unfinished tool call), so it is retried once with twice the budget.\n */\n maxTokens?: number\n /** Wall-clock cap for the judge provider call. Defaults to 60s. */\n timeoutMs?: number\n /** Select what the judge sees. Defaults to final text plus captured workspace files. */\n input?: (ctx: EvalScorerContext) => string\n /** Declared metric id to emit the judge's `0..1` score into. */\n metric?: string\n}\n\n/**\n * Room for the reasoning on a real app: at 600 the judge of a multi-file\n * workspace ran out mid-`submit_grade` and the case scored `0` (\"no parseable\n * score\") while the shorter evals graded fine.\n */\nexport const DEFAULT_JUDGE_MAX_TOKENS = 4000\n\nconst UNPARSEABLE_REASONING = 'Judge did not return a parseable score.'\n\nconst DEFAULT_JUDGE_SYSTEM = [\n 'You are a strict software eval judge.',\n 'Grade only the supplied output against the rubric.',\n 'Call the `submit_grade` tool with your score and reasoning.',\n 'The score must be between 0 and 1.',\n].join('\\n')\n\n/** Forced-output tool the judge must call — the schema-enforcement path. */\nconst JUDGE_TOOL: ToolSpec = {\n name: 'submit_grade',\n description: 'Submit the grade for the output under evaluation.',\n inputSchema: {\n type: 'object',\n properties: {\n score: { type: 'number', minimum: 0, maximum: 1, description: 'Quality score from 0 (worst) to 1 (best).' },\n reasoning: { type: 'string', description: 'Brief justification for the score.' },\n feedback: { type: 'string', description: 'Optional actionable feedback.' },\n },\n required: ['score', 'reasoning'],\n additionalProperties: false,\n },\n}\n\n/**\n * Creates a scorer that asks a model to grade the run against a rubric. The judge answers through a forced `submit_grade` tool call with a score from 0 to 1 and a short reasoning. The scorer passes at a score of 0.7 or more.\n *\n * @param options - Judge provider, rubric and optional model, prompt and limits.\n */\nexport function llmJudge(options: LlmJudgeOptions): EvalScorer {\n const name = options.name ?? 'llm.judge'\n const model = options.model ?? options.provider.meta.defaultModel\n return async (ctx) => {\n const userMessage = options.provider.userMessage(renderJudgePrompt({\n rubric: options.rubric,\n input: options.input?.(ctx) ?? defaultJudgeInput(ctx),\n }))\n\n // Primary: forced structured output via a single tool call. This is the\n // same enforcement the agent loop uses for `schema`, and it works on any\n // tool-calling provider (Anthropic, OpenAI, Cerebras, OpenRouter, ...).\n let text = ''\n const controller = new AbortController()\n const timeoutMs = options.timeoutMs ?? 60_000\n let timedOut = false\n const timer = timeoutMs > 0\n ? setTimeout(() => {\n timedOut = true\n controller.abort(new Error(`LLM judge timed out after ${timeoutMs}ms`))\n }, timeoutMs)\n : undefined\n\n const timeoutPromise = timeoutMs > 0\n ? new Promise<never>((_resolve, reject) => {\n controller.signal.addEventListener('abort', () => {\n if (timedOut)\n reject(new Error(`LLM judge timed out after ${timeoutMs}ms`))\n }, { once: true })\n })\n : undefined\n // Swallowed when the race already settled, so a late abort is not an unhandled rejection.\n timeoutPromise?.catch(() => {})\n\n const grade = async (maxTokens: number) => {\n text = ''\n const streamPromise = options.provider.stream({\n model,\n system: options.system ?? DEFAULT_JUDGE_SYSTEM,\n tools: options.provider.formatTools([JUDGE_TOOL]),\n messages: [userMessage],\n maxTokens,\n cache: false,\n signal: controller.signal,\n toolChoice: { type: 'tool', name: JUDGE_TOOL.name },\n }, {\n onText(delta) {\n text += delta\n },\n })\n return timeoutPromise ? await Promise.race([streamPromise, timeoutPromise]) : await streamPromise\n }\n\n try {\n const budget = options.maxTokens ?? DEFAULT_JUDGE_MAX_TOKENS\n let result = await grade(budget)\n const submitted = (r: typeof result) => r.toolCalls.some(tc => tc.name === JUDGE_TOOL.name)\n if (!submitted(result) && result.usage.finishReason === 'length')\n result = await grade(budget * 2)\n\n const parsed = readJudgeResult(result.toolCalls, text || result.text)\n if (!submitted(result) && parsed.reasoning === UNPARSEABLE_REASONING && result.usage.finishReason)\n parsed.reasoning = `${UNPARSEABLE_REASONING} (finish reason: ${result.usage.finishReason})`\n if (options.metric)\n ctx.metric(options.metric, parsed.score)\n return {\n name,\n passed: parsed.score >= 0.7,\n score: parsed.score,\n details: {\n reasoning: parsed.reasoning,\n ...(parsed.feedback ? { feedback: parsed.feedback } : {}),\n ...(parsed.raw ? { raw: parsed.raw } : {}),\n usage: result.usage,\n },\n }\n }\n finally {\n if (timer)\n clearTimeout(timer)\n }\n }\n}\n\nfunction readJudgeResult(\n toolCalls: ToolCall[],\n fallbackText: string,\n): { score: number, reasoning: string, feedback?: string, raw?: string } {\n // Preferred: the forced tool call carries typed fields.\n const call = toolCalls.find(tc => tc.name === JUDGE_TOOL.name)\n if (call) {\n const input = call.input as { score?: unknown, reasoning?: unknown, feedback?: unknown }\n return {\n score: clampScore(input.score),\n reasoning: typeof input.reasoning === 'string' ? input.reasoning : '',\n ...(typeof input.feedback === 'string' ? { feedback: input.feedback } : {}),\n }\n }\n // Fallback: a provider that ignored tool-forcing and returned text. The\n // lenient parser recovers a score from JSON/prose/bare-number output.\n return parseJudgeOutput(fallbackText)\n}\n\nfunction renderJudgePrompt(input: { rubric: string, input: string }): string {\n return [\n 'Rubric:',\n input.rubric,\n '',\n 'Output to grade:',\n input.input,\n '',\n 'Return JSON only.',\n ].join('\\n')\n}\n\nfunction defaultJudgeInput(ctx: EvalScorerContext): string {\n const chunks = [\n `Final answer:\\n${ctx.result.finalText}`,\n ]\n if (ctx.workspace) {\n chunks.push(`Workspace files:\\n${ctx.workspace.files.map(file => [\n `--- ${file.path}${file.truncated ? ' (truncated)' : ''} ---`,\n file.binary ? '[binary omitted]' : file.content ?? '',\n ].join('\\n')).join('\\n')}`)\n }\n return chunks.join('\\n\\n')\n}\n\nfunction parseJudgeOutput(raw: string): { score: number, reasoning: string, feedback?: string, raw?: string } {\n const trimmed = stripCodeFences(raw.trim())\n\n // Preferred path: a JSON object somewhere in the output.\n const jsonText = extractJsonObject(trimmed)\n if (jsonText) {\n try {\n const parsed = JSON.parse(jsonText) as Record<string, unknown>\n if (parsed.score !== undefined || parsed.reasoning !== undefined) {\n return {\n score: clampScore(parsed.score),\n reasoning: typeof parsed.reasoning === 'string' ? parsed.reasoning : '',\n ...(typeof parsed.feedback === 'string' ? { feedback: parsed.feedback } : {}),\n ...(jsonText === trimmed ? {} : { raw: trimmed }),\n }\n }\n }\n catch {\n // fall through to lenient parsing\n }\n }\n\n // Lenient fallbacks for models that don't honor strict JSON:\n // 1) a `\"score\": 0.8` / `score = 0.8` fragment anywhere.\n const scoreFragment = trimmed.match(/score[\"']?\\s*[:=]\\s*(-?\\d+(?:\\.\\d+)?)/i)\n if (scoreFragment) {\n return { score: clampScore(Number(scoreFragment[1])), reasoning: trimmed.slice(0, 500), raw: trimmed }\n }\n // 2) the whole output is just a number (`0.8` or `8/10`).\n const bareFraction = trimmed.match(/^(-?\\d+(?:\\.\\d+)?)\\s*\\/\\s*(\\d+(?:\\.\\d+)?)$/)\n if (bareFraction) {\n const denom = Number(bareFraction[2])\n return { score: clampScore(denom === 0 ? 0 : Number(bareFraction[1]) / denom), reasoning: trimmed, raw: trimmed }\n }\n const bareNumber = trimmed.match(/^-?\\d+(?:\\.\\d+)?$/)\n if (bareNumber) {\n return { score: clampScore(Number(trimmed)), reasoning: '', raw: trimmed }\n }\n\n return { score: 0, reasoning: UNPARSEABLE_REASONING, raw: trimmed }\n}\n\n/** Strip a leading/trailing markdown code fence (``` or ```json). */\nfunction stripCodeFences(text: string): string {\n const fence = text.match(/^```(?:json)?[ \\t]*\\n([\\s\\S]*?)\\n```$/i)\n return fence ? fence[1].trim() : text\n}\n\n/** Extract the first balanced `{...}` object, ignoring braces inside strings. */\nfunction extractJsonObject(text: string): string | undefined {\n const start = text.indexOf('{')\n if (start === -1)\n return undefined\n let depth = 0\n let inString = false\n let escaped = false\n for (let i = start; i < text.length; i++) {\n const ch = text[i]\n if (inString) {\n if (escaped)\n escaped = false\n else if (ch === '\\\\')\n escaped = true\n else if (ch === '\"')\n inString = false\n continue\n }\n if (ch === '\"') {\n inString = true\n }\n else if (ch === '{') {\n depth++\n }\n else if (ch === '}') {\n depth--\n if (depth === 0)\n return text.slice(start, i + 1)\n }\n }\n return undefined\n}\n\nfunction clampScore(value: unknown): number {\n const n = typeof value === 'number' ? value : Number(value)\n if (!Number.isFinite(n))\n return 0\n return Math.max(0, Math.min(1, n))\n}\n","import type { EvalCaseOptions, EvalDefinition, EvalDefinitionContext } from './eval-types'\nimport type { Provider } from './providers'\n\ninterface RegisteredEval {\n id: string\n define: EvalDefinition\n}\n\nconst evalRegistry: RegisteredEval[] = []\n\nconst STUB_PROVIDER = {\n name: 'stub',\n meta: { defaultModel: 'stub' },\n formatTools: (tools: unknown[]) => tools,\n userMessage: () => ({ role: 'user' as const, content: [] }),\n assistantMessage: () => ({ role: 'assistant' as const, content: [] }),\n toolResultsMessage: () => ({ role: 'user' as const, content: [] }),\n stream: async () => {\n throw new Error('stub provider is not runnable')\n },\n} as unknown as Provider\n\n/**\n * Register an eval definition. Eval files call this at module load; the harness\n * (`buildRegisteredEvals`) materializes them with a provider at run time. The\n * factory keeps definitions lazy so a single registry serves any provider/judge\n * pairing without re-importing eval files.\n *\n * Returns the same factory so a file can also `export default` it for direct,\n * registry-free use (e.g. hermetic unit tests).\n *\n * @param define - Function that builds the eval case from the provider and judge.\n *\n * @example\n * ~~~ts\n * import { defineEval, fileExists, statusCompleted } from 'zidane/eval'\n *\n * export default defineEval(({ provider, model }) => ({\n * id: 'creates-readme',\n * suite: 'files',\n * prompt: 'Create README.md with a one-line project description.',\n * provider,\n * model,\n * workspace: { capture: ['.'] },\n * scorers: [statusCompleted(), fileExists('README.md')],\n * }))\n * ~~~\n */\nexport function defineEval(define: EvalDefinition): EvalDefinition {\n // De-dupe by materializing once with a stub provider to read the id. The stub\n // is never streamed; it only exists so the registry can key on suite/id and a\n // re-imported module doesn't double-register.\n const id = safeRegistryId(define)\n if (!evalRegistry.some(entry => entry.id === id))\n evalRegistry.push({ id, define })\n return define\n}\n\n/**\n * Snapshot of every registered eval, materialized for one provider/judge pair.\n *\n * @param ctx - Provider and judge to build the eval cases with.\n */\nexport function buildRegisteredEvals(ctx: EvalDefinitionContext): EvalCaseOptions[] {\n return evalRegistry.map(entry => entry.define(ctx))\n}\n\n/** Drop every registered eval — test isolation helper. */\nexport function clearRegisteredEvals(): void {\n evalRegistry.length = 0\n}\n\nfunction safeRegistryId(define: EvalDefinition): string {\n try {\n const stub = define({ provider: STUB_PROVIDER, judge: STUB_PROVIDER })\n return `${stub.suite ?? 'eval'}/${stub.id}`\n }\n catch {\n return `eval/${evalRegistry.length}`\n }\n}\n","import type { MetricEmitter, MetricSpecMap } from './eval-metrics'\nimport type { EvalCaseOptions, EvalCaseResult, EvalRunReporter, EvalRunReporterOptions, EvalScorerContext } from './eval-types'\nimport type { HeadlessEvent } from './headless'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { safeSegment, writeEvalArtifacts } from './eval-artifacts'\nimport { computeEvalTagScores, EFFICIENCY_METRICS, emitEfficiencyMetrics, EvalMetricError, finalizeEvalMetrics, meanNormalized } from './eval-metrics'\nimport { formatEvalRunSummaryWithOptions } from './eval-report'\nimport { aggregateScore, runScorers } from './eval-scorers'\nimport { buildEvalRunSummary } from './eval-summary'\nimport { buildTrajectory } from './eval-trajectory'\nimport { prepareWorkspace } from './eval-workspace'\nimport { runHeadless } from './headless'\n\nexport type { CreateEvalAgentOptions, EvalAgent, EvalAgentMcpServers, EvalAgentRunOptions, EvalAgentRunResult, EvalAgentRunStats, EvalAgentStats } from './eval-agent'\nexport { createEvalAgent } from './eval-agent'\nexport { artifactPath, relativeArtifactPath } from './eval-artifacts'\nexport type { ReusableExecutionContext } from './eval-execution'\nexport { createReusableExecutionContext } from './eval-execution'\nexport type { LlmJudgeOptions } from './eval-judge'\nexport { llmJudge } from './eval-judge'\nexport type { EvalMetric, MetricDirection, MetricEmitter, MetricSpec, MetricSpecMap } from './eval-metrics'\nexport { computeEvalTagScores, defineMetrics, EFFICIENCY_METRICS, efficiencyMetricValues, emitEfficiencyMetrics, EvalMetricError, finalizeEvalMetrics, normalizeMetric } from './eval-metrics'\nexport { buildRegisteredEvals, clearRegisteredEvals, defineEval } from './eval-registry'\nexport { formatEvalCaseSummary, formatEvalRunSummary } from './eval-report'\nexport { fileContains, fileContentQuality, fileExists, fileExistsOneOf, functionalityMetric, statusCompleted } from './eval-scorers'\nexport { buildEvalRunSummary } from './eval-summary'\nexport type { Trajectory, TrajectoryStep, TrajectoryStepKind } from './eval-trajectory'\nexport { buildTrajectory, formatTrajectoryLine } from './eval-trajectory'\nexport type { EvalArtifacts, EvalCaseOptions, EvalCaseResult, EvalDefinition, EvalDefinitionContext, EvalRunMetricAggregate, EvalRunReporter, EvalRunReporterOptions, EvalRunSummary, EvalRunSummaryCase, EvalRunUsage, EvalScore, EvalScorer, EvalScorerContext, EvalVariantSummary, EvalWorkspaceFile, EvalWorkspaceOptions, EvalWorkspaceSnapshot, MetricStats } from './eval-types'\n\n/**\n * Runs one eval case: prepares the workspace, runs the agent headless, runs the scorers, computes metrics and the trajectory, and writes artifacts when `artifactDir` is set. The workspace is cleaned up when the run ends.\n *\n * Throws {@link EvalMetricError} when a scorer emits a metric that was not declared or a non-finite value. Other scorer failures are recorded as failed scores.\n *\n * @param options - Case definition: headless options plus `id`, `scorers`, `metrics` and `workspace`.\n * @returns The case result. A run that did not complete resolves with `passed` set to `false`.\n *\n * @example\n * ~~~ts\n * import { fileExists, runEvalCase, statusCompleted } from 'zidane/eval'\n * import { anthropic } from 'zidane/providers/anthropic'\n *\n * const result = await runEvalCase({\n * id: 'creates-readme',\n * suite: 'files',\n * prompt: 'Create README.md with a one-line project description.',\n * provider: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }),\n * maxTurns: 8,\n * workspace: { capture: ['.'] },\n * scorers: [statusCompleted(), fileExists('README.md')],\n * })\n *\n * console.log(result.passed, result.score)\n * ~~~\n */\nexport async function runEvalCase(options: EvalCaseOptions): Promise<EvalCaseResult> {\n const {\n id,\n suite,\n variant,\n tags = [],\n artifactDir,\n workspace,\n scorers = [],\n onEvent,\n ...headless\n } = options\n\n const { metrics: declaredMetrics, sourceFile, ...headlessRest } = headless\n const events: HeadlessEvent[] = []\n // Variant-aware artifact layout: <dir>[/<variant>]/<suite>/<id> so the same\n // case run against two models never overwrites its own output.\n const caseArtifactDir = artifactDir\n ? join(artifactDir, ...(variant ? [safeSegment(variant)] : []), safeSegment(suite ?? 'eval'), safeSegment(id))\n : undefined\n const workspaceState = await prepareWorkspace(headlessRest.execution, workspace)\n const caseMetricIds = new Set(Object.keys(declaredMetrics ?? {}))\n const hasCaseMetrics = caseMetricIds.size > 0\n\n // Merge declared metrics with the always-on efficiency set.\n const metricSpecs: MetricSpecMap = { ...EFFICIENCY_METRICS, ...declaredMetrics }\n const rawMetrics = new Map<string, number>()\n const emitMetric: MetricEmitter = (metricId, raw) => {\n if (!(metricId in metricSpecs))\n throw new EvalMetricError(`Eval ${id}: metric \"${metricId}\" emitted but not declared in defineMetrics`)\n if (!Number.isFinite(raw))\n throw new EvalMetricError(`Eval ${id}: metric \"${metricId}\" emitted a non-finite value (${raw}); scores require finite numbers`)\n rawMetrics.set(metricId, raw)\n }\n\n try {\n const result = await runHeadless({\n ...headlessRest,\n ...(workspaceState.execution ? { execution: workspaceState.execution } : {}),\n onEvent(event) {\n events.push(event)\n onEvent?.(event)\n },\n })\n\n // Auto-emit efficiency metrics from the headless result.\n emitEfficiencyMetrics(emitMetric, result)\n\n const workspaceSnapshot = workspaceState.snapshot()\n const workspaceError = workspaceState.error()\n const scorerContext: EvalScorerContext = {\n id,\n ...(suite ? { suite } : {}),\n tags,\n result,\n events,\n metric: emitMetric,\n ...(workspaceSnapshot ? { workspace: workspaceSnapshot } : {}),\n ...(caseArtifactDir ? { artifactDir: caseArtifactDir } : {}),\n }\n const scores = await runScorers(scorerContext, scorers)\n\n const metrics = finalizeEvalMetrics(metricSpecs, rawMetrics)\n const tagScores = computeEvalTagScores(metrics)\n // Score is metric-driven when metrics are declared beyond efficiency;\n // otherwise it is the scorer aggregate. If the declared set somehow filters\n // to empty, use the scorer aggregate too (avoid a meaningless 0 score).\n const caseMetrics = metrics.filter(metric => caseMetricIds.has(metric.id))\n const score = hasCaseMetrics && caseMetrics.length > 0\n ? meanNormalized(caseMetrics)\n : aggregateScore(scores)\n\n const evalResult: EvalCaseResult = {\n id,\n ...(suite ? { suite } : {}),\n ...(variant ? { variant } : {}),\n tags,\n result,\n score,\n passed: result.status === 'completed' && scores.every(score => score.passed),\n scores,\n metrics,\n tagScores,\n trajectory: buildTrajectory(result.transcript),\n events,\n ...(sourceFile ? { sourceFile } : {}),\n ...(workspaceSnapshot ? { workspace: workspaceSnapshot } : {}),\n ...(workspaceError ? { workspaceError } : {}),\n }\n\n const artifacts = caseArtifactDir\n ? await writeEvalArtifacts(caseArtifactDir, evalResult)\n : undefined\n\n return {\n ...evalResult,\n ...(artifacts ? { artifacts } : {}),\n }\n }\n finally {\n await workspaceState.cleanup()\n }\n}\n\n/** Minimal subset of a test runner's API the eval harness needs. */\nexport interface EvalTestRunner {\n /** Registers one test. */\n it: (name: string, fn: () => Promise<void> | void) => void\n /** Registers a callback that runs once after every test. */\n afterAll: (fn: () => Promise<void> | void) => void\n}\n\n/** Options for {@link registerEvalTests}. */\nexport interface RegisterEvalTestsOptions {\n /** Eval cases to register, one test each. */\n cases: EvalCaseOptions[]\n /** Test runner API the tests are registered on, for example `{ it, afterAll }` from `bun:test`. */\n runner: EvalTestRunner\n /** Reporter that collects the results. A new one is created when omitted. */\n reporter?: EvalRunReporter\n /** Directory where per-case artifacts are written. Nothing is written when omitted. */\n artifactDir?: string\n /**\n * When true (default), each case asserts only that the agent run reached a\n * terminal `completed` status — scores are recorded but never fail the test.\n * Evals are scoring tools, not deterministic assertions.\n */\n failOnIncomplete?: boolean\n /** Print the aggregated run summary after all cases. Default true. */\n printSummary?: boolean\n /** Repeat each case N times (each repetition is its own test). Default 1. */\n repeat?: number\n /** Teardown run once after all cases (e.g. dispose a shared container). */\n dispose?: () => Promise<void> | void\n /**\n * Max eval cases to run concurrently. Each case keeps its own workspace dir,\n * so a shared container runs them in parallel safely. Default 1 (sequential).\n */\n concurrency?: number\n}\n\n/**\n * Register one test per eval case against a test runner, funnel every result\n * into a shared reporter, and print the aggregated summary once after all cases.\n *\n * A failing test means the agent run itself broke (provider/tool/timeout). Low\n * scores are reported, not asserted — see {@link RegisterEvalTestsOptions.failOnIncomplete}.\n *\n * @param options - Cases, test runner and optional reporter, artifact directory, repeat count and concurrency.\n * @returns The reporter that receives every case result.\n *\n * @example\n * ~~~ts\n * import { afterAll, it } from 'bun:test'\n * import { fileExists, registerEvalTests, statusCompleted } from 'zidane/eval'\n * import { anthropic } from 'zidane/providers/anthropic'\n *\n * registerEvalTests({\n * runner: { it, afterAll },\n * artifactDir: 'eval-artifacts',\n * cases: [{\n * id: 'creates-readme',\n * suite: 'files',\n * prompt: 'Create README.md with a one-line project description.',\n * provider: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }),\n * workspace: { capture: ['.'] },\n * scorers: [statusCompleted(), fileExists('README.md')],\n * }],\n * })\n * ~~~\n */\nexport function registerEvalTests(options: RegisterEvalTestsOptions): EvalRunReporter {\n const reporter = options.reporter ?? createEvalRunReporter()\n const failOnIncomplete = options.failOnIncomplete ?? true\n const printSummary = options.printSummary ?? true\n const repeat = Math.max(1, options.repeat ?? 1)\n const concurrency = Math.max(1, options.concurrency ?? 1)\n\n options.runner.afterAll(async () => {\n await reporter.flush()\n if (printSummary)\n console.log(`\\n${reporter.format()}\\n`)\n if (options.dispose)\n await options.dispose()\n })\n\n // Build the (case × repeat) work list. Each entry runs exactly once; the\n // matching `it` test awaits its already-scheduled promise so bun still shows\n // per-case pass/fail while the pool drives real parallelism.\n const work: Array<{ label: string, run: () => Promise<EvalCaseResult> }> = []\n for (const evalCase of options.cases) {\n const caseLabel = `${evalCase.suite ? `${evalCase.suite}/` : ''}${evalCase.id}`\n const baseLabel = evalCase.variant ? `[${evalCase.variant}] ${caseLabel}` : caseLabel\n for (let run = 1; run <= repeat; run++) {\n const label = repeat > 1 ? `${baseLabel} #${run}` : baseLabel\n const caseId = repeat > 1 ? `${evalCase.id}-repeat-${run}` : evalCase.id\n work.push({\n label,\n run: () => runEvalCase({\n ...evalCase,\n id: caseId,\n ...(options.artifactDir ? { artifactDir: options.artifactDir } : {}),\n }),\n })\n }\n }\n\n const schedule = createLazyPool(concurrency)\n\n work.forEach((w) => {\n options.runner.it(w.label, async () => {\n const result = await schedule(w.run)\n await reporter.record(result)\n if (failOnIncomplete && result.result.status !== 'completed') {\n throw new Error(`Eval ${w.label} did not complete: ${JSON.stringify(result.result.error ?? { status: result.result.status }, null, 2)}`)\n }\n })\n })\n\n return reporter\n}\n\n/**\n * Lazily run tasks with a bounded concurrency `limit`. Nothing starts until a\n * runner invokes the corresponding test callback, so filtered/skipped tests do\n * not leak model or Docker work in the background.\n */\nfunction createLazyPool(limit: number): <T>(task: () => Promise<T>) => Promise<T> {\n const queue: Array<() => void> = []\n let active = 0\n\n const drain = (): void => {\n const available = Math.min(limit - active, queue.length)\n for (let i = 0; i < available; i++)\n queue.shift()?.()\n }\n\n return <T>(task: () => Promise<T>) => new Promise<T>((resolve, reject) => {\n const run = async (): Promise<void> => {\n active++\n try {\n resolve(await task())\n }\n catch (err) {\n reject(err)\n }\n finally {\n active--\n drain()\n }\n }\n queue.push(() => void run())\n drain()\n })\n}\n\n/**\n * Creates a reporter that collects case results, builds the run summary and formats it as a terminal table.\n *\n * @param options - Output directory and color setting. All fields are optional.\n */\nexport function createEvalRunReporter(options: EvalRunReporterOptions = {}): EvalRunReporter {\n const results: EvalCaseResult[] = []\n\n return {\n get results() {\n return results\n },\n async record(result) {\n results.push(result)\n if (options.outputDir) {\n const segments = [\n ...(result.variant ? [safeSegment(result.variant)] : []),\n safeSegment(result.suite ?? 'eval'),\n safeSegment(result.id),\n ]\n const casePath = join(options.outputDir, 'cases', `${segments.join('--')}.json`)\n await mkdir(join(options.outputDir, 'cases'), { recursive: true })\n await writeFile(casePath, `${JSON.stringify(result, null, 2)}\\n`)\n }\n },\n async flush() {\n const summary = buildEvalRunSummary(results)\n if (options.outputDir) {\n await mkdir(options.outputDir, { recursive: true })\n await writeFile(join(options.outputDir, 'run-summary.json'), `${JSON.stringify(summary, null, 2)}\\n`)\n }\n return summary\n },\n format() {\n return formatEvalRunSummaryWithOptions(results, { color: options.color })\n },\n }\n}\n"],"mappings":"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"}
|