@axlsdk/eval 0.17.7 → 0.17.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/dist/{chunk-NPKIP4SB.js → chunk-NETD4AUB.js} +15 -3
- package/dist/chunk-NETD4AUB.js.map +1 -0
- package/dist/cli.cjs +41 -8
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +28 -7
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +26 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -17
- package/dist/index.d.ts +23 -17
- package/dist/index.js +13 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-NPKIP4SB.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
evalCompare,
|
|
5
5
|
rescore,
|
|
6
6
|
runEval
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NETD4AUB.js";
|
|
8
8
|
|
|
9
9
|
// src/cli.ts
|
|
10
10
|
import { readdirSync, statSync } from "fs";
|
|
@@ -70,6 +70,22 @@ var KNOWN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
70
70
|
"--runs",
|
|
71
71
|
"--capture-traces"
|
|
72
72
|
]);
|
|
73
|
+
function installAbortHandler(controller) {
|
|
74
|
+
let signalled = false;
|
|
75
|
+
const onSignal = (sig) => {
|
|
76
|
+
if (signalled) {
|
|
77
|
+
console.error(`
|
|
78
|
+
[axl-eval] Second ${sig} \u2014 forcing exit.`);
|
|
79
|
+
process.exit(130);
|
|
80
|
+
}
|
|
81
|
+
signalled = true;
|
|
82
|
+
console.error(`
|
|
83
|
+
[axl-eval] ${sig} received \u2014 cancelling eval (press again to force exit)...`);
|
|
84
|
+
controller.abort();
|
|
85
|
+
};
|
|
86
|
+
process.on("SIGINT", onSignal);
|
|
87
|
+
process.on("SIGTERM", onSignal);
|
|
88
|
+
}
|
|
73
89
|
async function main() {
|
|
74
90
|
const args = process.argv.slice(2);
|
|
75
91
|
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
@@ -102,11 +118,13 @@ When no config is found, a bare AxlRuntime is created (providers from env vars).
|
|
|
102
118
|
await runCompare(args.slice(1));
|
|
103
119
|
return;
|
|
104
120
|
}
|
|
121
|
+
const controller = new AbortController();
|
|
122
|
+
installAbortHandler(controller);
|
|
105
123
|
if (args[0] === "rescore") {
|
|
106
|
-
await runRescore(args.slice(1));
|
|
124
|
+
await runRescore(args.slice(1), controller.signal);
|
|
107
125
|
return;
|
|
108
126
|
}
|
|
109
|
-
await runEvalCommand(args);
|
|
127
|
+
await runEvalCommand(args, controller.signal);
|
|
110
128
|
}
|
|
111
129
|
function parseThresholdArg(args) {
|
|
112
130
|
const idx = args.indexOf("--threshold");
|
|
@@ -201,7 +219,7 @@ Compare: baseline (${comparison.baseline.id.slice(0, 8)}) -> candidate (${compar
|
|
|
201
219
|
}
|
|
202
220
|
}
|
|
203
221
|
}
|
|
204
|
-
async function runRescore(args) {
|
|
222
|
+
async function runRescore(args, signal) {
|
|
205
223
|
const { outputPath, configArg, conditions, paths } = parseEvalArgs(args);
|
|
206
224
|
if (paths.length < 2) {
|
|
207
225
|
console.error("Usage: axl-eval rescore <results.json> <eval-file> [--output <file>]");
|
|
@@ -226,7 +244,8 @@ async function runRescore(args) {
|
|
|
226
244
|
}
|
|
227
245
|
const rescored = [];
|
|
228
246
|
for (const resultData of results) {
|
|
229
|
-
|
|
247
|
+
if (signal.aborted) break;
|
|
248
|
+
rescored.push(await rescore(resultData, evalConfig.scorers, runtime, { signal }));
|
|
230
249
|
}
|
|
231
250
|
for (const r of rescored) {
|
|
232
251
|
console.log("\n" + formatTable(r) + "\n");
|
|
@@ -439,7 +458,7 @@ function parseEvalArgs(args) {
|
|
|
439
458
|
}
|
|
440
459
|
return { outputPath, configArg, conditions, runs, captureTraces, paths };
|
|
441
460
|
}
|
|
442
|
-
async function runEvalCommand(args) {
|
|
461
|
+
async function runEvalCommand(args, signal) {
|
|
443
462
|
const { outputPath, configArg, conditions, runs, captureTraces, paths } = parseEvalArgs(args);
|
|
444
463
|
if (paths.length === 0) {
|
|
445
464
|
console.error("Error: No eval file path provided");
|
|
@@ -458,6 +477,7 @@ async function runEvalCommand(args) {
|
|
|
458
477
|
let failedFiles = 0;
|
|
459
478
|
try {
|
|
460
479
|
for (const filePath of evalFiles) {
|
|
480
|
+
if (signal.aborted) break;
|
|
461
481
|
try {
|
|
462
482
|
const mod = await importModule(path.resolve(filePath), import.meta.url);
|
|
463
483
|
const evalConfig = pickDefault(mod);
|
|
@@ -522,13 +542,14 @@ async function runEvalCommand(args) {
|
|
|
522
542
|
failedFiles++;
|
|
523
543
|
continue;
|
|
524
544
|
}
|
|
525
|
-
const runOptions = captureTraces ? { captureTraces: true } :
|
|
545
|
+
const runOptions = { signal, ...captureTraces ? { captureTraces: true } : {} };
|
|
526
546
|
if (runs > 1) {
|
|
527
547
|
const { randomUUID } = await import("crypto");
|
|
528
548
|
const runGroupId = randomUUID();
|
|
529
549
|
const runResults = [];
|
|
530
550
|
let runFailure;
|
|
531
551
|
for (let r = 0; r < runs; r++) {
|
|
552
|
+
if (signal.aborted) break;
|
|
532
553
|
console.error(`[axl-eval] Run ${r + 1}/${runs}...`);
|
|
533
554
|
try {
|
|
534
555
|
const result = await runEval(evalConfig, executeWorkflow, runtime, runOptions);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/cli-utils.ts","../src/cli-validate.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readdirSync, statSync } from 'node:fs';\nimport { readFile as readFileAsync, writeFile as writeFileAsync, mkdir } from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { AxlRuntime, EvalExecuteWorkflow } from '@axlsdk/axl';\nimport { evalCompare } from './compare.js';\nimport { runEval } from './runner.js';\nimport { rescore } from './rescore.js';\nimport { aggregateRuns } from './multi-run.js';\nimport type { MultiRunSummary } from './multi-run.js';\nimport type { EvalConfig, EvalResult } from './types.js';\nimport {\n findConfig,\n resolveRuntime,\n importModule,\n registerConditions,\n pickDefault,\n pickExport,\n expandGlob,\n CONFIG_CANDIDATES,\n} from './cli-utils.js';\nimport { validateEvalConfig } from './cli-validate.js';\n\nconst KNOWN_FLAGS = new Set([\n '--output',\n '--config',\n '--conditions',\n '--fail-on-regression',\n '--threshold',\n '--runs',\n '--capture-traces',\n]);\n\nasync function main() {\n const args = process.argv.slice(2);\n\n if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {\n console.log(`\nUsage:\n axl-eval <path> Run eval file(s)\n axl-eval <path> --runs <n> Run eval N times (multi-run)\n axl-eval <path> --output <file> Save results to JSON\n axl-eval <path> --config <file> Use config file for runtime\n axl-eval <path> --conditions <list> Node.js import conditions (comma-separated)\n axl-eval <path> --capture-traces Populate EvalItem.traces on every item\n (success + failure). Adds memory\n overhead proportional to dataset size\n x turns x agents; off by default.\n axl-eval rescore <results> <eval-file> Re-run scorers on saved outputs\n axl-eval compare <a> <b> Compare two eval result files\n axl-eval compare <a> <b> --threshold <v> Set regression threshold (global or per-scorer)\n axl-eval compare <a> <b> --fail-on-regression Exit 1 if regressions\n\nConfig auto-detection (when --config is not specified):\n ${CONFIG_CANDIDATES.join(' -> ')}\n\nWhen a config is found, the exported AxlRuntime is passed to executeWorkflow\nand cost is tracked automatically via runtime.trackCost().\nWhen no config is found, a bare AxlRuntime is created (providers from env vars).\n`);\n process.exit(0);\n }\n\n if (args[0] === 'compare') {\n await runCompare(args.slice(1));\n return;\n }\n\n if (args[0] === 'rescore') {\n await runRescore(args.slice(1));\n return;\n }\n\n await runEvalCommand(args);\n}\n\nfunction parseThresholdArg(args: string[]): Record<string, number> | number | undefined {\n const idx = args.indexOf('--threshold');\n if (idx === -1 || idx + 1 >= args.length) return undefined;\n const value = args[idx + 1];\n\n // Global numeric threshold: --threshold 0.05\n if (/^[\\d.]+$/.test(value)) return parseFloat(value);\n\n // Per-scorer map: --threshold accuracy=0,tone=0.1\n const map: Record<string, number> = {};\n for (const pair of value.split(',')) {\n const [key, val] = pair.split('=');\n if (key && val != null) map[key.trim()] = parseFloat(val.trim());\n }\n return Object.keys(map).length > 0 ? map : undefined;\n}\n\nasync function runCompare(args: string[]) {\n const failOnRegression = args.includes('--fail-on-regression');\n const thresholds = parseThresholdArg(args);\n const files = args.filter(\n (a, i) => !a.startsWith('--') && !(i > 0 && args[i - 1] === '--threshold'),\n );\n\n if (files.length !== 2) {\n console.error('Usage: axl-eval compare <baseline.json> <candidate.json> [--threshold <value>]');\n process.exit(1);\n }\n\n const baselineRaw = JSON.parse(await readFileAsync(files[0], 'utf-8'));\n const candidateRaw = JSON.parse(await readFileAsync(files[1], 'utf-8'));\n const baseline: EvalResult | EvalResult[] = baselineRaw;\n const candidate: EvalResult | EvalResult[] = candidateRaw;\n const compareOptions = thresholds != null ? { thresholds } : undefined;\n const comparison = evalCompare(baseline, candidate, compareOptions);\n\n console.log(\n `\\nCompare: baseline (${comparison.baseline.id.slice(0, 8)}) -> candidate (${comparison.candidate.id.slice(0, 8)})\\n`,\n );\n\n const scorerNames = Object.keys(comparison.scorers);\n const maxNameLen = Math.max(...scorerNames.map((n) => n.length), 6);\n const hasCI = scorerNames.some((n) => comparison.scorers[n].ci != null);\n\n const ciHeader = hasCI ? ' CI 95% Sig' : '';\n const ciRule = hasCI ? ' ---------------- ---' : '';\n console.log(` ${'Scorer'.padEnd(maxNameLen)} Baseline Candidate Delta Change${ciHeader}`);\n console.log(` ${''.padEnd(maxNameLen, '-')} -------- --------- -------- ------${ciRule}`);\n\n for (const name of scorerNames) {\n const s = comparison.scorers[name];\n const sign = s.delta > 0 ? '+' : '';\n let line = ` ${name.padEnd(maxNameLen)} ${s.baselineMean.toFixed(3).padStart(8)} ${s.candidateMean.toFixed(3).padStart(9)} ${(sign + s.delta.toFixed(3)).padStart(8)} ${(sign + s.deltaPercent.toFixed(1) + '%').padStart(6)}`;\n if (hasCI) {\n if (s.ci) {\n const lo = (s.ci.lower >= 0 ? '+' : '') + s.ci.lower.toFixed(4);\n const hi = (s.ci.upper >= 0 ? '+' : '') + s.ci.upper.toFixed(4);\n const sig = s.significant ? ' *' : ' ';\n line += ` [${lo}, ${hi}]${sig}`;\n } else {\n line += ' —'.padEnd(22);\n }\n }\n console.log(line);\n }\n\n if (comparison.timing) {\n const t = comparison.timing;\n const sign = t.delta > 0 ? '+' : '';\n console.log(\n `\\n Timing: baseline ${(t.baselineMean / 1000).toFixed(2)}s -> candidate ${(t.candidateMean / 1000).toFixed(2)}s (${sign}${t.deltaPercent.toFixed(1)}%)`,\n );\n }\n if (comparison.cost) {\n const c = comparison.cost;\n const sign = c.delta > 0 ? '+' : '';\n console.log(\n ` Cost: baseline $${c.baselineTotal.toFixed(2)} -> candidate $${c.candidateTotal.toFixed(2)} (${sign}${c.deltaPercent.toFixed(1)}%)`,\n );\n }\n\n const baselineRef = Array.isArray(baseline) ? baseline[0] : baseline;\n const stable = Math.max(\n 0,\n baselineRef.items.length - comparison.regressions.length - comparison.improvements.length,\n );\n console.log(\n `\\n Regressions: ${comparison.regressions.length} | Improvements: ${comparison.improvements.length} | Stable: ${stable}\\n`,\n );\n\n if (failOnRegression && comparison.regressions.length > 0) {\n // When CI is available, only fail on significant regressions\n const hasSignificance = scorerNames.some((n) => comparison.scorers[n].significant != null);\n if (hasSignificance) {\n const hasSignificantRegression = scorerNames.some(\n (n) => comparison.scorers[n].significant === true && comparison.scorers[n].delta < 0,\n );\n if (hasSignificantRegression) process.exit(1);\n } else {\n process.exit(1);\n }\n }\n}\n\nasync function runRescore(args: string[]) {\n const { outputPath, configArg, conditions, paths } = parseEvalArgs(args);\n\n if (paths.length < 2) {\n console.error('Usage: axl-eval rescore <results.json> <eval-file> [--output <file>]');\n process.exit(1);\n }\n\n const [resultsPath, evalFilePath] = paths;\n const raw = JSON.parse(await readFileAsync(resultsPath, 'utf-8'));\n const results: EvalResult[] = Array.isArray(raw) ? raw : [raw];\n\n const runtime = await getRuntime(configArg, conditions);\n try {\n const mod = await importModule(path.resolve(evalFilePath), import.meta.url);\n const evalConfig = pickDefault<EvalConfig>(mod);\n\n if (!evalConfig || typeof evalConfig !== 'object') {\n console.error(\n `Error: ${evalFilePath} does not export an eval config object — got ${evalConfig === null ? 'null' : typeof evalConfig}.`,\n );\n process.exit(1);\n }\n if (!Array.isArray(evalConfig.scorers) || evalConfig.scorers.length === 0) {\n console.error(`Error: ${evalFilePath} does not export a non-empty scorers array.`);\n process.exit(1);\n }\n\n const rescored: EvalResult[] = [];\n for (const resultData of results) {\n rescored.push(await rescore(resultData, evalConfig.scorers, runtime));\n }\n\n for (const r of rescored) {\n console.log('\\n' + formatTable(r) + '\\n');\n }\n\n if (outputPath) {\n const output = Array.isArray(raw) ? rescored : rescored[0];\n const outputDir = path.dirname(path.resolve(outputPath));\n await mkdir(outputDir, { recursive: true });\n await writeFileAsync(outputPath, JSON.stringify(output, null, 2), 'utf-8');\n console.log(`Rescored results saved to ${outputPath}`);\n }\n } finally {\n await runtime.shutdown().catch(() => {});\n }\n}\n\n/**\n * Resolve a CLI path argument into a list of eval files.\n *\n * Accepts:\n * - An explicit file path (`path/to/foo.eval.ts`)\n * - A directory (lists `*.eval.[mc]?[jt]sx?` inside, non-recursive)\n * - A glob pattern: `evals/*.eval.ts`, `evals/**\\/*.eval.ts`, `**\\/*.eval.ts`\n *\n * Glob expansion mirrors the studio eval-loader's so users get the same\n * behavior in both places. Without it, users running on Windows or with\n * quoted patterns hit confusing \"file not found\" errors when the shell\n * couldn't expand the glob.\n */\nfunction collectEvalFiles(p: string): string[] {\n if (p.includes('*')) return expandGlob(p, process.cwd());\n const resolved = path.resolve(p);\n try {\n const stat = statSync(resolved);\n if (stat.isDirectory()) {\n const entries = readdirSync(resolved);\n return entries\n .filter((e) => /\\.eval\\.[mc]?[jt]sx?$/.test(e))\n .map((e) => path.join(resolved, e));\n }\n return [resolved];\n } catch {\n return [resolved];\n }\n}\n\n/** Render observed workflows for a terse header line. Multiple → comma-separated. */\nfunction formatWorkflows(workflows: unknown): string {\n if (!Array.isArray(workflows) || workflows.length === 0) return '(unknown)';\n return (workflows as unknown[]).filter((w): w is string => typeof w === 'string').join(', ');\n}\n\nfunction formatTable(result: EvalResult): string {\n const lines: string[] = [];\n const scorerNames = Object.keys(result.summary.scorers);\n const maxNameLen = Math.max(...scorerNames.map((n) => n.length), 'Scorer'.length);\n const colWidth = 8;\n\n lines.push(\n `Eval: ${formatWorkflows(result.metadata.workflows)} x ${result.dataset} (${result.summary.count} items)`,\n );\n lines.push(\n ` ${'Scorer'.padEnd(maxNameLen)} ${'Mean'.padStart(colWidth)} ${'Min'.padStart(colWidth)} ${'Max'.padStart(colWidth)} ${'p50'.padStart(colWidth)} ${'p95'.padStart(colWidth)}`,\n );\n\n const ruleLen = maxNameLen + 2 + (colWidth + 2) * 5;\n lines.push(' ' + '\\u2500'.repeat(ruleLen));\n\n for (const name of scorerNames) {\n const s = result.summary.scorers[name];\n // Detect scorers with no valid scores (all items errored → computeStats([]) → all zeros)\n const validScoreCount = result.items.filter((i) => !i.error && i.scores[name] != null).length;\n if (validScoreCount === 0) {\n lines.push(\n ` ${name.padEnd(maxNameLen)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)}`,\n );\n } else {\n lines.push(\n ` ${name.padEnd(maxNameLen)} ${s.mean.toFixed(2).padStart(colWidth)} ${s.min.toFixed(2).padStart(colWidth)} ${s.max.toFixed(2).padStart(colWidth)} ${s.p50.toFixed(2).padStart(colWidth)} ${s.p95.toFixed(2).padStart(colWidth)}`,\n );\n }\n }\n\n if (result.summary.timing) {\n const t = result.summary.timing;\n lines.push(\n ` ${'Timing'.padEnd(maxNameLen)} ${(t.mean / 1000).toFixed(2).padStart(colWidth)}s ${(t.p50 / 1000).toFixed(2).padStart(colWidth)}s ${(t.p95 / 1000).toFixed(2).padStart(colWidth)}s`,\n );\n }\n\n const durationSec = (result.duration / 1000).toFixed(1);\n const costStr = result.totalCost > 0 ? `$${result.totalCost.toFixed(2)}` : '$0.00';\n lines.push('');\n lines.push(\n ` Failures: ${result.summary.failures}/${result.summary.count} | Cost: ${costStr} | Duration: ${durationSec}s`,\n );\n\n const itemsWithErrors = result.items.filter((i) => i.scorerErrors?.length);\n if (itemsWithErrors.length > 0) {\n const uniqueErrors = [...new Set(itemsWithErrors.flatMap((i) => i.scorerErrors!))];\n lines.push('');\n lines.push(\n ` Scorer errors (${itemsWithErrors.length}/${result.summary.count} items affected):`,\n );\n for (const err of uniqueErrors.slice(0, 5)) {\n lines.push(` - ${err}`);\n }\n if (uniqueErrors.length > 5) {\n lines.push(` ... and ${uniqueErrors.length - 5} more`);\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction formatMultiRunTable(summary: MultiRunSummary): string {\n const lines: string[] = [];\n const scorerNames = Object.keys(summary.scorers);\n const maxNameLen = Math.max(...scorerNames.map((n) => n.length), 'Scorer'.length);\n const colWidth = 16;\n\n lines.push(\n `Eval: ${formatWorkflows(summary.workflows)} x ${summary.dataset} \\u2014 ${summary.runCount} runs`,\n );\n lines.push(\n ` ${'Scorer'.padEnd(maxNameLen)} ${'Mean \\u00b1 Std'.padStart(colWidth)} ${'Min'.padStart(8)} ${'Max'.padStart(8)}`,\n );\n const ruleLen = maxNameLen + 2 + colWidth + 2 + 8 + 2 + 8;\n lines.push(' ' + '\\u2500'.repeat(ruleLen));\n\n for (const name of scorerNames) {\n const s = summary.scorers[name];\n const meanStd = `${s.mean.toFixed(3)} \\u00b1 ${s.std.toFixed(3)}`;\n lines.push(\n ` ${name.padEnd(maxNameLen)} ${meanStd.padStart(colWidth)} ${s.min.toFixed(3).padStart(8)} ${s.max.toFixed(3).padStart(8)}`,\n );\n }\n\n if (summary.timing) {\n lines.push(\n ` ${'Timing'.padEnd(maxNameLen)} ${((summary.timing.mean / 1000).toFixed(2) + ' \\u00b1 ' + (summary.timing.std / 1000).toFixed(2) + 's').padStart(colWidth)}`,\n );\n }\n\n const costStr = summary.totalCost > 0 ? `$${summary.totalCost.toFixed(2)}` : '$0.00';\n const durationStr = (summary.totalDuration / 1000).toFixed(1);\n lines.push('');\n lines.push(` Total Cost: ${costStr} | Total Duration: ${durationStr}s`);\n\n return lines.join('\\n');\n}\n\n// ── Runtime resolution ─────────────────────────────────────────────\n\nasync function resolveRuntimeFromConfig(configPath: string): Promise<AxlRuntime> {\n try {\n const mod = await importModule(configPath, import.meta.url);\n const runtime = resolveRuntime(mod) as AxlRuntime;\n\n if (!runtime || typeof runtime.execute !== 'function') {\n console.error(`Config must export a default AxlRuntime instance.`);\n if (runtime) {\n const keys = Object.keys(runtime as object)\n .slice(0, 5)\n .join(', ');\n console.error(` Got: ${typeof runtime}${keys ? ` with keys: { ${keys} }` : ''}`);\n }\n console.error(\n `Example:\\n import { AxlRuntime } from '@axlsdk/axl';\\n export default new AxlRuntime({ ... });`,\n );\n process.exit(1);\n }\n\n return runtime;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (\n /Cannot use import statement|Unexpected reserved word|top-level await|exports is not defined/.test(\n msg,\n )\n ) {\n const ext = path.extname(configPath);\n console.error(`[axl-eval] Config failed to load due to a CJS/ESM compatibility issue.`);\n if (ext === '.ts' || ext === '.tsx') {\n console.error(\n ` Tip: try renaming to .mts to force ESM format, or ensure tsx is installed and up to date.`,\n );\n } else {\n console.error(` Tip: add \"type\": \"module\" to your package.json.`);\n }\n console.error();\n }\n console.error(`Failed to load config:`, err);\n process.exit(1);\n }\n}\n\nasync function getRuntime(configArg?: string, conditions?: string[]): Promise<AxlRuntime> {\n // Register import conditions before any config loading\n if (conditions && conditions.length > 0) {\n await registerConditions(conditions);\n }\n\n // 1. Explicit --config\n if (configArg) {\n const configPath = path.resolve(process.cwd(), configArg);\n const stat = statSync(configPath, { throwIfNoEntry: false });\n if (!stat?.isFile()) {\n console.error(`Config file not found: ${configPath}`);\n process.exit(1);\n }\n console.error(`[axl-eval] Loading config from ${configPath}`);\n return resolveRuntimeFromConfig(configPath);\n }\n\n // 2. Auto-detect\n const found = findConfig(process.cwd());\n if (found) {\n console.error(`[axl-eval] Auto-detected config: ${found}`);\n return resolveRuntimeFromConfig(found);\n }\n\n // 3. Bare runtime (providers from env vars)\n const { AxlRuntime } = await import('@axlsdk/axl');\n return new AxlRuntime();\n}\n\n// ── Arg parsing ────────────────────────────────────────────────────\n\nfunction parseEvalArgs(args: string[]): {\n outputPath?: string;\n configArg?: string;\n conditions: string[];\n runs: number;\n captureTraces: boolean;\n paths: string[];\n} {\n let outputPath: string | undefined;\n let configArg: string | undefined;\n let conditions: string[] = [];\n let runs = 1;\n let captureTraces = false;\n const paths: string[] = [];\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === '--output' || arg === '--config' || arg === '--conditions' || arg === '--runs') {\n if (i + 1 >= args.length) {\n console.error(`Error: ${arg} requires a value`);\n process.exit(1);\n }\n const value = args[++i];\n if (arg === '--output') outputPath = value;\n else if (arg === '--config') configArg = value;\n else if (arg === '--runs') runs = Math.max(1, parseInt(value, 10) || 1);\n else\n conditions = value\n .split(',')\n .map((c) => c.trim())\n .filter(Boolean);\n } else if (arg === '--capture-traces') {\n // Boolean flag — no value consumed.\n captureTraces = true;\n } else if (arg.startsWith('--')) {\n if (!KNOWN_FLAGS.has(arg)) {\n console.error(`Unknown flag: ${arg}`);\n process.exit(1);\n }\n } else {\n paths.push(arg);\n }\n }\n\n return { outputPath, configArg, conditions, runs, captureTraces, paths };\n}\n\n// ── Main eval command ──────────────────────────────────────────────\n\nasync function runEvalCommand(args: string[]) {\n const { outputPath, configArg, conditions, runs, captureTraces, paths } = parseEvalArgs(args);\n\n if (paths.length === 0) {\n console.error('Error: No eval file path provided');\n process.exit(1);\n }\n\n const evalFiles: string[] = [];\n for (const p of paths) {\n evalFiles.push(...collectEvalFiles(p));\n }\n\n if (evalFiles.length === 0) {\n console.error('Error: No eval files found');\n process.exit(1);\n }\n\n const runtime = await getRuntime(configArg, conditions);\n const results: EvalResult[] = [];\n let failedFiles = 0;\n\n try {\n for (const filePath of evalFiles) {\n try {\n const mod = await importModule(path.resolve(filePath), import.meta.url);\n const evalConfig = pickDefault<EvalConfig>(mod);\n\n const validationError = validateEvalConfig(evalConfig);\n if (validationError) {\n console.error(`Error: ${filePath} ${validationError}`);\n failedFiles++;\n continue;\n }\n\n // Resolve executeWorkflow: custom export > registered workflow > error\n // Walk the ESM/CJS interop chain symmetrically with the default export\n // so named exports stay visible when tsx loads the eval module as CJS.\n const exported = pickExport<unknown>(mod, 'executeWorkflow');\n\n // Validate that the export, if present, is callable. Catches the\n // `export const executeWorkflow = 'foo'` typo at the boundary instead\n // of crashing deep inside trackExecution with a confusing stack.\n let customExecute: EvalExecuteWorkflow | undefined;\n if (typeof exported === 'function') {\n customExecute = exported as EvalExecuteWorkflow;\n } else if (exported !== undefined) {\n console.error(\n `[axl-eval] Error: ${filePath} exports executeWorkflow but it is ${typeof exported}, not a function.`,\n );\n failedFiles++;\n continue;\n }\n\n let executeWorkflow: EvalExecuteWorkflow;\n\n if (customExecute) {\n // Wrap custom executeWorkflow with trackExecution for cost + metadata attribution\n executeWorkflow = async (input, rt) => {\n const {\n result,\n cost: trackedCost,\n metadata,\n } = await runtime.trackExecution(async () => {\n return customExecute(input, rt);\n });\n return {\n output: result.output,\n cost: result.cost ?? trackedCost,\n metadata: result.metadata ?? metadata,\n };\n };\n } else if (runtime.getWorkflow(evalConfig.workflow)) {\n // No executeWorkflow exported but workflow is registered — use runtime.execute()\n executeWorkflow = async (input) => {\n const { result, cost, metadata } = await runtime.trackExecution(async () => {\n return runtime.execute(evalConfig.workflow, input);\n });\n return { output: result, cost, metadata };\n };\n } else {\n // Fail loudly. The previous identity-passthrough fallback silently\n // produced all-zero scores in CI — exactly the kind of footgun the\n // \"fail loudly, not silently\" rule is meant to prevent. If you\n // genuinely want identity, export it explicitly:\n // export const executeWorkflow = async (input) => ({ output: input });\n //\n // Surface what WAS exported (top-level + .default) so users\n // recognize a typo like `execute_workflow` and can spot the\n // CJS-interop case that motivates this whole code path: when tsx\n // loads a `.ts` file as CJS, all named exports land on\n // `mod.default.<name>`. The chain walk above already handled this,\n // but a user who removed `executeWorkflow` will see exactly what\n // export names ARE present.\n const exportShape = (() => {\n const top = Object.keys(mod).filter((k) => k !== 'default');\n const fromDefault =\n mod.default && typeof mod.default === 'object'\n ? Object.keys(mod.default as Record<string, unknown>)\n : [];\n const all = [...new Set([...top, ...fromDefault])];\n return all.length > 0 ? `Found exports: [${all.join(', ')}].` : '';\n })();\n console.error(\n `[axl-eval] Error: ${filePath} does not export an executeWorkflow function ` +\n `and no workflow named \"${evalConfig.workflow}\" is registered on the runtime.\\n` +\n (exportShape ? ` ${exportShape}\\n` : '') +\n ` Add either:\\n` +\n ` export async function executeWorkflow(input, runtime) { ... }\\n` +\n ` or register the workflow on your runtime via runtime.registerWorkflow(workflow).\\n` +\n ` Tip: if your eval previously worked, your package.json may be missing\\n` +\n ` \"type\": \"module\" — tsx loads .ts as CJS, putting named exports on\\n` +\n ` mod.default.<name>. The CLI handles that interop, but if you renamed\\n` +\n ` or removed the export the file path is your fix.`,\n );\n failedFiles++;\n continue;\n }\n\n // When --capture-traces is set, forward it to runEval so the runner\n // wraps each item's execution in a nested trackExecution({ captureTraces: true }).\n // This populates EvalItem.traces on both success (via tracked.traces)\n // and failure (via the axlCapturedTraces side-channel on the thrown\n // error). Nested trackExecution scopes walk the AsyncLocalStorage\n // parent chain, so the outer trackExecution above still observes\n // cost/metadata correctly.\n const runOptions = captureTraces ? { captureTraces: true } : undefined;\n\n if (runs > 1) {\n // Multi-run mode. Buffer per-run results locally so we can mark the\n // batch correctly before committing to outer `results[]`. The\n // original bug was the opposite: results pushed eagerly per-run, a\n // throw mid-batch left partial results posing as a complete run\n // (no `fromPartialBatch` marker, aggregate never ran). The fix ISN'T\n // to throw the partials away — those runs cost money and have\n // statistical signal. Instead we preserve them with explicit\n // partial-batch metadata, aggregate over what completed, and exit\n // non-zero so CI knows the batch wasn't clean.\n const { randomUUID } = await import('node:crypto');\n const runGroupId = randomUUID();\n const runResults: EvalResult[] = [];\n let runFailure: Error | undefined;\n\n for (let r = 0; r < runs; r++) {\n console.error(`[axl-eval] Run ${r + 1}/${runs}...`);\n try {\n const result = await runEval(evalConfig, executeWorkflow, runtime, runOptions);\n result.metadata.runGroupId = runGroupId;\n result.metadata.runIndex = r;\n runResults.push(result);\n } catch (err) {\n runFailure = err instanceof Error ? err : new Error(String(err));\n console.error(`[axl-eval] Run ${r + 1}/${runs} failed: ${runFailure.message}`);\n // Stop attempting further runs — we don't know whether this is\n // transient (rate limit) or permanent (auth failure), and\n // burning more API calls speculatively is hostile. Preserve\n // what completed.\n break;\n }\n }\n\n if (runResults.length === 0) {\n // Nothing completed — surface as a per-file failure. No partial\n // artifact to write; the outer try/catch error message would\n // duplicate the \"Run 1/N failed\" line we already printed, so\n // increment and continue without re-throwing.\n console.error(\n `[axl-eval] Aborting ${filePath}: no runs completed (${runFailure?.message ?? 'unknown failure'}).`,\n );\n failedFiles++;\n continue;\n }\n\n const partial = runResults.length < runs;\n if (partial) {\n // Mark every completed run so any consumer reading\n // `result.metadata` sees the partial-batch context. `aggregateRuns`\n // computes statistics over `runResults.length`, which is the\n // honest sample size to report.\n //\n // The flag is `fromPartialBatch` — a per-run marker meaning\n // \"this run came from a batch that did not complete.\" It is\n // NOT named `partialBatch` because that read as \"this run is\n // partial,\" and a defensive consumer wrote\n // `if (run.metadata.partialBatch) skipThisRun()`, throwing\n // away successful work that cost real money. The flag describes\n // the BATCH the run belongs to, not the run itself.\n //\n // `runFailure?.message` can be empty (e.g. `new Error('')` from a\n // misbehaving provider); fall back to `String(runFailure)` so the\n // banner never renders a blank \"Stopped after:\" line. Skip the\n // field entirely if both are empty so `buildMultiRunResult`'s\n // empty-string filter doesn't have to defensively guess.\n const failureMsg = runFailure\n ? runFailure.message || String(runFailure) || undefined\n : undefined;\n for (const r of runResults) {\n r.metadata.fromPartialBatch = true;\n r.metadata.batchCompleted = runResults.length;\n r.metadata.batchAttempted = runs;\n if (failureMsg) r.metadata.batchFailure = failureMsg;\n }\n console.error(\n `[axl-eval] PARTIAL: ${runResults.length} of ${runs} runs completed for ${filePath}.`,\n );\n failedFiles++;\n }\n\n const summary = aggregateRuns(runResults);\n console.log('\\n' + formatMultiRunTable(summary) + '\\n');\n for (const r of runResults) results.push(r);\n } else {\n const result = await runEval(evalConfig, executeWorkflow, runtime, runOptions);\n results.push(result);\n\n console.log('\\n' + formatTable(result) + '\\n');\n }\n } catch (err) {\n console.error(\n `Error running eval ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n );\n failedFiles++;\n }\n }\n\n if (outputPath && results.length > 0) {\n const output = results.length === 1 ? results[0] : results;\n const outputDir = path.dirname(path.resolve(outputPath));\n await mkdir(outputDir, { recursive: true });\n await writeFileAsync(outputPath, JSON.stringify(output, null, 2), 'utf-8');\n console.log(`Results saved to ${outputPath}`);\n }\n } finally {\n await runtime.shutdown().catch(() => {});\n }\n\n // Exit non-zero if any eval file failed to load/run. Previously we only\n // exited non-zero when zero evals succeeded, which silently masked\n // misconfigured files in mixed-success runs (a CI footgun).\n if (failedFiles > 0 || results.length === 0) {\n process.exit(1);\n }\n}\n\nmain().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n","/**\n * CLI utilities for `axl-eval`.\n *\n * The actual implementations of the loader, glob, and config-detection\n * helpers live in `@axlsdk/axl`'s `cli-internals` so a fix to (e.g.) the\n * tsx loader registration applies to both axl-eval and axl-studio\n * atomically. This file is now a thin re-export plus the symmetric\n * module-resolution helpers from `@axlsdk/axl`.\n */\n\nexport {\n resolveRuntime,\n pickDefault,\n pickExport,\n CONFIG_CANDIDATES,\n findConfig,\n needsTsxLoader,\n importModule,\n expandGlob,\n registerConditions,\n} from '@axlsdk/axl';\n","import type { EvalConfig } from './types.js';\n\n/**\n * Validate an eval config's required fields and produce a diagnostic string\n * if invalid. Returns `undefined` when the config passes.\n *\n * Returns a single-line message tail (caller prepends the file path) so the\n * full error reads like: `Error: <file> <message>`.\n *\n * Goes beyond a falsy check to:\n * - catch `scorers: []` which previously silently ran with no scorers\n * - reject scorers arrays that contain non-callable entries (e.g. typo\n * `scorers: [null, undefined]` would crash deep inside `runEval`)\n * - reject non-string `workflow` (downstream `runtime.getWorkflow(...)`\n * would silently miss it)\n * - reject non-object `dataset` (must be a `dataset()` factory result)\n * - provide a `Got: { keys: [...] }` hint so users can spot typos like\n * `scorerS` vs `scorers` immediately\n *\n * Lives in its own module so unit tests can import it without triggering\n * `cli.ts`'s `main()` at module load time.\n */\nexport function validateEvalConfig(cfg: unknown): string | undefined {\n if (!cfg || typeof cfg !== 'object') {\n return `does not export a valid eval config — got ${cfg === null ? 'null' : typeof cfg}.`;\n }\n const c = cfg as Partial<EvalConfig>;\n const missing: string[] = [];\n if (!c.workflow) missing.push('workflow');\n if (!c.dataset) missing.push('dataset');\n if (!c.scorers) missing.push('scorers');\n\n if (missing.length > 0) {\n const keys = Object.keys(c as object).slice(0, 10);\n const got = keys.length > 0 ? ` Got: { ${keys.join(', ')} }.` : '';\n return `does not export a valid eval config (missing ${missing.join(', ')}).${got}`;\n }\n\n if (typeof c.workflow !== 'string') {\n return `exports a non-string workflow (got ${typeof c.workflow}) — workflow must be the registered workflow name.`;\n }\n if (typeof c.dataset !== 'object' || Array.isArray(c.dataset)) {\n return `exports a non-object dataset (got ${Array.isArray(c.dataset) ? 'array' : typeof c.dataset}) — use the dataset() factory.`;\n }\n if (typeof (c.dataset as { getItems?: unknown }).getItems !== 'function') {\n return `exports a dataset without a getItems() method — use the dataset() factory.`;\n }\n if (!Array.isArray(c.scorers) || c.scorers.length === 0) {\n return `exports an empty scorers array — at least one scorer is required.`;\n }\n const badScorerIdx = c.scorers.findIndex(\n (s) => !s || typeof (s as { score?: unknown }).score !== 'function',\n );\n if (badScorerIdx !== -1) {\n return `exports a scorers array with a non-scorer entry at index ${badScorerIdx} — each scorer must have a score() method (use the scorer() factory).`;\n }\n return undefined;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/cli-utils.ts","../src/cli-validate.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readdirSync, statSync } from 'node:fs';\nimport { readFile as readFileAsync, writeFile as writeFileAsync, mkdir } from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { AxlRuntime, EvalExecuteWorkflow } from '@axlsdk/axl';\nimport { evalCompare } from './compare.js';\nimport { runEval } from './runner.js';\nimport { rescore } from './rescore.js';\nimport { aggregateRuns } from './multi-run.js';\nimport type { MultiRunSummary } from './multi-run.js';\nimport type { EvalConfig, EvalResult } from './types.js';\nimport {\n findConfig,\n resolveRuntime,\n importModule,\n registerConditions,\n pickDefault,\n pickExport,\n expandGlob,\n CONFIG_CANDIDATES,\n} from './cli-utils.js';\nimport { validateEvalConfig } from './cli-validate.js';\n\nconst KNOWN_FLAGS = new Set([\n '--output',\n '--config',\n '--conditions',\n '--fail-on-regression',\n '--threshold',\n '--runs',\n '--capture-traces',\n]);\n\n/** Install a SIGINT/SIGTERM handler that aborts an in-flight eval gracefully.\n * First signal: aborts the controller so runEval / rescore propagate cancellation\n * through ScorerContext.signal into in-flight provider.chat calls. The eval\n * unwinds normally and runtime.shutdown() runs in the `finally` block.\n * Second signal: hard exit — the user has signalled twice; cleanup is hung\n * or taking too long, so we abandon gracefulness rather than appear frozen. */\nfunction installAbortHandler(controller: AbortController): void {\n let signalled = false;\n const onSignal = (sig: NodeJS.Signals) => {\n if (signalled) {\n console.error(`\\n[axl-eval] Second ${sig} — forcing exit.`);\n process.exit(130);\n }\n signalled = true;\n console.error(`\\n[axl-eval] ${sig} received — cancelling eval (press again to force exit)...`);\n controller.abort();\n };\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n}\n\nasync function main() {\n const args = process.argv.slice(2);\n\n if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {\n console.log(`\nUsage:\n axl-eval <path> Run eval file(s)\n axl-eval <path> --runs <n> Run eval N times (multi-run)\n axl-eval <path> --output <file> Save results to JSON\n axl-eval <path> --config <file> Use config file for runtime\n axl-eval <path> --conditions <list> Node.js import conditions (comma-separated)\n axl-eval <path> --capture-traces Populate EvalItem.traces on every item\n (success + failure). Adds memory\n overhead proportional to dataset size\n x turns x agents; off by default.\n axl-eval rescore <results> <eval-file> Re-run scorers on saved outputs\n axl-eval compare <a> <b> Compare two eval result files\n axl-eval compare <a> <b> --threshold <v> Set regression threshold (global or per-scorer)\n axl-eval compare <a> <b> --fail-on-regression Exit 1 if regressions\n\nConfig auto-detection (when --config is not specified):\n ${CONFIG_CANDIDATES.join(' -> ')}\n\nWhen a config is found, the exported AxlRuntime is passed to executeWorkflow\nand cost is tracked automatically via runtime.trackCost().\nWhen no config is found, a bare AxlRuntime is created (providers from env vars).\n`);\n process.exit(0);\n }\n\n if (args[0] === 'compare') {\n // `compare` is pure computation — no LLM calls, no AbortSignal plumbing needed.\n await runCompare(args.slice(1));\n return;\n }\n\n // SIGINT/SIGTERM aborts in-flight LLM calls (eval + rescore) instead of leaving\n // the process to hard-exit mid-request, which would skip runtime.shutdown() and\n // leak streaming-buffer state.\n const controller = new AbortController();\n installAbortHandler(controller);\n\n if (args[0] === 'rescore') {\n await runRescore(args.slice(1), controller.signal);\n return;\n }\n\n await runEvalCommand(args, controller.signal);\n}\n\nfunction parseThresholdArg(args: string[]): Record<string, number> | number | undefined {\n const idx = args.indexOf('--threshold');\n if (idx === -1 || idx + 1 >= args.length) return undefined;\n const value = args[idx + 1];\n\n // Global numeric threshold: --threshold 0.05\n if (/^[\\d.]+$/.test(value)) return parseFloat(value);\n\n // Per-scorer map: --threshold accuracy=0,tone=0.1\n const map: Record<string, number> = {};\n for (const pair of value.split(',')) {\n const [key, val] = pair.split('=');\n if (key && val != null) map[key.trim()] = parseFloat(val.trim());\n }\n return Object.keys(map).length > 0 ? map : undefined;\n}\n\nasync function runCompare(args: string[]) {\n const failOnRegression = args.includes('--fail-on-regression');\n const thresholds = parseThresholdArg(args);\n const files = args.filter(\n (a, i) => !a.startsWith('--') && !(i > 0 && args[i - 1] === '--threshold'),\n );\n\n if (files.length !== 2) {\n console.error('Usage: axl-eval compare <baseline.json> <candidate.json> [--threshold <value>]');\n process.exit(1);\n }\n\n const baselineRaw = JSON.parse(await readFileAsync(files[0], 'utf-8'));\n const candidateRaw = JSON.parse(await readFileAsync(files[1], 'utf-8'));\n const baseline: EvalResult | EvalResult[] = baselineRaw;\n const candidate: EvalResult | EvalResult[] = candidateRaw;\n const compareOptions = thresholds != null ? { thresholds } : undefined;\n const comparison = evalCompare(baseline, candidate, compareOptions);\n\n console.log(\n `\\nCompare: baseline (${comparison.baseline.id.slice(0, 8)}) -> candidate (${comparison.candidate.id.slice(0, 8)})\\n`,\n );\n\n const scorerNames = Object.keys(comparison.scorers);\n const maxNameLen = Math.max(...scorerNames.map((n) => n.length), 6);\n const hasCI = scorerNames.some((n) => comparison.scorers[n].ci != null);\n\n const ciHeader = hasCI ? ' CI 95% Sig' : '';\n const ciRule = hasCI ? ' ---------------- ---' : '';\n console.log(` ${'Scorer'.padEnd(maxNameLen)} Baseline Candidate Delta Change${ciHeader}`);\n console.log(` ${''.padEnd(maxNameLen, '-')} -------- --------- -------- ------${ciRule}`);\n\n for (const name of scorerNames) {\n const s = comparison.scorers[name];\n const sign = s.delta > 0 ? '+' : '';\n let line = ` ${name.padEnd(maxNameLen)} ${s.baselineMean.toFixed(3).padStart(8)} ${s.candidateMean.toFixed(3).padStart(9)} ${(sign + s.delta.toFixed(3)).padStart(8)} ${(sign + s.deltaPercent.toFixed(1) + '%').padStart(6)}`;\n if (hasCI) {\n if (s.ci) {\n const lo = (s.ci.lower >= 0 ? '+' : '') + s.ci.lower.toFixed(4);\n const hi = (s.ci.upper >= 0 ? '+' : '') + s.ci.upper.toFixed(4);\n const sig = s.significant ? ' *' : ' ';\n line += ` [${lo}, ${hi}]${sig}`;\n } else {\n line += ' —'.padEnd(22);\n }\n }\n console.log(line);\n }\n\n if (comparison.timing) {\n const t = comparison.timing;\n const sign = t.delta > 0 ? '+' : '';\n console.log(\n `\\n Timing: baseline ${(t.baselineMean / 1000).toFixed(2)}s -> candidate ${(t.candidateMean / 1000).toFixed(2)}s (${sign}${t.deltaPercent.toFixed(1)}%)`,\n );\n }\n if (comparison.cost) {\n const c = comparison.cost;\n const sign = c.delta > 0 ? '+' : '';\n console.log(\n ` Cost: baseline $${c.baselineTotal.toFixed(2)} -> candidate $${c.candidateTotal.toFixed(2)} (${sign}${c.deltaPercent.toFixed(1)}%)`,\n );\n }\n\n const baselineRef = Array.isArray(baseline) ? baseline[0] : baseline;\n const stable = Math.max(\n 0,\n baselineRef.items.length - comparison.regressions.length - comparison.improvements.length,\n );\n console.log(\n `\\n Regressions: ${comparison.regressions.length} | Improvements: ${comparison.improvements.length} | Stable: ${stable}\\n`,\n );\n\n if (failOnRegression && comparison.regressions.length > 0) {\n // When CI is available, only fail on significant regressions\n const hasSignificance = scorerNames.some((n) => comparison.scorers[n].significant != null);\n if (hasSignificance) {\n const hasSignificantRegression = scorerNames.some(\n (n) => comparison.scorers[n].significant === true && comparison.scorers[n].delta < 0,\n );\n if (hasSignificantRegression) process.exit(1);\n } else {\n process.exit(1);\n }\n }\n}\n\nasync function runRescore(args: string[], signal: AbortSignal) {\n const { outputPath, configArg, conditions, paths } = parseEvalArgs(args);\n\n if (paths.length < 2) {\n console.error('Usage: axl-eval rescore <results.json> <eval-file> [--output <file>]');\n process.exit(1);\n }\n\n const [resultsPath, evalFilePath] = paths;\n const raw = JSON.parse(await readFileAsync(resultsPath, 'utf-8'));\n const results: EvalResult[] = Array.isArray(raw) ? raw : [raw];\n\n const runtime = await getRuntime(configArg, conditions);\n try {\n const mod = await importModule(path.resolve(evalFilePath), import.meta.url);\n const evalConfig = pickDefault<EvalConfig>(mod);\n\n if (!evalConfig || typeof evalConfig !== 'object') {\n console.error(\n `Error: ${evalFilePath} does not export an eval config object — got ${evalConfig === null ? 'null' : typeof evalConfig}.`,\n );\n process.exit(1);\n }\n if (!Array.isArray(evalConfig.scorers) || evalConfig.scorers.length === 0) {\n console.error(`Error: ${evalFilePath} does not export a non-empty scorers array.`);\n process.exit(1);\n }\n\n const rescored: EvalResult[] = [];\n for (const resultData of results) {\n if (signal.aborted) break;\n rescored.push(await rescore(resultData, evalConfig.scorers, runtime, { signal }));\n }\n\n for (const r of rescored) {\n console.log('\\n' + formatTable(r) + '\\n');\n }\n\n if (outputPath) {\n const output = Array.isArray(raw) ? rescored : rescored[0];\n const outputDir = path.dirname(path.resolve(outputPath));\n await mkdir(outputDir, { recursive: true });\n await writeFileAsync(outputPath, JSON.stringify(output, null, 2), 'utf-8');\n console.log(`Rescored results saved to ${outputPath}`);\n }\n } finally {\n await runtime.shutdown().catch(() => {});\n }\n}\n\n/**\n * Resolve a CLI path argument into a list of eval files.\n *\n * Accepts:\n * - An explicit file path (`path/to/foo.eval.ts`)\n * - A directory (lists `*.eval.[mc]?[jt]sx?` inside, non-recursive)\n * - A glob pattern: `evals/*.eval.ts`, `evals/**\\/*.eval.ts`, `**\\/*.eval.ts`\n *\n * Glob expansion mirrors the studio eval-loader's so users get the same\n * behavior in both places. Without it, users running on Windows or with\n * quoted patterns hit confusing \"file not found\" errors when the shell\n * couldn't expand the glob.\n */\nfunction collectEvalFiles(p: string): string[] {\n if (p.includes('*')) return expandGlob(p, process.cwd());\n const resolved = path.resolve(p);\n try {\n const stat = statSync(resolved);\n if (stat.isDirectory()) {\n const entries = readdirSync(resolved);\n return entries\n .filter((e) => /\\.eval\\.[mc]?[jt]sx?$/.test(e))\n .map((e) => path.join(resolved, e));\n }\n return [resolved];\n } catch {\n return [resolved];\n }\n}\n\n/** Render observed workflows for a terse header line. Multiple → comma-separated. */\nfunction formatWorkflows(workflows: unknown): string {\n if (!Array.isArray(workflows) || workflows.length === 0) return '(unknown)';\n return (workflows as unknown[]).filter((w): w is string => typeof w === 'string').join(', ');\n}\n\nfunction formatTable(result: EvalResult): string {\n const lines: string[] = [];\n const scorerNames = Object.keys(result.summary.scorers);\n const maxNameLen = Math.max(...scorerNames.map((n) => n.length), 'Scorer'.length);\n const colWidth = 8;\n\n lines.push(\n `Eval: ${formatWorkflows(result.metadata.workflows)} x ${result.dataset} (${result.summary.count} items)`,\n );\n lines.push(\n ` ${'Scorer'.padEnd(maxNameLen)} ${'Mean'.padStart(colWidth)} ${'Min'.padStart(colWidth)} ${'Max'.padStart(colWidth)} ${'p50'.padStart(colWidth)} ${'p95'.padStart(colWidth)}`,\n );\n\n const ruleLen = maxNameLen + 2 + (colWidth + 2) * 5;\n lines.push(' ' + '\\u2500'.repeat(ruleLen));\n\n for (const name of scorerNames) {\n const s = result.summary.scorers[name];\n // Detect scorers with no valid scores (all items errored → computeStats([]) → all zeros)\n const validScoreCount = result.items.filter((i) => !i.error && i.scores[name] != null).length;\n if (validScoreCount === 0) {\n lines.push(\n ` ${name.padEnd(maxNameLen)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)}`,\n );\n } else {\n lines.push(\n ` ${name.padEnd(maxNameLen)} ${s.mean.toFixed(2).padStart(colWidth)} ${s.min.toFixed(2).padStart(colWidth)} ${s.max.toFixed(2).padStart(colWidth)} ${s.p50.toFixed(2).padStart(colWidth)} ${s.p95.toFixed(2).padStart(colWidth)}`,\n );\n }\n }\n\n if (result.summary.timing) {\n const t = result.summary.timing;\n lines.push(\n ` ${'Timing'.padEnd(maxNameLen)} ${(t.mean / 1000).toFixed(2).padStart(colWidth)}s ${(t.p50 / 1000).toFixed(2).padStart(colWidth)}s ${(t.p95 / 1000).toFixed(2).padStart(colWidth)}s`,\n );\n }\n\n const durationSec = (result.duration / 1000).toFixed(1);\n const costStr = result.totalCost > 0 ? `$${result.totalCost.toFixed(2)}` : '$0.00';\n lines.push('');\n lines.push(\n ` Failures: ${result.summary.failures}/${result.summary.count} | Cost: ${costStr} | Duration: ${durationSec}s`,\n );\n\n const itemsWithErrors = result.items.filter((i) => i.scorerErrors?.length);\n if (itemsWithErrors.length > 0) {\n const uniqueErrors = [...new Set(itemsWithErrors.flatMap((i) => i.scorerErrors!))];\n lines.push('');\n lines.push(\n ` Scorer errors (${itemsWithErrors.length}/${result.summary.count} items affected):`,\n );\n for (const err of uniqueErrors.slice(0, 5)) {\n lines.push(` - ${err}`);\n }\n if (uniqueErrors.length > 5) {\n lines.push(` ... and ${uniqueErrors.length - 5} more`);\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction formatMultiRunTable(summary: MultiRunSummary): string {\n const lines: string[] = [];\n const scorerNames = Object.keys(summary.scorers);\n const maxNameLen = Math.max(...scorerNames.map((n) => n.length), 'Scorer'.length);\n const colWidth = 16;\n\n lines.push(\n `Eval: ${formatWorkflows(summary.workflows)} x ${summary.dataset} \\u2014 ${summary.runCount} runs`,\n );\n lines.push(\n ` ${'Scorer'.padEnd(maxNameLen)} ${'Mean \\u00b1 Std'.padStart(colWidth)} ${'Min'.padStart(8)} ${'Max'.padStart(8)}`,\n );\n const ruleLen = maxNameLen + 2 + colWidth + 2 + 8 + 2 + 8;\n lines.push(' ' + '\\u2500'.repeat(ruleLen));\n\n for (const name of scorerNames) {\n const s = summary.scorers[name];\n const meanStd = `${s.mean.toFixed(3)} \\u00b1 ${s.std.toFixed(3)}`;\n lines.push(\n ` ${name.padEnd(maxNameLen)} ${meanStd.padStart(colWidth)} ${s.min.toFixed(3).padStart(8)} ${s.max.toFixed(3).padStart(8)}`,\n );\n }\n\n if (summary.timing) {\n lines.push(\n ` ${'Timing'.padEnd(maxNameLen)} ${((summary.timing.mean / 1000).toFixed(2) + ' \\u00b1 ' + (summary.timing.std / 1000).toFixed(2) + 's').padStart(colWidth)}`,\n );\n }\n\n const costStr = summary.totalCost > 0 ? `$${summary.totalCost.toFixed(2)}` : '$0.00';\n const durationStr = (summary.totalDuration / 1000).toFixed(1);\n lines.push('');\n lines.push(` Total Cost: ${costStr} | Total Duration: ${durationStr}s`);\n\n return lines.join('\\n');\n}\n\n// ── Runtime resolution ─────────────────────────────────────────────\n\nasync function resolveRuntimeFromConfig(configPath: string): Promise<AxlRuntime> {\n try {\n const mod = await importModule(configPath, import.meta.url);\n const runtime = resolveRuntime(mod) as AxlRuntime;\n\n if (!runtime || typeof runtime.execute !== 'function') {\n console.error(`Config must export a default AxlRuntime instance.`);\n if (runtime) {\n const keys = Object.keys(runtime as object)\n .slice(0, 5)\n .join(', ');\n console.error(` Got: ${typeof runtime}${keys ? ` with keys: { ${keys} }` : ''}`);\n }\n console.error(\n `Example:\\n import { AxlRuntime } from '@axlsdk/axl';\\n export default new AxlRuntime({ ... });`,\n );\n process.exit(1);\n }\n\n return runtime;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (\n /Cannot use import statement|Unexpected reserved word|top-level await|exports is not defined/.test(\n msg,\n )\n ) {\n const ext = path.extname(configPath);\n console.error(`[axl-eval] Config failed to load due to a CJS/ESM compatibility issue.`);\n if (ext === '.ts' || ext === '.tsx') {\n console.error(\n ` Tip: try renaming to .mts to force ESM format, or ensure tsx is installed and up to date.`,\n );\n } else {\n console.error(` Tip: add \"type\": \"module\" to your package.json.`);\n }\n console.error();\n }\n console.error(`Failed to load config:`, err);\n process.exit(1);\n }\n}\n\nasync function getRuntime(configArg?: string, conditions?: string[]): Promise<AxlRuntime> {\n // Register import conditions before any config loading\n if (conditions && conditions.length > 0) {\n await registerConditions(conditions);\n }\n\n // 1. Explicit --config\n if (configArg) {\n const configPath = path.resolve(process.cwd(), configArg);\n const stat = statSync(configPath, { throwIfNoEntry: false });\n if (!stat?.isFile()) {\n console.error(`Config file not found: ${configPath}`);\n process.exit(1);\n }\n console.error(`[axl-eval] Loading config from ${configPath}`);\n return resolveRuntimeFromConfig(configPath);\n }\n\n // 2. Auto-detect\n const found = findConfig(process.cwd());\n if (found) {\n console.error(`[axl-eval] Auto-detected config: ${found}`);\n return resolveRuntimeFromConfig(found);\n }\n\n // 3. Bare runtime (providers from env vars)\n const { AxlRuntime } = await import('@axlsdk/axl');\n return new AxlRuntime();\n}\n\n// ── Arg parsing ────────────────────────────────────────────────────\n\nfunction parseEvalArgs(args: string[]): {\n outputPath?: string;\n configArg?: string;\n conditions: string[];\n runs: number;\n captureTraces: boolean;\n paths: string[];\n} {\n let outputPath: string | undefined;\n let configArg: string | undefined;\n let conditions: string[] = [];\n let runs = 1;\n let captureTraces = false;\n const paths: string[] = [];\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === '--output' || arg === '--config' || arg === '--conditions' || arg === '--runs') {\n if (i + 1 >= args.length) {\n console.error(`Error: ${arg} requires a value`);\n process.exit(1);\n }\n const value = args[++i];\n if (arg === '--output') outputPath = value;\n else if (arg === '--config') configArg = value;\n else if (arg === '--runs') runs = Math.max(1, parseInt(value, 10) || 1);\n else\n conditions = value\n .split(',')\n .map((c) => c.trim())\n .filter(Boolean);\n } else if (arg === '--capture-traces') {\n // Boolean flag — no value consumed.\n captureTraces = true;\n } else if (arg.startsWith('--')) {\n if (!KNOWN_FLAGS.has(arg)) {\n console.error(`Unknown flag: ${arg}`);\n process.exit(1);\n }\n } else {\n paths.push(arg);\n }\n }\n\n return { outputPath, configArg, conditions, runs, captureTraces, paths };\n}\n\n// ── Main eval command ──────────────────────────────────────────────\n\nasync function runEvalCommand(args: string[], signal: AbortSignal) {\n const { outputPath, configArg, conditions, runs, captureTraces, paths } = parseEvalArgs(args);\n\n if (paths.length === 0) {\n console.error('Error: No eval file path provided');\n process.exit(1);\n }\n\n const evalFiles: string[] = [];\n for (const p of paths) {\n evalFiles.push(...collectEvalFiles(p));\n }\n\n if (evalFiles.length === 0) {\n console.error('Error: No eval files found');\n process.exit(1);\n }\n\n const runtime = await getRuntime(configArg, conditions);\n const results: EvalResult[] = [];\n let failedFiles = 0;\n\n try {\n for (const filePath of evalFiles) {\n // Short-circuit if the user aborted between eval files. The in-flight eval\n // unwinds on its own via runEval({ signal }); this prevents starting the next one.\n if (signal.aborted) break;\n try {\n const mod = await importModule(path.resolve(filePath), import.meta.url);\n const evalConfig = pickDefault<EvalConfig>(mod);\n\n const validationError = validateEvalConfig(evalConfig);\n if (validationError) {\n console.error(`Error: ${filePath} ${validationError}`);\n failedFiles++;\n continue;\n }\n\n // Resolve executeWorkflow: custom export > registered workflow > error\n // Walk the ESM/CJS interop chain symmetrically with the default export\n // so named exports stay visible when tsx loads the eval module as CJS.\n const exported = pickExport<unknown>(mod, 'executeWorkflow');\n\n // Validate that the export, if present, is callable. Catches the\n // `export const executeWorkflow = 'foo'` typo at the boundary instead\n // of crashing deep inside trackExecution with a confusing stack.\n let customExecute: EvalExecuteWorkflow | undefined;\n if (typeof exported === 'function') {\n customExecute = exported as EvalExecuteWorkflow;\n } else if (exported !== undefined) {\n console.error(\n `[axl-eval] Error: ${filePath} exports executeWorkflow but it is ${typeof exported}, not a function.`,\n );\n failedFiles++;\n continue;\n }\n\n let executeWorkflow: EvalExecuteWorkflow;\n\n if (customExecute) {\n // Wrap custom executeWorkflow with trackExecution for cost + metadata attribution\n executeWorkflow = async (input, rt) => {\n const {\n result,\n cost: trackedCost,\n metadata,\n } = await runtime.trackExecution(async () => {\n return customExecute(input, rt);\n });\n return {\n output: result.output,\n cost: result.cost ?? trackedCost,\n metadata: result.metadata ?? metadata,\n };\n };\n } else if (runtime.getWorkflow(evalConfig.workflow)) {\n // No executeWorkflow exported but workflow is registered — use runtime.execute()\n executeWorkflow = async (input) => {\n const { result, cost, metadata } = await runtime.trackExecution(async () => {\n return runtime.execute(evalConfig.workflow, input);\n });\n return { output: result, cost, metadata };\n };\n } else {\n // Fail loudly. The previous identity-passthrough fallback silently\n // produced all-zero scores in CI — exactly the kind of footgun the\n // \"fail loudly, not silently\" rule is meant to prevent. If you\n // genuinely want identity, export it explicitly:\n // export const executeWorkflow = async (input) => ({ output: input });\n //\n // Surface what WAS exported (top-level + .default) so users\n // recognize a typo like `execute_workflow` and can spot the\n // CJS-interop case that motivates this whole code path: when tsx\n // loads a `.ts` file as CJS, all named exports land on\n // `mod.default.<name>`. The chain walk above already handled this,\n // but a user who removed `executeWorkflow` will see exactly what\n // export names ARE present.\n const exportShape = (() => {\n const top = Object.keys(mod).filter((k) => k !== 'default');\n const fromDefault =\n mod.default && typeof mod.default === 'object'\n ? Object.keys(mod.default as Record<string, unknown>)\n : [];\n const all = [...new Set([...top, ...fromDefault])];\n return all.length > 0 ? `Found exports: [${all.join(', ')}].` : '';\n })();\n console.error(\n `[axl-eval] Error: ${filePath} does not export an executeWorkflow function ` +\n `and no workflow named \"${evalConfig.workflow}\" is registered on the runtime.\\n` +\n (exportShape ? ` ${exportShape}\\n` : '') +\n ` Add either:\\n` +\n ` export async function executeWorkflow(input, runtime) { ... }\\n` +\n ` or register the workflow on your runtime via runtime.registerWorkflow(workflow).\\n` +\n ` Tip: if your eval previously worked, your package.json may be missing\\n` +\n ` \"type\": \"module\" — tsx loads .ts as CJS, putting named exports on\\n` +\n ` mod.default.<name>. The CLI handles that interop, but if you renamed\\n` +\n ` or removed the export the file path is your fix.`,\n );\n failedFiles++;\n continue;\n }\n\n // When --capture-traces is set, forward it to runEval so the runner\n // wraps each item's execution in a nested trackExecution({ captureTraces: true }).\n // This populates EvalItem.traces on both success (via tracked.traces)\n // and failure (via the axlCapturedTraces side-channel on the thrown\n // error). Nested trackExecution scopes walk the AsyncLocalStorage\n // parent chain, so the outer trackExecution above still observes\n // cost/metadata correctly.\n // Always pass the SIGINT-driven signal so Ctrl+C aborts in-flight\n // workflows + scorer LLM calls instead of dropping the connection mid-request.\n const runOptions = { signal, ...(captureTraces ? { captureTraces: true } : {}) };\n\n if (runs > 1) {\n // Multi-run mode. Buffer per-run results locally so we can mark the\n // batch correctly before committing to outer `results[]`. The\n // original bug was the opposite: results pushed eagerly per-run, a\n // throw mid-batch left partial results posing as a complete run\n // (no `fromPartialBatch` marker, aggregate never ran). The fix ISN'T\n // to throw the partials away — those runs cost money and have\n // statistical signal. Instead we preserve them with explicit\n // partial-batch metadata, aggregate over what completed, and exit\n // non-zero so CI knows the batch wasn't clean.\n const { randomUUID } = await import('node:crypto');\n const runGroupId = randomUUID();\n const runResults: EvalResult[] = [];\n let runFailure: Error | undefined;\n\n for (let r = 0; r < runs; r++) {\n if (signal.aborted) break;\n console.error(`[axl-eval] Run ${r + 1}/${runs}...`);\n try {\n const result = await runEval(evalConfig, executeWorkflow, runtime, runOptions);\n result.metadata.runGroupId = runGroupId;\n result.metadata.runIndex = r;\n runResults.push(result);\n } catch (err) {\n runFailure = err instanceof Error ? err : new Error(String(err));\n console.error(`[axl-eval] Run ${r + 1}/${runs} failed: ${runFailure.message}`);\n // Stop attempting further runs — we don't know whether this is\n // transient (rate limit) or permanent (auth failure), and\n // burning more API calls speculatively is hostile. Preserve\n // what completed.\n break;\n }\n }\n\n if (runResults.length === 0) {\n // Nothing completed — surface as a per-file failure. No partial\n // artifact to write; the outer try/catch error message would\n // duplicate the \"Run 1/N failed\" line we already printed, so\n // increment and continue without re-throwing.\n console.error(\n `[axl-eval] Aborting ${filePath}: no runs completed (${runFailure?.message ?? 'unknown failure'}).`,\n );\n failedFiles++;\n continue;\n }\n\n const partial = runResults.length < runs;\n if (partial) {\n // Mark every completed run so any consumer reading\n // `result.metadata` sees the partial-batch context. `aggregateRuns`\n // computes statistics over `runResults.length`, which is the\n // honest sample size to report.\n //\n // The flag is `fromPartialBatch` — a per-run marker meaning\n // \"this run came from a batch that did not complete.\" It is\n // NOT named `partialBatch` because that read as \"this run is\n // partial,\" and a defensive consumer wrote\n // `if (run.metadata.partialBatch) skipThisRun()`, throwing\n // away successful work that cost real money. The flag describes\n // the BATCH the run belongs to, not the run itself.\n //\n // `runFailure?.message` can be empty (e.g. `new Error('')` from a\n // misbehaving provider); fall back to `String(runFailure)` so the\n // banner never renders a blank \"Stopped after:\" line. Skip the\n // field entirely if both are empty so `buildMultiRunResult`'s\n // empty-string filter doesn't have to defensively guess.\n const failureMsg = runFailure\n ? runFailure.message || String(runFailure) || undefined\n : undefined;\n for (const r of runResults) {\n r.metadata.fromPartialBatch = true;\n r.metadata.batchCompleted = runResults.length;\n r.metadata.batchAttempted = runs;\n if (failureMsg) r.metadata.batchFailure = failureMsg;\n }\n console.error(\n `[axl-eval] PARTIAL: ${runResults.length} of ${runs} runs completed for ${filePath}.`,\n );\n failedFiles++;\n }\n\n const summary = aggregateRuns(runResults);\n console.log('\\n' + formatMultiRunTable(summary) + '\\n');\n for (const r of runResults) results.push(r);\n } else {\n const result = await runEval(evalConfig, executeWorkflow, runtime, runOptions);\n results.push(result);\n\n console.log('\\n' + formatTable(result) + '\\n');\n }\n } catch (err) {\n console.error(\n `Error running eval ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n );\n failedFiles++;\n }\n }\n\n if (outputPath && results.length > 0) {\n const output = results.length === 1 ? results[0] : results;\n const outputDir = path.dirname(path.resolve(outputPath));\n await mkdir(outputDir, { recursive: true });\n await writeFileAsync(outputPath, JSON.stringify(output, null, 2), 'utf-8');\n console.log(`Results saved to ${outputPath}`);\n }\n } finally {\n await runtime.shutdown().catch(() => {});\n }\n\n // Exit non-zero if any eval file failed to load/run. Previously we only\n // exited non-zero when zero evals succeeded, which silently masked\n // misconfigured files in mixed-success runs (a CI footgun).\n if (failedFiles > 0 || results.length === 0) {\n process.exit(1);\n }\n}\n\nmain().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n","/**\n * CLI utilities for `axl-eval`.\n *\n * The actual implementations of the loader, glob, and config-detection\n * helpers live in `@axlsdk/axl`'s `cli-internals` so a fix to (e.g.) the\n * tsx loader registration applies to both axl-eval and axl-studio\n * atomically. This file is now a thin re-export plus the symmetric\n * module-resolution helpers from `@axlsdk/axl`.\n */\n\nexport {\n resolveRuntime,\n pickDefault,\n pickExport,\n CONFIG_CANDIDATES,\n findConfig,\n needsTsxLoader,\n importModule,\n expandGlob,\n registerConditions,\n} from '@axlsdk/axl';\n","import type { EvalConfig } from './types.js';\n\n/**\n * Validate an eval config's required fields and produce a diagnostic string\n * if invalid. Returns `undefined` when the config passes.\n *\n * Returns a single-line message tail (caller prepends the file path) so the\n * full error reads like: `Error: <file> <message>`.\n *\n * Goes beyond a falsy check to:\n * - catch `scorers: []` which previously silently ran with no scorers\n * - reject scorers arrays that contain non-callable entries (e.g. typo\n * `scorers: [null, undefined]` would crash deep inside `runEval`)\n * - reject non-string `workflow` (downstream `runtime.getWorkflow(...)`\n * would silently miss it)\n * - reject non-object `dataset` (must be a `dataset()` factory result)\n * - provide a `Got: { keys: [...] }` hint so users can spot typos like\n * `scorerS` vs `scorers` immediately\n *\n * Lives in its own module so unit tests can import it without triggering\n * `cli.ts`'s `main()` at module load time.\n */\nexport function validateEvalConfig(cfg: unknown): string | undefined {\n if (!cfg || typeof cfg !== 'object') {\n return `does not export a valid eval config — got ${cfg === null ? 'null' : typeof cfg}.`;\n }\n const c = cfg as Partial<EvalConfig>;\n const missing: string[] = [];\n if (!c.workflow) missing.push('workflow');\n if (!c.dataset) missing.push('dataset');\n if (!c.scorers) missing.push('scorers');\n\n if (missing.length > 0) {\n const keys = Object.keys(c as object).slice(0, 10);\n const got = keys.length > 0 ? ` Got: { ${keys.join(', ')} }.` : '';\n return `does not export a valid eval config (missing ${missing.join(', ')}).${got}`;\n }\n\n if (typeof c.workflow !== 'string') {\n return `exports a non-string workflow (got ${typeof c.workflow}) — workflow must be the registered workflow name.`;\n }\n if (typeof c.dataset !== 'object' || Array.isArray(c.dataset)) {\n return `exports a non-object dataset (got ${Array.isArray(c.dataset) ? 'array' : typeof c.dataset}) — use the dataset() factory.`;\n }\n if (typeof (c.dataset as { getItems?: unknown }).getItems !== 'function') {\n return `exports a dataset without a getItems() method — use the dataset() factory.`;\n }\n if (!Array.isArray(c.scorers) || c.scorers.length === 0) {\n return `exports an empty scorers array — at least one scorer is required.`;\n }\n const badScorerIdx = c.scorers.findIndex(\n (s) => !s || typeof (s as { score?: unknown }).score !== 'function',\n );\n if (badScorerIdx !== -1) {\n return `exports a scorers array with a non-scorer entry at index ${badScorerIdx} — each scorer must have a score() method (use the scorer() factory).`;\n }\n return undefined;\n}\n"],"mappings":";;;;;;;;;AAEA,SAAS,aAAa,gBAAgB;AACtC,SAAS,YAAY,eAAe,aAAa,gBAAgB,aAAa;AAC9E,YAAY,UAAU;;;ACMtB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACEA,SAAS,mBAAmB,KAAkC;AACnE,MAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,WAAO,kDAA6C,QAAQ,OAAO,SAAS,OAAO,GAAG;AAAA,EACxF;AACA,QAAM,IAAI;AACV,QAAM,UAAoB,CAAC;AAC3B,MAAI,CAAC,EAAE,SAAU,SAAQ,KAAK,UAAU;AACxC,MAAI,CAAC,EAAE,QAAS,SAAQ,KAAK,SAAS;AACtC,MAAI,CAAC,EAAE,QAAS,SAAQ,KAAK,SAAS;AAEtC,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,OAAO,OAAO,KAAK,CAAW,EAAE,MAAM,GAAG,EAAE;AACjD,UAAM,MAAM,KAAK,SAAS,IAAI,WAAW,KAAK,KAAK,IAAI,CAAC,QAAQ;AAChE,WAAO,gDAAgD,QAAQ,KAAK,IAAI,CAAC,KAAK,GAAG;AAAA,EACnF;AAEA,MAAI,OAAO,EAAE,aAAa,UAAU;AAClC,WAAO,sCAAsC,OAAO,EAAE,QAAQ;AAAA,EAChE;AACA,MAAI,OAAO,EAAE,YAAY,YAAY,MAAM,QAAQ,EAAE,OAAO,GAAG;AAC7D,WAAO,qCAAqC,MAAM,QAAQ,EAAE,OAAO,IAAI,UAAU,OAAO,EAAE,OAAO;AAAA,EACnG;AACA,MAAI,OAAQ,EAAE,QAAmC,aAAa,YAAY;AACxE,WAAO;AAAA,EACT;AACA,MAAI,CAAC,MAAM,QAAQ,EAAE,OAAO,KAAK,EAAE,QAAQ,WAAW,GAAG;AACvD,WAAO;AAAA,EACT;AACA,QAAM,eAAe,EAAE,QAAQ;AAAA,IAC7B,CAAC,MAAM,CAAC,KAAK,OAAQ,EAA0B,UAAU;AAAA,EAC3D;AACA,MAAI,iBAAiB,IAAI;AACvB,WAAO,4DAA4D,YAAY;AAAA,EACjF;AACA,SAAO;AACT;;;AFjCA,IAAM,cAAc,oBAAI,IAAI;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAQD,SAAS,oBAAoB,YAAmC;AAC9D,MAAI,YAAY;AAChB,QAAM,WAAW,CAAC,QAAwB;AACxC,QAAI,WAAW;AACb,cAAQ,MAAM;AAAA,oBAAuB,GAAG,uBAAkB;AAC1D,cAAQ,KAAK,GAAG;AAAA,IAClB;AACA,gBAAY;AACZ,YAAQ,MAAM;AAAA,aAAgB,GAAG,iEAA4D;AAC7F,eAAW,MAAM;AAAA,EACnB;AACA,UAAQ,GAAG,UAAU,QAAQ;AAC7B,UAAQ,GAAG,WAAW,QAAQ;AAChC;AAEA,eAAe,OAAO;AACpB,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AAEjC,MAAI,KAAK,WAAW,KAAK,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,MAAM,MAAM;AACjE,YAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAiBZ,kBAAkB,KAAK,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,CAKjC;AACG,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,KAAK,CAAC,MAAM,WAAW;AAEzB,UAAM,WAAW,KAAK,MAAM,CAAC,CAAC;AAC9B;AAAA,EACF;AAKA,QAAM,aAAa,IAAI,gBAAgB;AACvC,sBAAoB,UAAU;AAE9B,MAAI,KAAK,CAAC,MAAM,WAAW;AACzB,UAAM,WAAW,KAAK,MAAM,CAAC,GAAG,WAAW,MAAM;AACjD;AAAA,EACF;AAEA,QAAM,eAAe,MAAM,WAAW,MAAM;AAC9C;AAEA,SAAS,kBAAkB,MAA6D;AACtF,QAAM,MAAM,KAAK,QAAQ,aAAa;AACtC,MAAI,QAAQ,MAAM,MAAM,KAAK,KAAK,OAAQ,QAAO;AACjD,QAAM,QAAQ,KAAK,MAAM,CAAC;AAG1B,MAAI,WAAW,KAAK,KAAK,EAAG,QAAO,WAAW,KAAK;AAGnD,QAAM,MAA8B,CAAC;AACrC,aAAW,QAAQ,MAAM,MAAM,GAAG,GAAG;AACnC,UAAM,CAAC,KAAK,GAAG,IAAI,KAAK,MAAM,GAAG;AACjC,QAAI,OAAO,OAAO,KAAM,KAAI,IAAI,KAAK,CAAC,IAAI,WAAW,IAAI,KAAK,CAAC;AAAA,EACjE;AACA,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,IAAI,MAAM;AAC7C;AAEA,eAAe,WAAW,MAAgB;AACxC,QAAM,mBAAmB,KAAK,SAAS,sBAAsB;AAC7D,QAAM,aAAa,kBAAkB,IAAI;AACzC,QAAM,QAAQ,KAAK;AAAA,IACjB,CAAC,GAAG,MAAM,CAAC,EAAE,WAAW,IAAI,KAAK,EAAE,IAAI,KAAK,KAAK,IAAI,CAAC,MAAM;AAAA,EAC9D;AAEA,MAAI,MAAM,WAAW,GAAG;AACtB,YAAQ,MAAM,gFAAgF;AAC9F,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,cAAc,KAAK,MAAM,MAAM,cAAc,MAAM,CAAC,GAAG,OAAO,CAAC;AACrE,QAAM,eAAe,KAAK,MAAM,MAAM,cAAc,MAAM,CAAC,GAAG,OAAO,CAAC;AACtE,QAAM,WAAsC;AAC5C,QAAM,YAAuC;AAC7C,QAAM,iBAAiB,cAAc,OAAO,EAAE,WAAW,IAAI;AAC7D,QAAM,aAAa,YAAY,UAAU,WAAW,cAAc;AAElE,UAAQ;AAAA,IACN;AAAA,qBAAwB,WAAW,SAAS,GAAG,MAAM,GAAG,CAAC,CAAC,mBAAmB,WAAW,UAAU,GAAG,MAAM,GAAG,CAAC,CAAC;AAAA;AAAA,EAClH;AAEA,QAAM,cAAc,OAAO,KAAK,WAAW,OAAO;AAClD,QAAM,aAAa,KAAK,IAAI,GAAG,YAAY,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC;AAClE,QAAM,QAAQ,YAAY,KAAK,CAAC,MAAM,WAAW,QAAQ,CAAC,EAAE,MAAM,IAAI;AAEtE,QAAM,WAAW,QAAQ,4BAA4B;AACrD,QAAM,SAAS,QAAQ,4BAA4B;AACnD,UAAQ,IAAI,KAAK,SAAS,OAAO,UAAU,CAAC,0CAA0C,QAAQ,EAAE;AAChG,UAAQ,IAAI,KAAK,GAAG,OAAO,YAAY,GAAG,CAAC,0CAA0C,MAAM,EAAE;AAE7F,aAAW,QAAQ,aAAa;AAC9B,UAAM,IAAI,WAAW,QAAQ,IAAI;AACjC,UAAM,OAAO,EAAE,QAAQ,IAAI,MAAM;AACjC,QAAI,OAAO,KAAK,KAAK,OAAO,UAAU,CAAC,KAAK,EAAE,aAAa,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,KAAK,EAAE,cAAc,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,MAAM,OAAO,EAAE,MAAM,QAAQ,CAAC,GAAG,SAAS,CAAC,CAAC,MAAM,OAAO,EAAE,aAAa,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;AACjO,QAAI,OAAO;AACT,UAAI,EAAE,IAAI;AACR,cAAM,MAAM,EAAE,GAAG,SAAS,IAAI,MAAM,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC;AAC9D,cAAM,MAAM,EAAE,GAAG,SAAS,IAAI,MAAM,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC;AAC9D,cAAM,MAAM,EAAE,cAAc,QAAQ;AACpC,gBAAQ,MAAM,EAAE,KAAK,EAAE,IAAI,GAAG;AAAA,MAChC,OAAO;AACL,gBAAQ,WAAM,OAAO,EAAE;AAAA,MACzB;AAAA,IACF;AACA,YAAQ,IAAI,IAAI;AAAA,EAClB;AAEA,MAAI,WAAW,QAAQ;AACrB,UAAM,IAAI,WAAW;AACrB,UAAM,OAAO,EAAE,QAAQ,IAAI,MAAM;AACjC,YAAQ;AAAA,MACN;AAAA,sBAAyB,EAAE,eAAe,KAAM,QAAQ,CAAC,CAAC,mBAAmB,EAAE,gBAAgB,KAAM,QAAQ,CAAC,CAAC,MAAM,IAAI,GAAG,EAAE,aAAa,QAAQ,CAAC,CAAC;AAAA,IACvJ;AAAA,EACF;AACA,MAAI,WAAW,MAAM;AACnB,UAAM,IAAI,WAAW;AACrB,UAAM,OAAO,EAAE,QAAQ,IAAI,MAAM;AACjC,YAAQ;AAAA,MACN,qBAAqB,EAAE,cAAc,QAAQ,CAAC,CAAC,kBAAkB,EAAE,eAAe,QAAQ,CAAC,CAAC,KAAK,IAAI,GAAG,EAAE,aAAa,QAAQ,CAAC,CAAC;AAAA,IACnI;AAAA,EACF;AAEA,QAAM,cAAc,MAAM,QAAQ,QAAQ,IAAI,SAAS,CAAC,IAAI;AAC5D,QAAM,SAAS,KAAK;AAAA,IAClB;AAAA,IACA,YAAY,MAAM,SAAS,WAAW,YAAY,SAAS,WAAW,aAAa;AAAA,EACrF;AACA,UAAQ;AAAA,IACN;AAAA,iBAAoB,WAAW,YAAY,MAAM,oBAAoB,WAAW,aAAa,MAAM,cAAc,MAAM;AAAA;AAAA,EACzH;AAEA,MAAI,oBAAoB,WAAW,YAAY,SAAS,GAAG;AAEzD,UAAM,kBAAkB,YAAY,KAAK,CAAC,MAAM,WAAW,QAAQ,CAAC,EAAE,eAAe,IAAI;AACzF,QAAI,iBAAiB;AACnB,YAAM,2BAA2B,YAAY;AAAA,QAC3C,CAAC,MAAM,WAAW,QAAQ,CAAC,EAAE,gBAAgB,QAAQ,WAAW,QAAQ,CAAC,EAAE,QAAQ;AAAA,MACrF;AACA,UAAI,yBAA0B,SAAQ,KAAK,CAAC;AAAA,IAC9C,OAAO;AACL,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF;AAEA,eAAe,WAAW,MAAgB,QAAqB;AAC7D,QAAM,EAAE,YAAY,WAAW,YAAY,MAAM,IAAI,cAAc,IAAI;AAEvE,MAAI,MAAM,SAAS,GAAG;AACpB,YAAQ,MAAM,sEAAsE;AACpF,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,CAAC,aAAa,YAAY,IAAI;AACpC,QAAM,MAAM,KAAK,MAAM,MAAM,cAAc,aAAa,OAAO,CAAC;AAChE,QAAM,UAAwB,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,GAAG;AAE7D,QAAM,UAAU,MAAM,WAAW,WAAW,UAAU;AACtD,MAAI;AACF,UAAM,MAAM,MAAM,aAAkB,aAAQ,YAAY,GAAG,YAAY,GAAG;AAC1E,UAAM,aAAa,YAAwB,GAAG;AAE9C,QAAI,CAAC,cAAc,OAAO,eAAe,UAAU;AACjD,cAAQ;AAAA,QACN,UAAU,YAAY,qDAAgD,eAAe,OAAO,SAAS,OAAO,UAAU;AAAA,MACxH;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,QAAI,CAAC,MAAM,QAAQ,WAAW,OAAO,KAAK,WAAW,QAAQ,WAAW,GAAG;AACzE,cAAQ,MAAM,UAAU,YAAY,6CAA6C;AACjF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,WAAyB,CAAC;AAChC,eAAW,cAAc,SAAS;AAChC,UAAI,OAAO,QAAS;AACpB,eAAS,KAAK,MAAM,QAAQ,YAAY,WAAW,SAAS,SAAS,EAAE,OAAO,CAAC,CAAC;AAAA,IAClF;AAEA,eAAW,KAAK,UAAU;AACxB,cAAQ,IAAI,OAAO,YAAY,CAAC,IAAI,IAAI;AAAA,IAC1C;AAEA,QAAI,YAAY;AACd,YAAM,SAAS,MAAM,QAAQ,GAAG,IAAI,WAAW,SAAS,CAAC;AACzD,YAAM,YAAiB,aAAa,aAAQ,UAAU,CAAC;AACvD,YAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC1C,YAAM,eAAe,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,GAAG,OAAO;AACzE,cAAQ,IAAI,6BAA6B,UAAU,EAAE;AAAA,IACvD;AAAA,EACF,UAAE;AACA,UAAM,QAAQ,SAAS,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACzC;AACF;AAeA,SAAS,iBAAiB,GAAqB;AAC7C,MAAI,EAAE,SAAS,GAAG,EAAG,QAAO,WAAW,GAAG,QAAQ,IAAI,CAAC;AACvD,QAAM,WAAgB,aAAQ,CAAC;AAC/B,MAAI;AACF,UAAM,OAAO,SAAS,QAAQ;AAC9B,QAAI,KAAK,YAAY,GAAG;AACtB,YAAM,UAAU,YAAY,QAAQ;AACpC,aAAO,QACJ,OAAO,CAAC,MAAM,wBAAwB,KAAK,CAAC,CAAC,EAC7C,IAAI,CAAC,MAAW,UAAK,UAAU,CAAC,CAAC;AAAA,IACtC;AACA,WAAO,CAAC,QAAQ;AAAA,EAClB,QAAQ;AACN,WAAO,CAAC,QAAQ;AAAA,EAClB;AACF;AAGA,SAAS,gBAAgB,WAA4B;AACnD,MAAI,CAAC,MAAM,QAAQ,SAAS,KAAK,UAAU,WAAW,EAAG,QAAO;AAChE,SAAQ,UAAwB,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,EAAE,KAAK,IAAI;AAC7F;AAEA,SAAS,YAAY,QAA4B;AAC/C,QAAM,QAAkB,CAAC;AACzB,QAAM,cAAc,OAAO,KAAK,OAAO,QAAQ,OAAO;AACtD,QAAM,aAAa,KAAK,IAAI,GAAG,YAAY,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM;AAChF,QAAM,WAAW;AAEjB,QAAM;AAAA,IACJ,SAAS,gBAAgB,OAAO,SAAS,SAAS,CAAC,MAAM,OAAO,OAAO,KAAK,OAAO,QAAQ,KAAK;AAAA,EAClG;AACA,QAAM;AAAA,IACJ,KAAK,SAAS,OAAO,UAAU,CAAC,KAAK,OAAO,SAAS,QAAQ,CAAC,KAAK,MAAM,SAAS,QAAQ,CAAC,KAAK,MAAM,SAAS,QAAQ,CAAC,KAAK,MAAM,SAAS,QAAQ,CAAC,KAAK,MAAM,SAAS,QAAQ,CAAC;AAAA,EACpL;AAEA,QAAM,UAAU,aAAa,KAAK,WAAW,KAAK;AAClD,QAAM,KAAK,OAAO,SAAS,OAAO,OAAO,CAAC;AAE1C,aAAW,QAAQ,aAAa;AAC9B,UAAM,IAAI,OAAO,QAAQ,QAAQ,IAAI;AAErC,UAAM,kBAAkB,OAAO,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,OAAO,IAAI,KAAK,IAAI,EAAE;AACvF,QAAI,oBAAoB,GAAG;AACzB,YAAM;AAAA,QACJ,KAAK,KAAK,OAAO,UAAU,CAAC,KAAK,KAAK,SAAS,QAAQ,CAAC,KAAK,KAAK,SAAS,QAAQ,CAAC,KAAK,KAAK,SAAS,QAAQ,CAAC,KAAK,KAAK,SAAS,QAAQ,CAAC,KAAK,KAAK,SAAS,QAAQ,CAAC;AAAA,MAC1K;AAAA,IACF,OAAO;AACL,YAAM;AAAA,QACJ,KAAK,KAAK,OAAO,UAAU,CAAC,KAAK,EAAE,KAAK,QAAQ,CAAC,EAAE,SAAS,QAAQ,CAAC,KAAK,EAAE,IAAI,QAAQ,CAAC,EAAE,SAAS,QAAQ,CAAC,KAAK,EAAE,IAAI,QAAQ,CAAC,EAAE,SAAS,QAAQ,CAAC,KAAK,EAAE,IAAI,QAAQ,CAAC,EAAE,SAAS,QAAQ,CAAC,KAAK,EAAE,IAAI,QAAQ,CAAC,EAAE,SAAS,QAAQ,CAAC;AAAA,MACvO;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO,QAAQ,QAAQ;AACzB,UAAM,IAAI,OAAO,QAAQ;AACzB,UAAM;AAAA,MACJ,KAAK,SAAS,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,KAAM,QAAQ,CAAC,EAAE,SAAS,QAAQ,CAAC,MAAM,EAAE,MAAM,KAAM,QAAQ,CAAC,EAAE,SAAS,QAAQ,CAAC,MAAM,EAAE,MAAM,KAAM,QAAQ,CAAC,EAAE,SAAS,QAAQ,CAAC;AAAA,IACtL;AAAA,EACF;AAEA,QAAM,eAAe,OAAO,WAAW,KAAM,QAAQ,CAAC;AACtD,QAAM,UAAU,OAAO,YAAY,IAAI,IAAI,OAAO,UAAU,QAAQ,CAAC,CAAC,KAAK;AAC3E,QAAM,KAAK,EAAE;AACb,QAAM;AAAA,IACJ,eAAe,OAAO,QAAQ,QAAQ,IAAI,OAAO,QAAQ,KAAK,YAAY,OAAO,gBAAgB,WAAW;AAAA,EAC9G;AAEA,QAAM,kBAAkB,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,cAAc,MAAM;AACzE,MAAI,gBAAgB,SAAS,GAAG;AAC9B,UAAM,eAAe,CAAC,GAAG,IAAI,IAAI,gBAAgB,QAAQ,CAAC,MAAM,EAAE,YAAa,CAAC,CAAC;AACjF,UAAM,KAAK,EAAE;AACb,UAAM;AAAA,MACJ,oBAAoB,gBAAgB,MAAM,IAAI,OAAO,QAAQ,KAAK;AAAA,IACpE;AACA,eAAW,OAAO,aAAa,MAAM,GAAG,CAAC,GAAG;AAC1C,YAAM,KAAK,SAAS,GAAG,EAAE;AAAA,IAC3B;AACA,QAAI,aAAa,SAAS,GAAG;AAC3B,YAAM,KAAK,eAAe,aAAa,SAAS,CAAC,OAAO;AAAA,IAC1D;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,oBAAoB,SAAkC;AAC7D,QAAM,QAAkB,CAAC;AACzB,QAAM,cAAc,OAAO,KAAK,QAAQ,OAAO;AAC/C,QAAM,aAAa,KAAK,IAAI,GAAG,YAAY,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM;AAChF,QAAM,WAAW;AAEjB,QAAM;AAAA,IACJ,SAAS,gBAAgB,QAAQ,SAAS,CAAC,MAAM,QAAQ,OAAO,WAAW,QAAQ,QAAQ;AAAA,EAC7F;AACA,QAAM;AAAA,IACJ,KAAK,SAAS,OAAO,UAAU,CAAC,KAAK,gBAAkB,SAAS,QAAQ,CAAC,KAAK,MAAM,SAAS,CAAC,CAAC,KAAK,MAAM,SAAS,CAAC,CAAC;AAAA,EACvH;AACA,QAAM,UAAU,aAAa,IAAI,WAAW,IAAI,IAAI,IAAI;AACxD,QAAM,KAAK,OAAO,SAAS,OAAO,OAAO,CAAC;AAE1C,aAAW,QAAQ,aAAa;AAC9B,UAAM,IAAI,QAAQ,QAAQ,IAAI;AAC9B,UAAM,UAAU,GAAG,EAAE,KAAK,QAAQ,CAAC,CAAC,SAAW,EAAE,IAAI,QAAQ,CAAC,CAAC;AAC/D,UAAM;AAAA,MACJ,KAAK,KAAK,OAAO,UAAU,CAAC,KAAK,QAAQ,SAAS,QAAQ,CAAC,KAAK,EAAE,IAAI,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,KAAK,EAAE,IAAI,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;AAAA,IAC/H;AAAA,EACF;AAEA,MAAI,QAAQ,QAAQ;AAClB,UAAM;AAAA,MACJ,KAAK,SAAS,OAAO,UAAU,CAAC,OAAO,QAAQ,OAAO,OAAO,KAAM,QAAQ,CAAC,IAAI,YAAc,QAAQ,OAAO,MAAM,KAAM,QAAQ,CAAC,IAAI,KAAK,SAAS,QAAQ,CAAC;AAAA,IAC/J;AAAA,EACF;AAEA,QAAM,UAAU,QAAQ,YAAY,IAAI,IAAI,QAAQ,UAAU,QAAQ,CAAC,CAAC,KAAK;AAC7E,QAAM,eAAe,QAAQ,gBAAgB,KAAM,QAAQ,CAAC;AAC5D,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,iBAAiB,OAAO,sBAAsB,WAAW,GAAG;AAEvE,SAAO,MAAM,KAAK,IAAI;AACxB;AAIA,eAAe,yBAAyB,YAAyC;AAC/E,MAAI;AACF,UAAM,MAAM,MAAM,aAAa,YAAY,YAAY,GAAG;AAC1D,UAAM,UAAU,eAAe,GAAG;AAElC,QAAI,CAAC,WAAW,OAAO,QAAQ,YAAY,YAAY;AACrD,cAAQ,MAAM,mDAAmD;AACjE,UAAI,SAAS;AACX,cAAM,OAAO,OAAO,KAAK,OAAiB,EACvC,MAAM,GAAG,CAAC,EACV,KAAK,IAAI;AACZ,gBAAQ,MAAM,UAAU,OAAO,OAAO,GAAG,OAAO,iBAAiB,IAAI,OAAO,EAAE,EAAE;AAAA,MAClF;AACA,cAAQ;AAAA,QACN;AAAA;AAAA;AAAA,MACF;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,QACE,8FAA8F;AAAA,MAC5F;AAAA,IACF,GACA;AACA,YAAM,MAAW,aAAQ,UAAU;AACnC,cAAQ,MAAM,wEAAwE;AACtF,UAAI,QAAQ,SAAS,QAAQ,QAAQ;AACnC,gBAAQ;AAAA,UACN;AAAA,QACF;AAAA,MACF,OAAO;AACL,gBAAQ,MAAM,mDAAmD;AAAA,MACnE;AACA,cAAQ,MAAM;AAAA,IAChB;AACA,YAAQ,MAAM,0BAA0B,GAAG;AAC3C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,eAAe,WAAW,WAAoB,YAA4C;AAExF,MAAI,cAAc,WAAW,SAAS,GAAG;AACvC,UAAM,mBAAmB,UAAU;AAAA,EACrC;AAGA,MAAI,WAAW;AACb,UAAM,aAAkB,aAAQ,QAAQ,IAAI,GAAG,SAAS;AACxD,UAAM,OAAO,SAAS,YAAY,EAAE,gBAAgB,MAAM,CAAC;AAC3D,QAAI,CAAC,MAAM,OAAO,GAAG;AACnB,cAAQ,MAAM,0BAA0B,UAAU,EAAE;AACpD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,YAAQ,MAAM,kCAAkC,UAAU,EAAE;AAC5D,WAAO,yBAAyB,UAAU;AAAA,EAC5C;AAGA,QAAM,QAAQ,WAAW,QAAQ,IAAI,CAAC;AACtC,MAAI,OAAO;AACT,YAAQ,MAAM,oCAAoC,KAAK,EAAE;AACzD,WAAO,yBAAyB,KAAK;AAAA,EACvC;AAGA,QAAM,EAAE,WAAW,IAAI,MAAM,OAAO,aAAa;AACjD,SAAO,IAAI,WAAW;AACxB;AAIA,SAAS,cAAc,MAOrB;AACA,MAAI;AACJ,MAAI;AACJ,MAAI,aAAuB,CAAC;AAC5B,MAAI,OAAO;AACX,MAAI,gBAAgB;AACpB,QAAM,QAAkB,CAAC;AAEzB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,QAAQ,cAAc,QAAQ,cAAc,QAAQ,kBAAkB,QAAQ,UAAU;AAC1F,UAAI,IAAI,KAAK,KAAK,QAAQ;AACxB,gBAAQ,MAAM,UAAU,GAAG,mBAAmB;AAC9C,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,YAAM,QAAQ,KAAK,EAAE,CAAC;AACtB,UAAI,QAAQ,WAAY,cAAa;AAAA,eAC5B,QAAQ,WAAY,aAAY;AAAA,eAChC,QAAQ,SAAU,QAAO,KAAK,IAAI,GAAG,SAAS,OAAO,EAAE,KAAK,CAAC;AAAA;AAEpE,qBAAa,MACV,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AAAA,IACrB,WAAW,QAAQ,oBAAoB;AAErC,sBAAgB;AAAA,IAClB,WAAW,IAAI,WAAW,IAAI,GAAG;AAC/B,UAAI,CAAC,YAAY,IAAI,GAAG,GAAG;AACzB,gBAAQ,MAAM,iBAAiB,GAAG,EAAE;AACpC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF,OAAO;AACL,YAAM,KAAK,GAAG;AAAA,IAChB;AAAA,EACF;AAEA,SAAO,EAAE,YAAY,WAAW,YAAY,MAAM,eAAe,MAAM;AACzE;AAIA,eAAe,eAAe,MAAgB,QAAqB;AACjE,QAAM,EAAE,YAAY,WAAW,YAAY,MAAM,eAAe,MAAM,IAAI,cAAc,IAAI;AAE5F,MAAI,MAAM,WAAW,GAAG;AACtB,YAAQ,MAAM,mCAAmC;AACjD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,YAAsB,CAAC;AAC7B,aAAW,KAAK,OAAO;AACrB,cAAU,KAAK,GAAG,iBAAiB,CAAC,CAAC;AAAA,EACvC;AAEA,MAAI,UAAU,WAAW,GAAG;AAC1B,YAAQ,MAAM,4BAA4B;AAC1C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,UAAU,MAAM,WAAW,WAAW,UAAU;AACtD,QAAM,UAAwB,CAAC;AAC/B,MAAI,cAAc;AAElB,MAAI;AACF,eAAW,YAAY,WAAW;AAGhC,UAAI,OAAO,QAAS;AACpB,UAAI;AACF,cAAM,MAAM,MAAM,aAAkB,aAAQ,QAAQ,GAAG,YAAY,GAAG;AACtE,cAAM,aAAa,YAAwB,GAAG;AAE9C,cAAM,kBAAkB,mBAAmB,UAAU;AACrD,YAAI,iBAAiB;AACnB,kBAAQ,MAAM,UAAU,QAAQ,IAAI,eAAe,EAAE;AACrD;AACA;AAAA,QACF;AAKA,cAAM,WAAW,WAAoB,KAAK,iBAAiB;AAK3D,YAAI;AACJ,YAAI,OAAO,aAAa,YAAY;AAClC,0BAAgB;AAAA,QAClB,WAAW,aAAa,QAAW;AACjC,kBAAQ;AAAA,YACN,qBAAqB,QAAQ,sCAAsC,OAAO,QAAQ;AAAA,UACpF;AACA;AACA;AAAA,QACF;AAEA,YAAI;AAEJ,YAAI,eAAe;AAEjB,4BAAkB,OAAO,OAAO,OAAO;AACrC,kBAAM;AAAA,cACJ;AAAA,cACA,MAAM;AAAA,cACN;AAAA,YACF,IAAI,MAAM,QAAQ,eAAe,YAAY;AAC3C,qBAAO,cAAc,OAAO,EAAE;AAAA,YAChC,CAAC;AACD,mBAAO;AAAA,cACL,QAAQ,OAAO;AAAA,cACf,MAAM,OAAO,QAAQ;AAAA,cACrB,UAAU,OAAO,YAAY;AAAA,YAC/B;AAAA,UACF;AAAA,QACF,WAAW,QAAQ,YAAY,WAAW,QAAQ,GAAG;AAEnD,4BAAkB,OAAO,UAAU;AACjC,kBAAM,EAAE,QAAQ,MAAM,SAAS,IAAI,MAAM,QAAQ,eAAe,YAAY;AAC1E,qBAAO,QAAQ,QAAQ,WAAW,UAAU,KAAK;AAAA,YACnD,CAAC;AACD,mBAAO,EAAE,QAAQ,QAAQ,MAAM,SAAS;AAAA,UAC1C;AAAA,QACF,OAAO;AAcL,gBAAM,eAAe,MAAM;AACzB,kBAAM,MAAM,OAAO,KAAK,GAAG,EAAE,OAAO,CAAC,MAAM,MAAM,SAAS;AAC1D,kBAAM,cACJ,IAAI,WAAW,OAAO,IAAI,YAAY,WAClC,OAAO,KAAK,IAAI,OAAkC,IAClD,CAAC;AACP,kBAAM,MAAM,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,KAAK,GAAG,WAAW,CAAC,CAAC;AACjD,mBAAO,IAAI,SAAS,IAAI,mBAAmB,IAAI,KAAK,IAAI,CAAC,OAAO;AAAA,UAClE,GAAG;AACH,kBAAQ;AAAA,YACN,qBAAqB,QAAQ,uEACD,WAAW,QAAQ;AAAA,KAC5C,cAAc,KAAK,WAAW;AAAA,IAAO,MACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAOJ;AACA;AACA;AAAA,QACF;AAWA,cAAM,aAAa,EAAE,QAAQ,GAAI,gBAAgB,EAAE,eAAe,KAAK,IAAI,CAAC,EAAG;AAE/E,YAAI,OAAO,GAAG;AAUZ,gBAAM,EAAE,WAAW,IAAI,MAAM,OAAO,QAAa;AACjD,gBAAM,aAAa,WAAW;AAC9B,gBAAM,aAA2B,CAAC;AAClC,cAAI;AAEJ,mBAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,gBAAI,OAAO,QAAS;AACpB,oBAAQ,MAAM,kBAAkB,IAAI,CAAC,IAAI,IAAI,KAAK;AAClD,gBAAI;AACF,oBAAM,SAAS,MAAM,QAAQ,YAAY,iBAAiB,SAAS,UAAU;AAC7E,qBAAO,SAAS,aAAa;AAC7B,qBAAO,SAAS,WAAW;AAC3B,yBAAW,KAAK,MAAM;AAAA,YACxB,SAAS,KAAK;AACZ,2BAAa,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAC/D,sBAAQ,MAAM,kBAAkB,IAAI,CAAC,IAAI,IAAI,YAAY,WAAW,OAAO,EAAE;AAK7E;AAAA,YACF;AAAA,UACF;AAEA,cAAI,WAAW,WAAW,GAAG;AAK3B,oBAAQ;AAAA,cACN,uBAAuB,QAAQ,wBAAwB,YAAY,WAAW,iBAAiB;AAAA,YACjG;AACA;AACA;AAAA,UACF;AAEA,gBAAM,UAAU,WAAW,SAAS;AACpC,cAAI,SAAS;AAmBX,kBAAM,aAAa,aACf,WAAW,WAAW,OAAO,UAAU,KAAK,SAC5C;AACJ,uBAAW,KAAK,YAAY;AAC1B,gBAAE,SAAS,mBAAmB;AAC9B,gBAAE,SAAS,iBAAiB,WAAW;AACvC,gBAAE,SAAS,iBAAiB;AAC5B,kBAAI,WAAY,GAAE,SAAS,eAAe;AAAA,YAC5C;AACA,oBAAQ;AAAA,cACN,uBAAuB,WAAW,MAAM,OAAO,IAAI,uBAAuB,QAAQ;AAAA,YACpF;AACA;AAAA,UACF;AAEA,gBAAM,UAAU,cAAc,UAAU;AACxC,kBAAQ,IAAI,OAAO,oBAAoB,OAAO,IAAI,IAAI;AACtD,qBAAW,KAAK,WAAY,SAAQ,KAAK,CAAC;AAAA,QAC5C,OAAO;AACL,gBAAM,SAAS,MAAM,QAAQ,YAAY,iBAAiB,SAAS,UAAU;AAC7E,kBAAQ,KAAK,MAAM;AAEnB,kBAAQ,IAAI,OAAO,YAAY,MAAM,IAAI,IAAI;AAAA,QAC/C;AAAA,MACF,SAAS,KAAK;AACZ,gBAAQ;AAAA,UACN,sBAAsB,QAAQ,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACrF;AACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,cAAc,QAAQ,SAAS,GAAG;AACpC,YAAM,SAAS,QAAQ,WAAW,IAAI,QAAQ,CAAC,IAAI;AACnD,YAAM,YAAiB,aAAa,aAAQ,UAAU,CAAC;AACvD,YAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC1C,YAAM,eAAe,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,GAAG,OAAO;AACzE,cAAQ,IAAI,oBAAoB,UAAU,EAAE;AAAA,IAC9C;AAAA,EACF,UAAE;AACA,UAAM,QAAQ,SAAS,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACzC;AAKA,MAAI,cAAc,KAAK,QAAQ,WAAW,GAAG;AAC3C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,GAAG;AACjB,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -125,7 +125,18 @@ ${JSON.stringify(annotations, null, 2)}` : "",
|
|
|
125
125
|
{ role: "system", content: config.system },
|
|
126
126
|
{ role: "user", content: prompt }
|
|
127
127
|
],
|
|
128
|
-
{
|
|
128
|
+
{
|
|
129
|
+
model,
|
|
130
|
+
temperature: config.temperature ?? 0.2,
|
|
131
|
+
maxTokens: config.maxTokens,
|
|
132
|
+
effort: config.effort,
|
|
133
|
+
thinkingBudget: config.thinkingBudget,
|
|
134
|
+
includeThoughts: config.includeThoughts,
|
|
135
|
+
stop: config.stop,
|
|
136
|
+
providerOptions: config.providerOptions,
|
|
137
|
+
responseFormat: { type: "json_object" },
|
|
138
|
+
signal: context.signal
|
|
139
|
+
}
|
|
129
140
|
);
|
|
130
141
|
const responseCost = response.cost;
|
|
131
142
|
let validated;
|
|
@@ -227,7 +238,8 @@ async function runEval(config, executeWorkflow, runtime, options) {
|
|
|
227
238
|
);
|
|
228
239
|
}
|
|
229
240
|
return runtime.resolveProvider(uri);
|
|
230
|
-
}
|
|
241
|
+
},
|
|
242
|
+
signal: options?.signal
|
|
231
243
|
};
|
|
232
244
|
const evalItems = new Array(items.length);
|
|
233
245
|
let totalCost = 0;
|
|
@@ -753,11 +765,22 @@ async function rescore(result, scorers, runtime, options) {
|
|
|
753
765
|
);
|
|
754
766
|
}
|
|
755
767
|
return runtime.resolveProvider(uri);
|
|
756
|
-
}
|
|
768
|
+
},
|
|
769
|
+
signal: options?.signal
|
|
757
770
|
};
|
|
758
771
|
const rescored = new Array(result.items.length);
|
|
759
772
|
let totalCost = 0;
|
|
760
773
|
async function rescoreItem(original, itemIndex) {
|
|
774
|
+
if (options?.signal?.aborted) {
|
|
775
|
+
rescored[itemIndex] = {
|
|
776
|
+
input: original.input,
|
|
777
|
+
annotations: original.annotations,
|
|
778
|
+
output: original.output,
|
|
779
|
+
error: "cancelled",
|
|
780
|
+
scores: {}
|
|
781
|
+
};
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
761
784
|
if (original.error) {
|
|
762
785
|
rescored[itemIndex] = {
|
|
763
786
|
input: original.input,
|