agentv 5.3.0-next.1 → 5.3.2-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -60
- package/dist/{artifact-writer-JFNIPMKW.js → artifact-writer-KJEOROKQ.js} +5 -5
- package/dist/{chunk-6ZZCDZPD.js → chunk-6262OKXM.js} +21774 -21034
- package/dist/chunk-6262OKXM.js.map +1 -0
- package/dist/chunk-AQ5BIAXF.js +604 -0
- package/dist/chunk-AQ5BIAXF.js.map +1 -0
- package/dist/chunk-BV5VQLI2.js +2 -0
- package/dist/{chunk-V52ATPTT.js → chunk-JGSRUJZQ.js} +186 -32
- package/dist/chunk-JGSRUJZQ.js.map +1 -0
- package/dist/chunk-MMDLXYBX.js +721 -0
- package/dist/chunk-MMDLXYBX.js.map +1 -0
- package/dist/{chunk-FVR4RQFK.js → chunk-QSK3PC44.js} +1131 -580
- package/dist/chunk-QSK3PC44.js.map +1 -0
- package/dist/chunk-TEEXVJWM.js +2 -0
- package/dist/{chunk-BHKQHG26.js → chunk-WIAJ7JAV.js} +186 -64
- package/dist/chunk-WIAJ7JAV.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +17517 -10
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/{ts-eval-loader-DQDYRULE-V3377FOL.js → config.js} +7 -7
- package/dist/config.js.map +1 -0
- package/dist/contracts-DsZmZLl8.d.ts +742 -0
- package/dist/contracts.d.ts +2 -0
- package/dist/contracts.js +28 -0
- package/dist/contracts.js.map +1 -0
- package/dist/dashboard/assets/{index-DNgf3qJ2.js → index-BfqOlLOF.js} +1 -1
- package/dist/dashboard/assets/index-Bh8lpGce.css +1 -0
- package/dist/dashboard/assets/index-oPR3ywQb.js +121 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/{dist-6Z7U473R.js → dist-A3SGR7TW.js} +30 -18
- package/dist/dist-A3SGR7TW.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +137 -18
- package/dist/{interactive-RUY3OCBI.js → interactive-DL7N2C7K.js} +24 -24
- package/dist/interactive-DL7N2C7K.js.map +1 -0
- package/dist/provider.d.ts +2 -0
- package/dist/provider.js +24 -0
- package/dist/provider.js.map +1 -0
- package/dist/sdk.d.ts +802 -0
- package/dist/sdk.js +145 -0
- package/dist/sdk.js.map +1 -0
- package/dist/skills/agentv-bench/SKILL.md +14 -13
- package/dist/skills/agentv-bench/agents/analyzer.md +1 -1
- package/dist/skills/agentv-bench/agents/executor.md +1 -1
- package/dist/skills/agentv-bench/references/autoresearch.md +9 -9
- package/dist/skills/agentv-bench/references/environment-adaptation.md +4 -4
- package/dist/skills/agentv-bench/references/eval-yaml-spec.md +30 -47
- package/dist/skills/agentv-bench/references/schemas.md +44 -60
- package/dist/skills/agentv-bench/references/subagent-pipeline.md +20 -18
- package/dist/skills/agentv-eval-migrations/SKILL.md +13 -0
- package/dist/skills/agentv-eval-migrations/references/breaking-changes.md +56 -39
- package/dist/skills/agentv-eval-writer/SKILL.md +101 -60
- package/dist/skills/agentv-eval-writer/references/custom-evaluators.md +15 -10
- package/dist/skills/agentv-eval-writer/references/eval.schema.json +4543 -5189
- package/dist/skills/agentv-eval-writer/references/python-helpers.md +2 -2
- package/dist/skills/agentv-eval-writer/references/rubric-evaluator.md +20 -3
- package/dist/templates/.agentv/providers.yaml +42 -0
- package/dist/templates/.env.example +2 -2
- package/dist/ts-eval-loader-3G5GEAEC-6F52JLPP.js +18 -0
- package/dist/ts-eval-loader-3G5GEAEC-6F52JLPP.js.map +1 -0
- package/package.json +29 -4
- package/dist/chunk-6ZZCDZPD.js.map +0 -1
- package/dist/chunk-BHKQHG26.js.map +0 -1
- package/dist/chunk-FVR4RQFK.js.map +0 -1
- package/dist/chunk-T32NL3E6.js +0 -17973
- package/dist/chunk-T32NL3E6.js.map +0 -1
- package/dist/chunk-V52ATPTT.js.map +0 -1
- package/dist/dashboard/assets/index-D_bokML8.css +0 -1
- package/dist/dashboard/assets/index-r_jSJmlw.js +0 -121
- package/dist/interactive-RUY3OCBI.js.map +0 -1
- package/dist/templates/.agentv/targets.yaml +0 -97
- /package/dist/{artifact-writer-JFNIPMKW.js.map → artifact-writer-KJEOROKQ.js.map} +0 -0
- /package/dist/{dist-6Z7U473R.js.map → chunk-BV5VQLI2.js.map} +0 -0
- /package/dist/{ts-eval-loader-DQDYRULE-V3377FOL.js.map → chunk-TEEXVJWM.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
writeArtifactsFromResults
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WIAJ7JAV.js";
|
|
5
5
|
import {
|
|
6
6
|
RunBudgetTracker,
|
|
7
7
|
buildWipBranchName,
|
|
@@ -18,12 +18,12 @@ import {
|
|
|
18
18
|
resolveResultsRepoRunsDir,
|
|
19
19
|
setupWipWorktree,
|
|
20
20
|
syncResultsRepoForProject
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-JGSRUJZQ.js";
|
|
22
22
|
import {
|
|
23
23
|
AGENTV_LOCAL_CONFIG_FILE_NAME,
|
|
24
24
|
AGENTV_LOCAL_CONFIG_YML_FILE_NAME,
|
|
25
25
|
CLI_PLACEHOLDERS,
|
|
26
|
-
|
|
26
|
+
COMMON_PROVIDER_SETTINGS,
|
|
27
27
|
DEFAULT_EVAL_PATTERNS,
|
|
28
28
|
DEFAULT_THRESHOLD,
|
|
29
29
|
KNOWN_PROVIDERS,
|
|
@@ -51,7 +51,9 @@ import {
|
|
|
51
51
|
interpolateEnv,
|
|
52
52
|
isAgentVConfigFileName,
|
|
53
53
|
isGraderKind,
|
|
54
|
-
|
|
54
|
+
isScenarioFileReference,
|
|
55
|
+
isTypeScriptEvalConfigFileName,
|
|
56
|
+
listProviderLabels,
|
|
55
57
|
loadCasesFromDirectory,
|
|
56
58
|
loadCasesFromFile,
|
|
57
59
|
loadConfig,
|
|
@@ -60,17 +62,19 @@ import {
|
|
|
60
62
|
loadTestSuiteFromYamlObject,
|
|
61
63
|
normalizeComposableConfigGraph,
|
|
62
64
|
normalizeMetricsArtifactWire,
|
|
65
|
+
normalizeProviderDefinition,
|
|
63
66
|
normalizeResultRow,
|
|
64
|
-
normalizeTargetDefinition,
|
|
65
67
|
parseJsonlResults,
|
|
66
68
|
parseYamlValue,
|
|
67
|
-
|
|
69
|
+
readProviderDefinitions,
|
|
68
70
|
readTestSuiteMetadata,
|
|
69
71
|
resolveConfigFieldReferences,
|
|
70
72
|
resolveEnvironmentRecipe,
|
|
71
73
|
resolveFileReference,
|
|
74
|
+
resolveProviderDefinition,
|
|
75
|
+
resolveProviderDefinitionEnvironments,
|
|
72
76
|
resolveResultsConfigForProject,
|
|
73
|
-
|
|
77
|
+
resolveScenarioFileReference,
|
|
74
78
|
runEvaluation,
|
|
75
79
|
serializeEvaluationResultWire,
|
|
76
80
|
shouldEnableCache,
|
|
@@ -83,8 +87,9 @@ import {
|
|
|
83
87
|
toSnakeCaseDeep,
|
|
84
88
|
traceEnvelopeToTraceSummary,
|
|
85
89
|
traceEnvelopeToTranscriptMessages,
|
|
90
|
+
typeScriptEvalConfigGlob,
|
|
86
91
|
writeInitialRunSummaryArtifact
|
|
87
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-6262OKXM.js";
|
|
88
93
|
|
|
89
94
|
// src/commands/eval/shared.ts
|
|
90
95
|
import { constants } from "node:fs";
|
|
@@ -215,7 +220,7 @@ function agentSkillsToAgentVYamlObject(suite) {
|
|
|
215
220
|
|
|
216
221
|
// src/commands/eval/shared.ts
|
|
217
222
|
function isNativeEvalFile(filePath) {
|
|
218
|
-
return /\.(ya?ml|jsonl
|
|
223
|
+
return /\.(ya?ml|jsonl)$/i.test(filePath) || isTypeScriptEvalConfigFileName(filePath);
|
|
219
224
|
}
|
|
220
225
|
function shouldInspectJsonPath(filePath) {
|
|
221
226
|
const base = path.basename(filePath).toLowerCase();
|
|
@@ -265,7 +270,7 @@ async function resolveEvalPaths(evalPaths, cwd, options = {}) {
|
|
|
265
270
|
continue;
|
|
266
271
|
}
|
|
267
272
|
if (candidateStats.isDirectory()) {
|
|
268
|
-
const filePattern = options.allowReadAdapters ?
|
|
273
|
+
const filePattern = options.allowReadAdapters ? `{suite.yaml,suite.yml,*.eval.yaml,*.eval.yml,eval.yaml,eval.yml,${typeScriptEvalConfigGlob()},evals.json,*.evals.json}` : `{suite.yaml,suite.yml,*.eval.yaml,*.eval.yml,eval.yaml,eval.yml,${typeScriptEvalConfigGlob()}}`;
|
|
269
274
|
const dirGlob = path.posix.join(candidatePath.replace(/\\/g, "/"), `**/${filePattern}`);
|
|
270
275
|
const dirMatches = await fg(dirGlob, {
|
|
271
276
|
absolute: true,
|
|
@@ -344,83 +349,6 @@ async function findRepoRoot(start) {
|
|
|
344
349
|
return fallback;
|
|
345
350
|
}
|
|
346
351
|
|
|
347
|
-
// package.json
|
|
348
|
-
var package_default = {
|
|
349
|
-
name: "agentv",
|
|
350
|
-
version: "5.3.0-next.1",
|
|
351
|
-
description: "CLI entry point for AgentV",
|
|
352
|
-
type: "module",
|
|
353
|
-
repository: {
|
|
354
|
-
type: "git",
|
|
355
|
-
url: "https://github.com/EntityProcess/agentv.git"
|
|
356
|
-
},
|
|
357
|
-
homepage: "https://agentv.dev",
|
|
358
|
-
bugs: {
|
|
359
|
-
url: "https://github.com/EntityProcess/agentv/issues"
|
|
360
|
-
},
|
|
361
|
-
bin: {
|
|
362
|
-
agentv: "./dist/cli.js"
|
|
363
|
-
},
|
|
364
|
-
files: ["dist", "README.md"],
|
|
365
|
-
scripts: {
|
|
366
|
-
dev: "bun src/cli.ts",
|
|
367
|
-
build: "(cd ../../packages/sdk && bun run build) && tsup && bun run copy-readme",
|
|
368
|
-
"copy-readme": `bun -e "import { cpSync } from 'fs'; cpSync('../../README.md', 'README.md')"`,
|
|
369
|
-
prepublishOnly: `node -e "if(process.env.ALLOW_PUBLISH!=='1'){console.error('ERROR: Use bun run publish:next, then bun run promote:latest');process.exit(1)}"`,
|
|
370
|
-
typecheck: "(cd ../../packages/sdk && bun run build) && tsc --noEmit",
|
|
371
|
-
lint: "biome check .",
|
|
372
|
-
format: "biome format --write .",
|
|
373
|
-
fix: "biome check --write .",
|
|
374
|
-
test: "(cd ../../packages/sdk && bun run build) && bun test",
|
|
375
|
-
"test:watch": "bun test --watch"
|
|
376
|
-
},
|
|
377
|
-
dependencies: {
|
|
378
|
-
"@hono/node-server": "^1.19.11",
|
|
379
|
-
"@inquirer/prompts": "^8.2.1",
|
|
380
|
-
"@earendil-works/pi-ai": "^0.74.0",
|
|
381
|
-
"cmd-ts": "^0.14.3",
|
|
382
|
-
dotenv: "^16.4.5",
|
|
383
|
-
"fast-glob": "^3.3.3",
|
|
384
|
-
hono: "^4.12.9",
|
|
385
|
-
json5: "^2.2.3",
|
|
386
|
-
micromatch: "^4.0.8",
|
|
387
|
-
semver: "^7.7.4",
|
|
388
|
-
yaml: "^2.8.3"
|
|
389
|
-
},
|
|
390
|
-
peerDependencies: {
|
|
391
|
-
"@anthropic-ai/claude-agent-sdk": "^0.2.89",
|
|
392
|
-
"@github/copilot-sdk": "^1.0.3",
|
|
393
|
-
"@openai/codex-sdk": "^0.136.0",
|
|
394
|
-
"@earendil-works/pi-coding-agent": "^0.74.0"
|
|
395
|
-
},
|
|
396
|
-
peerDependenciesMeta: {
|
|
397
|
-
"@anthropic-ai/claude-agent-sdk": {
|
|
398
|
-
optional: true
|
|
399
|
-
},
|
|
400
|
-
"@github/copilot-sdk": {
|
|
401
|
-
optional: true
|
|
402
|
-
},
|
|
403
|
-
"@openai/codex-sdk": {
|
|
404
|
-
optional: true
|
|
405
|
-
},
|
|
406
|
-
"@earendil-works/pi-coding-agent": {
|
|
407
|
-
optional: true
|
|
408
|
-
}
|
|
409
|
-
},
|
|
410
|
-
optionalDependencies: {
|
|
411
|
-
"@anthropic-ai/claude-agent-sdk": "^0.2.89",
|
|
412
|
-
"@github/copilot-sdk": "^1.0.3",
|
|
413
|
-
"@openai/codex-sdk": "^0.136.0",
|
|
414
|
-
"@earendil-works/pi-coding-agent": "^0.74.0"
|
|
415
|
-
},
|
|
416
|
-
devDependencies: {
|
|
417
|
-
"@agentv/core": "workspace:*",
|
|
418
|
-
"@agentv/sdk": "workspace:*",
|
|
419
|
-
"@types/semver": "^7.7.1",
|
|
420
|
-
execa: "^9.3.0"
|
|
421
|
-
}
|
|
422
|
-
};
|
|
423
|
-
|
|
424
352
|
// src/commands/eval/result-layout.ts
|
|
425
353
|
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
426
354
|
import path2 from "node:path";
|
|
@@ -558,11 +486,17 @@ function relativeRunPathFromCwd(cwd, runDir) {
|
|
|
558
486
|
return parts.join(path2.posix.sep);
|
|
559
487
|
}
|
|
560
488
|
|
|
561
|
-
// src/utils/
|
|
489
|
+
// src/utils/providers.ts
|
|
562
490
|
import { constants as constants2 } from "node:fs";
|
|
563
|
-
import { access as access2 } from "node:fs/promises";
|
|
491
|
+
import { access as access2, stat as stat2 } from "node:fs/promises";
|
|
564
492
|
import path3 from "node:path";
|
|
565
|
-
var
|
|
493
|
+
var PROVIDER_FILE_CANDIDATES = [
|
|
494
|
+
"providers.yaml",
|
|
495
|
+
"providers.yml",
|
|
496
|
+
path3.join(".agentv", "providers.yaml"),
|
|
497
|
+
path3.join(".agentv", "providers.yml")
|
|
498
|
+
];
|
|
499
|
+
var LEGACY_TARGET_FILE_CANDIDATES = [
|
|
566
500
|
"targets.yaml",
|
|
567
501
|
"targets.yml",
|
|
568
502
|
path3.join(".agentv", "targets.yaml"),
|
|
@@ -576,20 +510,71 @@ async function fileExists(filePath) {
|
|
|
576
510
|
return false;
|
|
577
511
|
}
|
|
578
512
|
}
|
|
579
|
-
async function
|
|
580
|
-
|
|
513
|
+
async function pathKind(filePath) {
|
|
514
|
+
try {
|
|
515
|
+
const info = await stat2(filePath);
|
|
516
|
+
if (info.isDirectory()) {
|
|
517
|
+
return "directory";
|
|
518
|
+
}
|
|
519
|
+
if (info.isFile()) {
|
|
520
|
+
return "file";
|
|
521
|
+
}
|
|
522
|
+
return void 0;
|
|
523
|
+
} catch {
|
|
524
|
+
return void 0;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
function isLegacyTargetFile(filePath) {
|
|
528
|
+
return /^targets\.ya?ml$/i.test(path3.basename(filePath));
|
|
529
|
+
}
|
|
530
|
+
function removedTargetsFileError(filePath) {
|
|
531
|
+
return new Error(
|
|
532
|
+
`Authored targets.yaml files were removed. Rename ${filePath} to providers.yaml and use --providers to specify it explicitly.`
|
|
533
|
+
);
|
|
534
|
+
}
|
|
535
|
+
async function findProviderFileInDirectory(directory) {
|
|
536
|
+
for (const candidate of PROVIDER_FILE_CANDIDATES) {
|
|
537
|
+
const fullPath = path3.join(directory, candidate);
|
|
538
|
+
if (await pathKind(fullPath) === "file") {
|
|
539
|
+
return fullPath;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
return void 0;
|
|
543
|
+
}
|
|
544
|
+
async function findLegacyGeneratedTargetFileInDirectory(directory) {
|
|
545
|
+
for (const candidate of LEGACY_TARGET_FILE_CANDIDATES) {
|
|
546
|
+
const fullPath = path3.join(directory, candidate);
|
|
547
|
+
if (await pathKind(fullPath) === "file") {
|
|
548
|
+
return fullPath;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return void 0;
|
|
552
|
+
}
|
|
553
|
+
async function discoverProvidersFile(options) {
|
|
554
|
+
const { explicitPath, testFilePath, repoRoot, cwd, allowLegacyTargetFiles = false } = options;
|
|
581
555
|
if (explicitPath) {
|
|
582
556
|
const resolvedExplicit = path3.resolve(explicitPath);
|
|
583
|
-
|
|
557
|
+
const kind = await pathKind(resolvedExplicit);
|
|
558
|
+
if (kind === "file") {
|
|
559
|
+
if (!allowLegacyTargetFiles && isLegacyTargetFile(resolvedExplicit)) {
|
|
560
|
+
throw removedTargetsFileError(resolvedExplicit);
|
|
561
|
+
}
|
|
584
562
|
return resolvedExplicit;
|
|
585
563
|
}
|
|
586
|
-
|
|
587
|
-
const
|
|
588
|
-
if (
|
|
589
|
-
return
|
|
564
|
+
if (kind === "directory") {
|
|
565
|
+
const providerFile = await findProviderFileInDirectory(resolvedExplicit);
|
|
566
|
+
if (providerFile) {
|
|
567
|
+
return providerFile;
|
|
568
|
+
}
|
|
569
|
+
const legacyTargetFile = await findLegacyGeneratedTargetFileInDirectory(resolvedExplicit);
|
|
570
|
+
if (legacyTargetFile) {
|
|
571
|
+
if (allowLegacyTargetFiles) {
|
|
572
|
+
return legacyTargetFile;
|
|
573
|
+
}
|
|
574
|
+
throw removedTargetsFileError(legacyTargetFile);
|
|
590
575
|
}
|
|
591
576
|
}
|
|
592
|
-
throw new Error(`
|
|
577
|
+
throw new Error(`providers.yaml not found at provided path: ${resolvedExplicit}`);
|
|
593
578
|
}
|
|
594
579
|
const directories = [...buildDirectoryChain(testFilePath, repoRoot)];
|
|
595
580
|
const resolvedCwd = path3.resolve(cwd);
|
|
@@ -597,14 +582,23 @@ async function discoverTargetsFile(options) {
|
|
|
597
582
|
directories.push(resolvedCwd);
|
|
598
583
|
}
|
|
599
584
|
for (const directory of directories) {
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
585
|
+
const providerFile = await findProviderFileInDirectory(directory);
|
|
586
|
+
if (providerFile) {
|
|
587
|
+
return providerFile;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
for (const directory of directories) {
|
|
591
|
+
const legacyTargetFile = await findLegacyGeneratedTargetFileInDirectory(directory);
|
|
592
|
+
if (legacyTargetFile) {
|
|
593
|
+
if (allowLegacyTargetFiles) {
|
|
594
|
+
return legacyTargetFile;
|
|
604
595
|
}
|
|
596
|
+
throw removedTargetsFileError(legacyTargetFile);
|
|
605
597
|
}
|
|
606
598
|
}
|
|
607
|
-
throw new Error(
|
|
599
|
+
throw new Error(
|
|
600
|
+
"Unable to locate providers.yaml. Use --providers to specify the file explicitly."
|
|
601
|
+
);
|
|
608
602
|
}
|
|
609
603
|
|
|
610
604
|
// src/commands/eval/discover.ts
|
|
@@ -648,7 +642,7 @@ function filterByCategory(files, category) {
|
|
|
648
642
|
import { constants as constants4, existsSync as existsSync5, mkdirSync } from "node:fs";
|
|
649
643
|
import { access as access5, readFile as readFile8 } from "node:fs/promises";
|
|
650
644
|
import { createRequire as createNodeRequire } from "node:module";
|
|
651
|
-
import
|
|
645
|
+
import path13 from "node:path";
|
|
652
646
|
import { pathToFileURL } from "node:url";
|
|
653
647
|
|
|
654
648
|
// ../../node_modules/.bun/yocto-queue@1.2.2/node_modules/yocto-queue/index.js
|
|
@@ -792,6 +786,110 @@ function validateConcurrency(concurrency) {
|
|
|
792
786
|
|
|
793
787
|
// src/version-check.ts
|
|
794
788
|
import { coerce, satisfies, validRange } from "semver";
|
|
789
|
+
|
|
790
|
+
// package.json
|
|
791
|
+
var package_default = {
|
|
792
|
+
name: "agentv",
|
|
793
|
+
version: "5.3.2-next.1",
|
|
794
|
+
description: "CLI entry point for AgentV",
|
|
795
|
+
type: "module",
|
|
796
|
+
repository: {
|
|
797
|
+
type: "git",
|
|
798
|
+
url: "https://github.com/EntityProcess/agentv.git"
|
|
799
|
+
},
|
|
800
|
+
homepage: "https://agentv.dev",
|
|
801
|
+
bugs: {
|
|
802
|
+
url: "https://github.com/EntityProcess/agentv/issues"
|
|
803
|
+
},
|
|
804
|
+
bin: {
|
|
805
|
+
agentv: "./dist/cli.js"
|
|
806
|
+
},
|
|
807
|
+
main: "./dist/index.js",
|
|
808
|
+
types: "./dist/index.d.ts",
|
|
809
|
+
exports: {
|
|
810
|
+
".": {
|
|
811
|
+
types: "./dist/index.d.ts",
|
|
812
|
+
import: "./dist/index.js"
|
|
813
|
+
},
|
|
814
|
+
"./sdk": {
|
|
815
|
+
types: "./dist/sdk.d.ts",
|
|
816
|
+
import: "./dist/sdk.js"
|
|
817
|
+
},
|
|
818
|
+
"./provider": {
|
|
819
|
+
types: "./dist/provider.d.ts",
|
|
820
|
+
import: "./dist/provider.js"
|
|
821
|
+
},
|
|
822
|
+
"./contracts": {
|
|
823
|
+
types: "./dist/contracts.d.ts",
|
|
824
|
+
import: "./dist/contracts.js"
|
|
825
|
+
},
|
|
826
|
+
"./config": {
|
|
827
|
+
types: "./dist/config.d.ts",
|
|
828
|
+
import: "./dist/config.js"
|
|
829
|
+
},
|
|
830
|
+
"./package.json": "./package.json"
|
|
831
|
+
},
|
|
832
|
+
files: ["dist", "README.md"],
|
|
833
|
+
scripts: {
|
|
834
|
+
dev: "bun src/cli.ts",
|
|
835
|
+
build: "tsup && bun run copy-readme",
|
|
836
|
+
"copy-readme": `bun -e "import { cpSync } from 'fs'; cpSync('../../README.md', 'README.md')"`,
|
|
837
|
+
prepublishOnly: `node -e "if(process.env.ALLOW_PUBLISH!=='1'){console.error('ERROR: Use bun run publish:next, then bun run promote:latest');process.exit(1)}"`,
|
|
838
|
+
typecheck: "tsc --noEmit",
|
|
839
|
+
lint: "biome check .",
|
|
840
|
+
format: "biome format --write .",
|
|
841
|
+
fix: "biome check --write .",
|
|
842
|
+
test: "bun test",
|
|
843
|
+
"test:watch": "bun test --watch"
|
|
844
|
+
},
|
|
845
|
+
dependencies: {
|
|
846
|
+
"@hono/node-server": "^1.19.11",
|
|
847
|
+
"@inquirer/prompts": "^8.2.1",
|
|
848
|
+
"@earendil-works/pi-ai": "^0.74.0",
|
|
849
|
+
"cmd-ts": "^0.14.3",
|
|
850
|
+
dotenv: "^16.4.5",
|
|
851
|
+
"fast-glob": "^3.3.3",
|
|
852
|
+
hono: "^4.12.9",
|
|
853
|
+
json5: "^2.2.3",
|
|
854
|
+
micromatch: "^4.0.8",
|
|
855
|
+
semver: "^7.7.4",
|
|
856
|
+
yaml: "^2.8.3"
|
|
857
|
+
},
|
|
858
|
+
peerDependencies: {
|
|
859
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.89",
|
|
860
|
+
"@github/copilot-sdk": "^1.0.3",
|
|
861
|
+
"@openai/codex-sdk": "^0.136.0",
|
|
862
|
+
"@earendil-works/pi-coding-agent": "^0.74.0"
|
|
863
|
+
},
|
|
864
|
+
peerDependenciesMeta: {
|
|
865
|
+
"@anthropic-ai/claude-agent-sdk": {
|
|
866
|
+
optional: true
|
|
867
|
+
},
|
|
868
|
+
"@github/copilot-sdk": {
|
|
869
|
+
optional: true
|
|
870
|
+
},
|
|
871
|
+
"@openai/codex-sdk": {
|
|
872
|
+
optional: true
|
|
873
|
+
},
|
|
874
|
+
"@earendil-works/pi-coding-agent": {
|
|
875
|
+
optional: true
|
|
876
|
+
}
|
|
877
|
+
},
|
|
878
|
+
optionalDependencies: {
|
|
879
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.89",
|
|
880
|
+
"@github/copilot-sdk": "^1.0.3",
|
|
881
|
+
"@openai/codex-sdk": "^0.136.0",
|
|
882
|
+
"@earendil-works/pi-coding-agent": "^0.74.0"
|
|
883
|
+
},
|
|
884
|
+
devDependencies: {
|
|
885
|
+
"@agentv/core": "workspace:*",
|
|
886
|
+
"@agentv/sdk": "workspace:*",
|
|
887
|
+
"@types/semver": "^7.7.1",
|
|
888
|
+
execa: "^9.3.0"
|
|
889
|
+
}
|
|
890
|
+
};
|
|
891
|
+
|
|
892
|
+
// src/version-check.ts
|
|
795
893
|
var ANSI_YELLOW = "\x1B[33m";
|
|
796
894
|
var ANSI_RED = "\x1B[31m";
|
|
797
895
|
var ANSI_RESET = "\x1B[0m";
|
|
@@ -856,24 +954,6 @@ function manifestBaseDir(indexPath) {
|
|
|
856
954
|
const dir = path5.dirname(indexPath);
|
|
857
955
|
return path5.basename(dir) === ".internal" ? path5.dirname(dir) : dir;
|
|
858
956
|
}
|
|
859
|
-
function mapGradingAssertions(value) {
|
|
860
|
-
if (!Array.isArray(value)) {
|
|
861
|
-
return void 0;
|
|
862
|
-
}
|
|
863
|
-
return value.map((assertion) => {
|
|
864
|
-
const record = assertion;
|
|
865
|
-
return {
|
|
866
|
-
text: String(record.text ?? ""),
|
|
867
|
-
passed: Boolean(record.passed),
|
|
868
|
-
evidence: typeof record.evidence === "string" ? record.evidence : void 0
|
|
869
|
-
};
|
|
870
|
-
});
|
|
871
|
-
}
|
|
872
|
-
function readGradingAssertionResults(record) {
|
|
873
|
-
return mapGradingAssertions(
|
|
874
|
-
Array.isArray(record.assertion_results) ? record.assertion_results : record.assertions
|
|
875
|
-
);
|
|
876
|
-
}
|
|
877
957
|
function readNestedGradingScores(record) {
|
|
878
958
|
if (Array.isArray(record.component_results)) {
|
|
879
959
|
return record.component_results;
|
|
@@ -881,12 +961,6 @@ function readNestedGradingScores(record) {
|
|
|
881
961
|
if (Array.isArray(record.scores)) {
|
|
882
962
|
return record.scores;
|
|
883
963
|
}
|
|
884
|
-
if (Array.isArray(record.graders)) {
|
|
885
|
-
return record.graders;
|
|
886
|
-
}
|
|
887
|
-
if (Array.isArray(record.evaluators)) {
|
|
888
|
-
return record.evaluators;
|
|
889
|
-
}
|
|
890
964
|
return void 0;
|
|
891
965
|
}
|
|
892
966
|
function componentLabel(component) {
|
|
@@ -923,7 +997,7 @@ function collectComponentAssertions(value) {
|
|
|
923
997
|
});
|
|
924
998
|
}
|
|
925
999
|
function mapGradingEvaluator(evaluator) {
|
|
926
|
-
const pass =
|
|
1000
|
+
const pass = evaluator.pass === true;
|
|
927
1001
|
const verdict = pass ? "pass" : "fail";
|
|
928
1002
|
const details = evaluator.details && typeof evaluator.details === "object" && !Array.isArray(evaluator.details) ? evaluator.details : void 0;
|
|
929
1003
|
const assertion = evaluator.assertion && typeof evaluator.assertion === "object" && !Array.isArray(evaluator.assertion) ? evaluator.assertion : void 0;
|
|
@@ -937,7 +1011,7 @@ function mapGradingEvaluator(evaluator) {
|
|
|
937
1011
|
if (nestedAssertions.length > 0) {
|
|
938
1012
|
return nestedAssertions;
|
|
939
1013
|
}
|
|
940
|
-
return
|
|
1014
|
+
return [mapComponentAssertion(evaluator)];
|
|
941
1015
|
})(),
|
|
942
1016
|
scores: mapGradingEvaluators(readNestedGradingScores(evaluator)),
|
|
943
1017
|
weight: typeof evaluator.weight === "number" ? evaluator.weight : void 0,
|
|
@@ -1061,9 +1135,7 @@ function hydrateManifestRecord(baseDir, record, options) {
|
|
|
1061
1135
|
const testId = record.test_id ?? "unknown";
|
|
1062
1136
|
const gradingAssertions = grading ? collectComponentAssertions(grading.component_results) : void 0;
|
|
1063
1137
|
const gradingRecord = grading;
|
|
1064
|
-
const gradingScores = mapGradingEvaluators(
|
|
1065
|
-
gradingRecord?.component_results ?? gradingRecord?.graders ?? gradingRecord?.evaluators
|
|
1066
|
-
);
|
|
1138
|
+
const gradingScores = mapGradingEvaluators(gradingRecord?.component_results);
|
|
1067
1139
|
return {
|
|
1068
1140
|
timestamp: record.timestamp,
|
|
1069
1141
|
testId,
|
|
@@ -1079,11 +1151,7 @@ function hydrateManifestRecord(baseDir, record, options) {
|
|
|
1079
1151
|
passed: assertion.passed,
|
|
1080
1152
|
evidence: assertion.evidence
|
|
1081
1153
|
})),
|
|
1082
|
-
scores:
|
|
1083
|
-
// `evaluators` was renamed to `graders` in v4.13 — read both for backwards compat with old artifacts.
|
|
1084
|
-
// TODO: remove `evaluators` fallback once old run directories are no longer in use.
|
|
1085
|
-
gradingScores ?? record.scores
|
|
1086
|
-
),
|
|
1154
|
+
scores: gradingScores ?? record.scores,
|
|
1087
1155
|
tokenUsage: metrics?.tokens ? {
|
|
1088
1156
|
input: metrics.tokens.input,
|
|
1089
1157
|
output: metrics.tokens.output,
|
|
@@ -1147,8 +1215,16 @@ function loadLightweightResults(sourceFile) {
|
|
|
1147
1215
|
executionStatus: record.execution_status,
|
|
1148
1216
|
error: record.error,
|
|
1149
1217
|
costUsd: record.cost_usd,
|
|
1218
|
+
durationMs: record.duration_ms,
|
|
1219
|
+
tokenUsage: record.token_usage,
|
|
1150
1220
|
timestamp: record.timestamp,
|
|
1151
|
-
runtimeSource: record.runtime_source
|
|
1221
|
+
runtimeSource: record.runtime_source,
|
|
1222
|
+
resultDir: record.result_dir,
|
|
1223
|
+
outputPath: record.output_path,
|
|
1224
|
+
answerPath: record.answer_path,
|
|
1225
|
+
gradingPath: record.grading_path,
|
|
1226
|
+
transcriptPath: record.transcript_path,
|
|
1227
|
+
metricsPath: record.metrics_path
|
|
1152
1228
|
}));
|
|
1153
1229
|
}
|
|
1154
1230
|
|
|
@@ -1888,6 +1964,16 @@ function relativeRunPathFromManifestPath(relativeManifestPath) {
|
|
|
1888
1964
|
const manifestDir = path7.posix.dirname(relativeManifestPath);
|
|
1889
1965
|
return path7.posix.basename(manifestDir) === ".internal" ? path7.posix.dirname(manifestDir) : manifestDir;
|
|
1890
1966
|
}
|
|
1967
|
+
function formatPendingMergeWarnings(pendingMerge) {
|
|
1968
|
+
if (!pendingMerge) {
|
|
1969
|
+
return [];
|
|
1970
|
+
}
|
|
1971
|
+
const { temp_branch, target_branch, compare_url } = pendingMerge;
|
|
1972
|
+
const mergeSuffix = compare_url ? `: ${compare_url}` : ".";
|
|
1973
|
+
return [
|
|
1974
|
+
`Warning: results were pushed to '${temp_branch}' instead \u2014 they are not lost. Merge that branch into ${target_branch} with a pull request${mergeSuffix}`
|
|
1975
|
+
];
|
|
1976
|
+
}
|
|
1891
1977
|
async function maybeAutoExportRunArtifacts(payload) {
|
|
1892
1978
|
const config = await loadNormalizedResultsConfig(
|
|
1893
1979
|
payload.cwd,
|
|
@@ -1912,6 +1998,9 @@ async function maybeAutoExportRunArtifacts(payload) {
|
|
|
1912
1998
|
throw new Error(pushResult.block_reason ?? "Results branch push conflict");
|
|
1913
1999
|
}
|
|
1914
2000
|
console.warn(`Warning: skipping results export: ${pushResult.block_reason}`);
|
|
2001
|
+
for (const line of formatPendingMergeWarnings(pushResult.pending_merge)) {
|
|
2002
|
+
console.warn(line);
|
|
2003
|
+
}
|
|
1915
2004
|
return "failed";
|
|
1916
2005
|
}
|
|
1917
2006
|
if (!pushResult.changed) {
|
|
@@ -2714,10 +2803,13 @@ function formatMatrixSummary(results) {
|
|
|
2714
2803
|
return lines.join("\n");
|
|
2715
2804
|
}
|
|
2716
2805
|
|
|
2806
|
+
// src/commands/eval/targets.ts
|
|
2807
|
+
import path12 from "node:path";
|
|
2808
|
+
|
|
2717
2809
|
// ../../packages/core/dist/evaluation/validation/index.js
|
|
2718
2810
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
2719
2811
|
import path11 from "node:path";
|
|
2720
|
-
import { readFile as readFile22, readdir, realpath, stat as
|
|
2812
|
+
import { readFile as readFile22, readdir, realpath, stat as stat3 } from "node:fs/promises";
|
|
2721
2813
|
import path22 from "node:path";
|
|
2722
2814
|
import fg3 from "fast-glob";
|
|
2723
2815
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
@@ -2738,6 +2830,10 @@ async function detectFileType(filePath) {
|
|
|
2738
2830
|
const content = await readFile2(filePath, "utf8");
|
|
2739
2831
|
const parsed = parseYamlValue(content);
|
|
2740
2832
|
if (Array.isArray(parsed)) {
|
|
2833
|
+
const inferred = inferFileTypeFromPath(filePath);
|
|
2834
|
+
if (inferred === "targets") {
|
|
2835
|
+
return inferred;
|
|
2836
|
+
}
|
|
2741
2837
|
return "cases";
|
|
2742
2838
|
}
|
|
2743
2839
|
if (typeof parsed !== "object" || parsed === null) {
|
|
@@ -2772,7 +2868,7 @@ function inferFileTypeFromPath(filePath) {
|
|
|
2772
2868
|
if (isAgentVConfigFileName(basename)) {
|
|
2773
2869
|
return "config";
|
|
2774
2870
|
}
|
|
2775
|
-
if (basename === "
|
|
2871
|
+
if (basename === "providers.yaml" || basename === "providers.yml") {
|
|
2776
2872
|
return "targets";
|
|
2777
2873
|
}
|
|
2778
2874
|
}
|
|
@@ -2799,6 +2895,7 @@ var ASSERTION_TYPES_WITH_ARRAY_VALUE = /* @__PURE__ */ new Set([
|
|
|
2799
2895
|
var PROMPTFOO_ASSERTION_TYPES = /* @__PURE__ */ new Set([
|
|
2800
2896
|
"assert-set",
|
|
2801
2897
|
"llm-rubric",
|
|
2898
|
+
"agent-rubric",
|
|
2802
2899
|
"javascript",
|
|
2803
2900
|
"python",
|
|
2804
2901
|
"webhook",
|
|
@@ -2812,11 +2909,9 @@ var REMOVED_ASSERTION_TYPE_REPLACEMENTS = /* @__PURE__ */ new Map([
|
|
|
2812
2909
|
["rubrics", "llm-rubric with value"],
|
|
2813
2910
|
["rubric", "llm-rubric with value"],
|
|
2814
2911
|
["script-grader", "script"],
|
|
2815
|
-
["code-judge", "script"]
|
|
2816
|
-
["llm-judge", "llm-grader"]
|
|
2912
|
+
["code-judge", "script"]
|
|
2817
2913
|
]);
|
|
2818
2914
|
var UNSUPPORTED_PROMPTFOO_ASSERTION_TYPES = /* @__PURE__ */ new Set([
|
|
2819
|
-
"agent-rubric",
|
|
2820
2915
|
"answer-relevance",
|
|
2821
2916
|
"bleu",
|
|
2822
2917
|
"classifier",
|
|
@@ -2909,6 +3004,9 @@ function staleToolTrajectoryMessage(value) {
|
|
|
2909
3004
|
function staleAuthoredAssertionMessage(value) {
|
|
2910
3005
|
if (typeof value.type !== "string") return void 0;
|
|
2911
3006
|
const type = value.type.replace(/_/g, "-");
|
|
3007
|
+
if (type === "llm-grader" || type === "llm-judge") {
|
|
3008
|
+
return "Authored assertion type 'llm-grader' has been removed. Use 'llm-rubric' for free-form rubric checks or 'agent-rubric' for agentic rubric checks.";
|
|
3009
|
+
}
|
|
2912
3010
|
if (type === "skill-trigger") return staleSkillTriggerMessage(value);
|
|
2913
3011
|
if (type === "tool-trajectory") return staleToolTrajectoryMessage(value);
|
|
2914
3012
|
return void 0;
|
|
@@ -2939,6 +3037,7 @@ var KNOWN_TOP_LEVEL_FIELDS = /* @__PURE__ */ new Set([
|
|
|
2939
3037
|
"input_files",
|
|
2940
3038
|
"prompts",
|
|
2941
3039
|
"tests",
|
|
3040
|
+
"providers",
|
|
2942
3041
|
"graders",
|
|
2943
3042
|
"defaults",
|
|
2944
3043
|
"environment",
|
|
@@ -2974,7 +3073,6 @@ var KNOWN_DEFAULT_TEST_FIELDS = /* @__PURE__ */ new Set([
|
|
|
2974
3073
|
"provider",
|
|
2975
3074
|
"providers",
|
|
2976
3075
|
"prompts",
|
|
2977
|
-
"provider_output",
|
|
2978
3076
|
"assert",
|
|
2979
3077
|
"assert_scoring_function",
|
|
2980
3078
|
"options",
|
|
@@ -2992,8 +3090,6 @@ var KNOWN_EVALUATE_OPTION_FIELDS = /* @__PURE__ */ new Set([
|
|
|
2992
3090
|
"max_eval_time_ms",
|
|
2993
3091
|
"filter_range"
|
|
2994
3092
|
]);
|
|
2995
|
-
var KNOWN_REPEAT_FIELDS = /* @__PURE__ */ new Set(["count", "strategy", "early_exit", "cost_limit_usd"]);
|
|
2996
|
-
var KNOWN_REPEAT_STRATEGIES = /* @__PURE__ */ new Set(["pass_any", "pass_all", "mean", "confidence_interval"]);
|
|
2997
3093
|
var KNOWN_TEST_EXECUTION_FIELDS = /* @__PURE__ */ new Set([
|
|
2998
3094
|
"assert",
|
|
2999
3095
|
"skip_defaults",
|
|
@@ -3007,9 +3103,13 @@ var KNOWN_TEST_EXECUTION_FIELDS = /* @__PURE__ */ new Set([
|
|
|
3007
3103
|
"workspace"
|
|
3008
3104
|
]);
|
|
3009
3105
|
var REMOVED_TOP_LEVEL_FIELDS = /* @__PURE__ */ new Map([
|
|
3106
|
+
[
|
|
3107
|
+
"experiment",
|
|
3108
|
+
"Top-level 'experiment' has been removed from authored eval YAML. Use tags.experiment in the eval file or CLI --experiment at run time."
|
|
3109
|
+
],
|
|
3010
3110
|
[
|
|
3011
3111
|
"imports",
|
|
3012
|
-
"Top-level 'imports' is not supported. Run eval files directly with CLI multi-file selection and tags for grouping. For raw case files, use tests: file://... or string entries under tests. For reusable config, use prompts: file://..., default_test: file://..., and environment: file://... for coding-agent testbeds."
|
|
3112
|
+
"Top-level 'imports' is not supported. Run eval files directly with CLI multi-file selection and tags for grouping. For raw case files, use tests: file://... or string entries under tests. For reusable scenarios, use scenarios: [file://...]. For reusable config, use prompts: file://..., default_test: file://..., and environment: file://... for coding-agent testbeds."
|
|
3013
3113
|
],
|
|
3014
3114
|
[
|
|
3015
3115
|
"expected_output",
|
|
@@ -3023,20 +3123,29 @@ var REMOVED_TOP_LEVEL_FIELDS = /* @__PURE__ */ new Map([
|
|
|
3023
3123
|
"workers",
|
|
3024
3124
|
"'workers' has been removed from eval YAML. Set authored eval concurrency with evaluate_options.max_concurrency."
|
|
3025
3125
|
],
|
|
3026
|
-
["model", "Top-level 'model' is not part of eval YAML. Put model inside
|
|
3126
|
+
["model", "Top-level 'model' is not part of eval YAML. Put model inside providers[].config."],
|
|
3027
3127
|
[
|
|
3028
3128
|
"policy",
|
|
3029
3129
|
"Top-level 'policy' is not part of eval YAML. Put repeat under evaluate_options.repeat, timeout_seconds and threshold at the top level, and budget_usd under evaluate_options."
|
|
3030
3130
|
],
|
|
3131
|
+
["target", "Top-level 'target' has been removed. Use top-level 'providers' instead."],
|
|
3132
|
+
[
|
|
3133
|
+
"targets",
|
|
3134
|
+
"Top-level 'targets' has been removed. Use 'providers'; map targets[].id to providers[].label and targets[].provider to providers[].id."
|
|
3135
|
+
],
|
|
3031
3136
|
[
|
|
3032
|
-
"
|
|
3033
|
-
"Top-level '
|
|
3137
|
+
"eval_cases",
|
|
3138
|
+
"Top-level 'eval_cases' has been removed from authored eval YAML. Use 'tests' instead."
|
|
3139
|
+
],
|
|
3140
|
+
[
|
|
3141
|
+
"evalcases",
|
|
3142
|
+
"Top-level 'evalcases' has been removed from authored eval YAML. Use 'tests' instead."
|
|
3034
3143
|
],
|
|
3035
3144
|
["repeat", "Top-level 'repeat' has been removed. Use evaluate_options.repeat instead."],
|
|
3036
|
-
["runs", "Top-level 'runs' has been removed. Use evaluate_options.repeat.
|
|
3145
|
+
["runs", "Top-level 'runs' has been removed. Use a positive integer evaluate_options.repeat."],
|
|
3037
3146
|
[
|
|
3038
3147
|
"early_exit",
|
|
3039
|
-
"Top-level 'early_exit' has been removed. Use evaluate_options.repeat.
|
|
3148
|
+
"Top-level 'early_exit' has been removed. Use a positive integer evaluate_options.repeat."
|
|
3040
3149
|
],
|
|
3041
3150
|
["budget_usd", "Top-level 'budget_usd' has been removed. Use evaluate_options.budget_usd."],
|
|
3042
3151
|
[
|
|
@@ -3046,11 +3155,11 @@ var REMOVED_TOP_LEVEL_FIELDS = /* @__PURE__ */ new Map([
|
|
|
3046
3155
|
[
|
|
3047
3156
|
"preprocessors",
|
|
3048
3157
|
"Top-level 'preprocessors' has been removed from authored eval YAML. Use default_test.options.transform or assertion-level transform instead."
|
|
3049
|
-
]
|
|
3158
|
+
],
|
|
3159
|
+
["providerPromptMap", "Top-level 'providerPromptMap' is not supported. Use 'providers'."],
|
|
3160
|
+
["provider_prompt_map", "Top-level 'provider_prompt_map' is not supported. Use 'providers'."]
|
|
3050
3161
|
]);
|
|
3051
3162
|
var DEPRECATED_TOP_LEVEL_FIELDS = /* @__PURE__ */ new Map([
|
|
3052
|
-
["eval_cases", "'eval_cases' is deprecated. Use 'tests' instead."],
|
|
3053
|
-
["evalcases", "'evalcases' is deprecated. Use 'tests' instead."],
|
|
3054
3163
|
["evaluator", "'evaluator' is deprecated. Use 'assert' instead."]
|
|
3055
3164
|
]);
|
|
3056
3165
|
var KNOWN_TEST_FIELDS = /* @__PURE__ */ new Set([
|
|
@@ -3061,7 +3170,6 @@ var KNOWN_TEST_FIELDS = /* @__PURE__ */ new Set([
|
|
|
3061
3170
|
"provider",
|
|
3062
3171
|
"providers",
|
|
3063
3172
|
"prompts",
|
|
3064
|
-
"provider_output",
|
|
3065
3173
|
"input",
|
|
3066
3174
|
"input_files",
|
|
3067
3175
|
"assert",
|
|
@@ -3083,6 +3191,7 @@ var KNOWN_TEST_FIELDS = /* @__PURE__ */ new Set([
|
|
|
3083
3191
|
"on_turn_failure",
|
|
3084
3192
|
"window_size"
|
|
3085
3193
|
]);
|
|
3194
|
+
var KNOWN_SCENARIO_FIELDS = /* @__PURE__ */ new Set(["description", "config", "tests"]);
|
|
3086
3195
|
var SUPPORTED_WORKSPACE_REPO_FIELDS = /* @__PURE__ */ new Set(["path", "repo", "commit", "ancestor", "sparse"]);
|
|
3087
3196
|
var KNOWN_REMOVED_WORKSPACE_FIELDS = /* @__PURE__ */ new Set([
|
|
3088
3197
|
"template",
|
|
@@ -3100,6 +3209,26 @@ REMOVED_TEST_FIELDS.set(
|
|
|
3100
3209
|
"input",
|
|
3101
3210
|
"tests[].input has been removed from authored eval YAML. Put prompt text or chat/system/user messages in top-level 'prompts' and put row-specific data in tests[].vars."
|
|
3102
3211
|
);
|
|
3212
|
+
REMOVED_TEST_FIELDS.set(
|
|
3213
|
+
"provider_output",
|
|
3214
|
+
"tests[].provider_output is not supported in authored AgentV YAML. Use an explicit deterministic target such as provider: cli for fixed outputs, or use a replay/fixture target for captured provider responses."
|
|
3215
|
+
);
|
|
3216
|
+
REMOVED_TEST_FIELDS.set(
|
|
3217
|
+
"preprocessors",
|
|
3218
|
+
"tests[].preprocessors has been removed from authored eval YAML. Use tests[].options.transform or assertion-level transform instead."
|
|
3219
|
+
);
|
|
3220
|
+
REMOVED_TEST_FIELDS.set(
|
|
3221
|
+
"postprocess",
|
|
3222
|
+
"tests[].postprocess has been removed from authored eval YAML. Use tests[].options.transform instead."
|
|
3223
|
+
);
|
|
3224
|
+
REMOVED_TEST_FIELDS.set(
|
|
3225
|
+
"eval_cases",
|
|
3226
|
+
"tests[].eval_cases has been removed from authored eval YAML. Use 'tests' rows directly."
|
|
3227
|
+
);
|
|
3228
|
+
REMOVED_TEST_FIELDS.set(
|
|
3229
|
+
"evalcases",
|
|
3230
|
+
"tests[].evalcases has been removed from authored eval YAML. Use 'tests' rows directly."
|
|
3231
|
+
);
|
|
3103
3232
|
var DEPRECATED_TEST_FIELDS = /* @__PURE__ */ new Map([
|
|
3104
3233
|
["evaluator", "'evaluator' is deprecated. Use 'assert' instead."],
|
|
3105
3234
|
["expected_outcome", "'expected_outcome' is deprecated. Use 'assert' instead."]
|
|
@@ -3188,14 +3317,6 @@ async function validateEvalFile(filePath) {
|
|
|
3188
3317
|
};
|
|
3189
3318
|
}
|
|
3190
3319
|
validateMetadata(parsed, absolutePath, errors);
|
|
3191
|
-
if (parsed.experiment !== void 0 && typeof parsed.experiment !== "string") {
|
|
3192
|
-
errors.push({
|
|
3193
|
-
severity: "error",
|
|
3194
|
-
filePath: absolutePath,
|
|
3195
|
-
location: "experiment",
|
|
3196
|
-
message: "Top-level 'experiment' must be a string run/result grouping label."
|
|
3197
|
-
});
|
|
3198
|
-
}
|
|
3199
3320
|
for (const key of Object.keys(parsed)) {
|
|
3200
3321
|
const removedMessage = REMOVED_TOP_LEVEL_FIELDS.get(key);
|
|
3201
3322
|
if (removedMessage) {
|
|
@@ -3225,6 +3346,7 @@ async function validateEvalFile(filePath) {
|
|
|
3225
3346
|
}
|
|
3226
3347
|
}
|
|
3227
3348
|
await validateEnvironmentConfig(parsed.environment, absolutePath, errors, "environment");
|
|
3349
|
+
await validateProviderEnvironmentFields(parsed.providers, "providers", absolutePath, errors);
|
|
3228
3350
|
await validateSuiteWorkspaceConfigs(parsed, absolutePath, errors);
|
|
3229
3351
|
validateTargetTestbedFields(parsed.target, "target", absolutePath, errors);
|
|
3230
3352
|
validateTargetsTestbedFields(parsed.targets, "targets", absolutePath, errors);
|
|
@@ -3233,9 +3355,15 @@ async function validateEvalFile(filePath) {
|
|
|
3233
3355
|
validateEvaluateOptions(parsed.evaluate_options, "evaluate_options", absolutePath, errors);
|
|
3234
3356
|
validateAssertArray(parsed.assert, "assert", absolutePath, errors, customAssertionTypes);
|
|
3235
3357
|
validateDefaultTest(parsed.default_test, absolutePath, errors, customAssertionTypes);
|
|
3358
|
+
const expandedScenarios = await expandScenariosForValidation(
|
|
3359
|
+
parsed.scenarios,
|
|
3360
|
+
absolutePath,
|
|
3361
|
+
errors
|
|
3362
|
+
);
|
|
3363
|
+
await validateScenarios(expandedScenarios, parsed, absolutePath, errors, customAssertionTypes);
|
|
3236
3364
|
const cases = parsed.tests;
|
|
3237
3365
|
const hasImports = collectImportEntries(parsed).length > 0;
|
|
3238
|
-
const hasScenarios = Array.isArray(
|
|
3366
|
+
const hasScenarios = Array.isArray(expandedScenarios);
|
|
3239
3367
|
if (typeof cases === "string") {
|
|
3240
3368
|
await validateRawCaseImportPath(cases, absolutePath, "tests", errors);
|
|
3241
3369
|
await validateCompositionDiagnostics(absolutePath, parsed, errors);
|
|
@@ -3362,7 +3490,7 @@ async function validateEvalFile(filePath) {
|
|
|
3362
3490
|
suiteInputFiles: skipDefaults ? void 0 : parsed.input_files
|
|
3363
3491
|
}) !== void 0 : false;
|
|
3364
3492
|
validateInputField(evalCase.input, `${location}.input`, absolutePath, errors, {
|
|
3365
|
-
required: !hasPromptMdFallback && evalCase.prompts === void 0 && parsed.prompts === void 0
|
|
3493
|
+
required: !hasPromptMdFallback && evalCase.prompts === void 0 && parsed.prompts === void 0
|
|
3366
3494
|
});
|
|
3367
3495
|
const expectedOutputField = evalCase.expected_output;
|
|
3368
3496
|
if (expectedOutputField !== void 0) {
|
|
@@ -3405,6 +3533,32 @@ async function validateEvalFile(filePath) {
|
|
|
3405
3533
|
errors
|
|
3406
3534
|
};
|
|
3407
3535
|
}
|
|
3536
|
+
async function validateTypeScriptEvalConfigFile(filePath) {
|
|
3537
|
+
const absolutePath = path22.resolve(filePath);
|
|
3538
|
+
try {
|
|
3539
|
+
const { loadTsEvalSuite } = await import("./ts-eval-loader-3G5GEAEC-6F52JLPP.js");
|
|
3540
|
+
await loadTsEvalSuite(absolutePath, process.cwd());
|
|
3541
|
+
return {
|
|
3542
|
+
valid: true,
|
|
3543
|
+
filePath: absolutePath,
|
|
3544
|
+
fileType: "eval",
|
|
3545
|
+
errors: []
|
|
3546
|
+
};
|
|
3547
|
+
} catch (error) {
|
|
3548
|
+
return {
|
|
3549
|
+
valid: false,
|
|
3550
|
+
filePath: absolutePath,
|
|
3551
|
+
fileType: "eval",
|
|
3552
|
+
errors: [
|
|
3553
|
+
{
|
|
3554
|
+
severity: "error",
|
|
3555
|
+
filePath: absolutePath,
|
|
3556
|
+
message: error.message
|
|
3557
|
+
}
|
|
3558
|
+
]
|
|
3559
|
+
};
|
|
3560
|
+
}
|
|
3561
|
+
}
|
|
3408
3562
|
async function validateSuiteWorkspaceConfigs(parsed, absolutePath, errors) {
|
|
3409
3563
|
await validateWorkspaceConfig(parsed.workspace, absolutePath, errors, "workspace");
|
|
3410
3564
|
if (isObject(parsed.execution)) {
|
|
@@ -3447,6 +3601,31 @@ function validateTargetTestbedFields(target, location, filePath, errors) {
|
|
|
3447
3601
|
});
|
|
3448
3602
|
}
|
|
3449
3603
|
}
|
|
3604
|
+
async function validateProviderEnvironmentFields(providers, location, filePath, errors) {
|
|
3605
|
+
const entries = Array.isArray(providers) ? providers : providers === void 0 ? [] : [providers];
|
|
3606
|
+
for (let index = 0; index < entries.length; index++) {
|
|
3607
|
+
const entry = entries[index];
|
|
3608
|
+
if (!isObject(entry)) {
|
|
3609
|
+
continue;
|
|
3610
|
+
}
|
|
3611
|
+
await validateEnvironmentConfig(
|
|
3612
|
+
entry.environment,
|
|
3613
|
+
filePath,
|
|
3614
|
+
errors,
|
|
3615
|
+
`${location}[${index}].environment`
|
|
3616
|
+
);
|
|
3617
|
+
for (const field of ["container", "install"]) {
|
|
3618
|
+
if (entry[field] !== void 0) {
|
|
3619
|
+
errors.push({
|
|
3620
|
+
severity: "error",
|
|
3621
|
+
filePath,
|
|
3622
|
+
location: `${location}[${index}].${field}`,
|
|
3623
|
+
message: `Provider definitions cannot include ${field}; use an environment recipe for testbed setup.`
|
|
3624
|
+
});
|
|
3625
|
+
}
|
|
3626
|
+
}
|
|
3627
|
+
}
|
|
3628
|
+
}
|
|
3450
3629
|
function validateTargetsTestbedFields(targets, location, filePath, errors) {
|
|
3451
3630
|
const entries = Array.isArray(targets) ? targets : targets === void 0 ? [] : [targets];
|
|
3452
3631
|
entries.forEach((entry, index) => {
|
|
@@ -3634,7 +3813,7 @@ async function validateCompositionDiagnostics(filePath, parsed, errors) {
|
|
|
3634
3813
|
severity: "warning",
|
|
3635
3814
|
filePath,
|
|
3636
3815
|
location: entry.location,
|
|
3637
|
-
message: parentHasRuntime ? `Imported suite '${resolvedSuite.displayPath}' defines ${runtimeFields.join(", ")}, but child
|
|
3816
|
+
message: parentHasRuntime ? `Imported suite '${resolvedSuite.displayPath}' defines ${runtimeFields.join(", ")}, but child providers and run controls are ignored by legacy tests[].include suite imports. Prefer running eval files directly with CLI multi-file selection and tags.` : `Imported suite '${resolvedSuite.displayPath}' defines ${runtimeFields.join(", ")}, but child providers and run controls are ignored by legacy tests[].include suite imports. Prefer running eval files directly with CLI multi-file selection and tags.`
|
|
3638
3817
|
});
|
|
3639
3818
|
}
|
|
3640
3819
|
continue;
|
|
@@ -3656,7 +3835,9 @@ async function validateCompositionDiagnostics(filePath, parsed, errors) {
|
|
|
3656
3835
|
}
|
|
3657
3836
|
var WRAPPER_RUNTIME_CONTROL_FIELDS = [
|
|
3658
3837
|
"experiment",
|
|
3838
|
+
"providers",
|
|
3659
3839
|
"target",
|
|
3840
|
+
"targets",
|
|
3660
3841
|
"repeat",
|
|
3661
3842
|
"timeout_seconds",
|
|
3662
3843
|
"evaluate_options",
|
|
@@ -3852,10 +4033,18 @@ function validateDefaultTest(defaultTest, filePath, errors, customAssertionTypes
|
|
|
3852
4033
|
severity: "error",
|
|
3853
4034
|
filePath,
|
|
3854
4035
|
location: `default_test.${key}`,
|
|
3855
|
-
message: "Invalid default_test field. Supported fields: vars, provider, providers, prompts,
|
|
4036
|
+
message: "Invalid default_test field. Supported fields: vars, provider, providers, prompts, assert, assert_scoring_function, options, threshold, metadata."
|
|
3856
4037
|
});
|
|
3857
4038
|
}
|
|
3858
4039
|
}
|
|
4040
|
+
if (defaultTest.provider_output !== void 0) {
|
|
4041
|
+
errors.push({
|
|
4042
|
+
severity: "error",
|
|
4043
|
+
filePath,
|
|
4044
|
+
location: "default_test.provider_output",
|
|
4045
|
+
message: "default_test.provider_output is not supported in authored AgentV YAML. Use an explicit deterministic target such as provider: cli for fixed outputs, or use a replay/fixture target for captured provider responses."
|
|
4046
|
+
});
|
|
4047
|
+
}
|
|
3859
4048
|
if (defaultTest.expected_output !== void 0) {
|
|
3860
4049
|
errors.push({
|
|
3861
4050
|
severity: "error",
|
|
@@ -3877,19 +4066,222 @@ function validateDefaultTest(defaultTest, filePath, errors, customAssertionTypes
|
|
|
3877
4066
|
errors.push({
|
|
3878
4067
|
severity: "error",
|
|
3879
4068
|
filePath,
|
|
3880
|
-
location: "default_test.threshold",
|
|
3881
|
-
message: "Invalid 'default_test.threshold' field (must be a number between 0 and 1)"
|
|
4069
|
+
location: "default_test.threshold",
|
|
4070
|
+
message: "Invalid 'default_test.threshold' field (must be a number between 0 and 1)"
|
|
4071
|
+
});
|
|
4072
|
+
}
|
|
4073
|
+
const options = defaultTest.options;
|
|
4074
|
+
if (options !== void 0 && !isObject(options)) {
|
|
4075
|
+
errors.push({
|
|
4076
|
+
severity: "error",
|
|
4077
|
+
filePath,
|
|
4078
|
+
location: "default_test.options",
|
|
4079
|
+
message: "Invalid 'default_test.options' field (must be an object)"
|
|
4080
|
+
});
|
|
4081
|
+
}
|
|
4082
|
+
}
|
|
4083
|
+
async function validateScenarios(scenarios, parsed, filePath, errors, customAssertionTypes) {
|
|
4084
|
+
if (scenarios === void 0) {
|
|
4085
|
+
return;
|
|
4086
|
+
}
|
|
4087
|
+
if (!Array.isArray(scenarios)) {
|
|
4088
|
+
errors.push({
|
|
4089
|
+
severity: "error",
|
|
4090
|
+
filePath,
|
|
4091
|
+
location: "scenarios",
|
|
4092
|
+
message: "Invalid 'scenarios' field (must be an array)"
|
|
4093
|
+
});
|
|
4094
|
+
return;
|
|
4095
|
+
}
|
|
4096
|
+
for (let scenarioIndex = 0; scenarioIndex < scenarios.length; scenarioIndex++) {
|
|
4097
|
+
const scenario = scenarios[scenarioIndex];
|
|
4098
|
+
const scenarioLocation = `scenarios[${scenarioIndex}]`;
|
|
4099
|
+
if (!isObject(scenario)) {
|
|
4100
|
+
errors.push({
|
|
4101
|
+
severity: "error",
|
|
4102
|
+
filePath,
|
|
4103
|
+
location: scenarioLocation,
|
|
4104
|
+
message: "Scenario must be an object"
|
|
4105
|
+
});
|
|
4106
|
+
continue;
|
|
4107
|
+
}
|
|
4108
|
+
for (const key of Object.keys(scenario)) {
|
|
4109
|
+
if (!KNOWN_SCENARIO_FIELDS.has(key)) {
|
|
4110
|
+
errors.push({
|
|
4111
|
+
severity: "error",
|
|
4112
|
+
filePath,
|
|
4113
|
+
location: `${scenarioLocation}.${key}`,
|
|
4114
|
+
message: `Unknown scenario field '${key}'.`
|
|
4115
|
+
});
|
|
4116
|
+
}
|
|
4117
|
+
}
|
|
4118
|
+
if (!Array.isArray(scenario.config)) {
|
|
4119
|
+
errors.push({
|
|
4120
|
+
severity: "error",
|
|
4121
|
+
filePath,
|
|
4122
|
+
location: `${scenarioLocation}.config`,
|
|
4123
|
+
message: "Invalid 'config' field (must be an array)"
|
|
4124
|
+
});
|
|
4125
|
+
} else {
|
|
4126
|
+
for (let configIndex = 0; configIndex < scenario.config.length; configIndex++) {
|
|
4127
|
+
await validateScenarioTestLikeRow(
|
|
4128
|
+
scenario.config[configIndex],
|
|
4129
|
+
`${scenarioLocation}.config[${configIndex}]`,
|
|
4130
|
+
filePath,
|
|
4131
|
+
errors,
|
|
4132
|
+
customAssertionTypes,
|
|
4133
|
+
{ requireInput: false }
|
|
4134
|
+
);
|
|
4135
|
+
}
|
|
4136
|
+
}
|
|
4137
|
+
const scenarioConfigs = Array.isArray(scenario.config) ? scenario.config : [];
|
|
4138
|
+
if (!Array.isArray(scenario.tests)) {
|
|
4139
|
+
errors.push({
|
|
4140
|
+
severity: "error",
|
|
4141
|
+
filePath,
|
|
4142
|
+
location: `${scenarioLocation}.tests`,
|
|
4143
|
+
message: "Invalid 'tests' field (must be an array)"
|
|
4144
|
+
});
|
|
4145
|
+
continue;
|
|
4146
|
+
}
|
|
4147
|
+
for (let testIndex = 0; testIndex < scenario.tests.length; testIndex++) {
|
|
4148
|
+
const test = scenario.tests[testIndex];
|
|
4149
|
+
const everyConfigProvidesInput = scenarioConfigs.length > 0 && scenarioConfigs.every((config) => isObject(config) && config.prompts !== void 0);
|
|
4150
|
+
const requireInput = isObject(test) && parsed.prompts === void 0 && test.prompts === void 0 && !everyConfigProvidesInput;
|
|
4151
|
+
await validateScenarioTestLikeRow(
|
|
4152
|
+
test,
|
|
4153
|
+
`${scenarioLocation}.tests[${testIndex}]`,
|
|
4154
|
+
filePath,
|
|
4155
|
+
errors,
|
|
4156
|
+
customAssertionTypes,
|
|
4157
|
+
{ requireInput }
|
|
4158
|
+
);
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
}
|
|
4162
|
+
async function expandScenariosForValidation(scenarios, filePath, errors) {
|
|
4163
|
+
if (!Array.isArray(scenarios)) {
|
|
4164
|
+
return scenarios;
|
|
4165
|
+
}
|
|
4166
|
+
const expanded = [];
|
|
4167
|
+
for (let scenarioIndex = 0; scenarioIndex < scenarios.length; scenarioIndex++) {
|
|
4168
|
+
const scenario = scenarios[scenarioIndex];
|
|
4169
|
+
if (!isScenarioFileReference(scenario)) {
|
|
4170
|
+
expanded.push(scenario);
|
|
4171
|
+
continue;
|
|
4172
|
+
}
|
|
4173
|
+
try {
|
|
4174
|
+
const externalScenarios = await resolveScenarioFileReference(
|
|
4175
|
+
scenario,
|
|
4176
|
+
path22.dirname(filePath)
|
|
4177
|
+
);
|
|
4178
|
+
expanded.push(...externalScenarios);
|
|
4179
|
+
} catch (error) {
|
|
4180
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4181
|
+
errors.push({
|
|
4182
|
+
severity: "error",
|
|
4183
|
+
filePath,
|
|
4184
|
+
location: `scenarios[${scenarioIndex}]`,
|
|
4185
|
+
message
|
|
4186
|
+
});
|
|
4187
|
+
}
|
|
4188
|
+
}
|
|
4189
|
+
return expanded;
|
|
4190
|
+
}
|
|
4191
|
+
async function validateScenarioTestLikeRow(row, location, filePath, errors, customAssertionTypes, options) {
|
|
4192
|
+
if (!isObject(row)) {
|
|
4193
|
+
errors.push({
|
|
4194
|
+
severity: "error",
|
|
4195
|
+
filePath,
|
|
4196
|
+
location,
|
|
4197
|
+
message: "Scenario row must be an object"
|
|
4198
|
+
});
|
|
4199
|
+
return;
|
|
4200
|
+
}
|
|
4201
|
+
for (const key of Object.keys(row)) {
|
|
4202
|
+
const removedMessage = REMOVED_TEST_FIELDS.get(key);
|
|
4203
|
+
if (removedMessage) {
|
|
4204
|
+
errors.push({
|
|
4205
|
+
severity: "error",
|
|
4206
|
+
filePath,
|
|
4207
|
+
location: `${location}.${key}`,
|
|
4208
|
+
message: removedMessage.replaceAll("tests[]", location)
|
|
4209
|
+
});
|
|
4210
|
+
continue;
|
|
4211
|
+
}
|
|
4212
|
+
const deprecationMessage = DEPRECATED_TEST_FIELDS.get(key);
|
|
4213
|
+
if (deprecationMessage) {
|
|
4214
|
+
errors.push({
|
|
4215
|
+
severity: "warning",
|
|
4216
|
+
filePath,
|
|
4217
|
+
location: `${location}.${key}`,
|
|
4218
|
+
message: deprecationMessage
|
|
4219
|
+
});
|
|
4220
|
+
} else if (!KNOWN_TEST_FIELDS.has(key)) {
|
|
4221
|
+
errors.push({
|
|
4222
|
+
severity: "error",
|
|
4223
|
+
filePath,
|
|
4224
|
+
location: `${location}.${key}`,
|
|
4225
|
+
message: `Unknown test field '${key}'.`
|
|
4226
|
+
});
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4229
|
+
const id = row.id;
|
|
4230
|
+
if (id !== void 0 && (typeof id !== "string" || id.trim().length === 0)) {
|
|
4231
|
+
errors.push({
|
|
4232
|
+
severity: "error",
|
|
4233
|
+
filePath,
|
|
4234
|
+
location: `${location}.id`,
|
|
4235
|
+
message: "Invalid 'id' field (must be a non-empty string when provided)"
|
|
4236
|
+
});
|
|
4237
|
+
}
|
|
4238
|
+
const criteria = row.criteria;
|
|
4239
|
+
if (criteria !== void 0 && (typeof criteria !== "string" || criteria.trim().length === 0)) {
|
|
4240
|
+
errors.push({
|
|
4241
|
+
severity: "error",
|
|
4242
|
+
filePath,
|
|
4243
|
+
location: `${location}.criteria`,
|
|
4244
|
+
message: "Invalid 'criteria' field (must be a non-empty string if provided)"
|
|
4245
|
+
});
|
|
4246
|
+
} else if (criteria !== void 0 && row.assert !== void 0) {
|
|
4247
|
+
errors.push({
|
|
4248
|
+
severity: "error",
|
|
4249
|
+
filePath,
|
|
4250
|
+
location: `${location}.criteria`,
|
|
4251
|
+
message: "Do not combine test-level 'criteria' with 'assert'. Put human-readable case descriptions in tests[].description, or express grading text as an explicit assertion such as { type: 'llm-rubric', value: ... }."
|
|
3882
4252
|
});
|
|
3883
4253
|
}
|
|
3884
|
-
|
|
3885
|
-
|
|
4254
|
+
validateInputField(row.input, `${location}.input`, filePath, errors, {
|
|
4255
|
+
required: options.requireInput
|
|
4256
|
+
});
|
|
4257
|
+
if (row.expected_output !== void 0) {
|
|
3886
4258
|
errors.push({
|
|
3887
4259
|
severity: "error",
|
|
3888
4260
|
filePath,
|
|
3889
|
-
location:
|
|
3890
|
-
message: "
|
|
4261
|
+
location: `${location}.expected_output`,
|
|
4262
|
+
message: "tests[].expected_output has been removed from authored eval YAML. Put the reference answer in tests[].vars.expected_output and consume it with an explicit assertion, for example { type: 'llm-rubric', value: 'Matches the reference answer: {{ expected_output }}' }."
|
|
3891
4263
|
});
|
|
3892
4264
|
}
|
|
4265
|
+
validateAssertArray(row.assert, `${location}.assert`, filePath, errors, customAssertionTypes);
|
|
4266
|
+
validateRunOverride(row.run, `${location}.run`, filePath, errors);
|
|
4267
|
+
validateTestOptions(row.options, `${location}.options`, filePath, errors);
|
|
4268
|
+
await validateEnvironmentConfig(row.environment, filePath, errors, `${location}.environment`);
|
|
4269
|
+
validateConversationMode(row, location, filePath, errors);
|
|
4270
|
+
await validateWorkspaceConfig(row.workspace, filePath, errors, `${location}.workspace`);
|
|
4271
|
+
const caseExecution = isObject(row.execution) ? row.execution : void 0;
|
|
4272
|
+
if (caseExecution) {
|
|
4273
|
+
validateTestExecutionFields(caseExecution, filePath, errors, location);
|
|
4274
|
+
rejectRuntimeWorkspaceConfig(
|
|
4275
|
+
caseExecution.workspace,
|
|
4276
|
+
filePath,
|
|
4277
|
+
errors,
|
|
4278
|
+
`${location}.execution.workspace`
|
|
4279
|
+
);
|
|
4280
|
+
}
|
|
4281
|
+
const targets = row.providers !== void 0 ? row.providers : row.provider;
|
|
4282
|
+
if (targets !== void 0) {
|
|
4283
|
+
await validateProviderEnvironmentFields(targets, `${location}.providers`, filePath, errors);
|
|
4284
|
+
}
|
|
3893
4285
|
}
|
|
3894
4286
|
function validateEvaluateOptions(evaluateOptions, location, filePath, errors) {
|
|
3895
4287
|
if (evaluateOptions === void 0) {
|
|
@@ -3978,7 +4370,12 @@ function validateEvaluateOptionsRepeat(repeat, location, filePath, errors) {
|
|
|
3978
4370
|
}
|
|
3979
4371
|
return;
|
|
3980
4372
|
}
|
|
3981
|
-
|
|
4373
|
+
errors.push({
|
|
4374
|
+
severity: "error",
|
|
4375
|
+
filePath,
|
|
4376
|
+
location,
|
|
4377
|
+
message: `Invalid '${location}' field (must be a positive integer). The repeat object shape has been removed; use ${location}: 2.`
|
|
4378
|
+
});
|
|
3982
4379
|
}
|
|
3983
4380
|
function validateFilterRange(filterRange, location, filePath, errors) {
|
|
3984
4381
|
if (filterRange === void 0 || typeof filterRange === "string") {
|
|
@@ -3997,57 +4394,12 @@ function validateRepeatOverride(repeat, location, filePath, errors) {
|
|
|
3997
4394
|
if (repeat === void 0) {
|
|
3998
4395
|
return;
|
|
3999
4396
|
}
|
|
4000
|
-
if (!
|
|
4397
|
+
if (typeof repeat !== "number" || !Number.isInteger(repeat) || repeat < 1) {
|
|
4001
4398
|
errors.push({
|
|
4002
4399
|
severity: "error",
|
|
4003
4400
|
filePath,
|
|
4004
4401
|
location,
|
|
4005
|
-
message: "Invalid 'repeat' field (must be
|
|
4006
|
-
});
|
|
4007
|
-
return;
|
|
4008
|
-
}
|
|
4009
|
-
for (const key of Object.keys(repeat)) {
|
|
4010
|
-
if (!KNOWN_REPEAT_FIELDS.has(key)) {
|
|
4011
|
-
errors.push({
|
|
4012
|
-
severity: "error",
|
|
4013
|
-
filePath,
|
|
4014
|
-
location: `${location}.${key}`,
|
|
4015
|
-
message: "Invalid repeat field. Supported fields: count, strategy, early_exit, cost_limit_usd."
|
|
4016
|
-
});
|
|
4017
|
-
}
|
|
4018
|
-
}
|
|
4019
|
-
if (typeof repeat.count !== "number" || !Number.isInteger(repeat.count) || repeat.count < 1) {
|
|
4020
|
-
errors.push({
|
|
4021
|
-
severity: "error",
|
|
4022
|
-
filePath,
|
|
4023
|
-
location: `${location}.count`,
|
|
4024
|
-
message: "Invalid 'count' field (must be a positive integer)"
|
|
4025
|
-
});
|
|
4026
|
-
}
|
|
4027
|
-
if (repeat.strategy !== void 0 && (typeof repeat.strategy !== "string" || !KNOWN_REPEAT_STRATEGIES.has(repeat.strategy))) {
|
|
4028
|
-
errors.push({
|
|
4029
|
-
severity: "error",
|
|
4030
|
-
filePath,
|
|
4031
|
-
location: `${location}.strategy`,
|
|
4032
|
-
message: "Invalid 'strategy' field (must be pass_any, pass_all, mean, or confidence_interval; use pass_any instead of removed pass_at_k)"
|
|
4033
|
-
});
|
|
4034
|
-
}
|
|
4035
|
-
const earlyExit = repeat.early_exit;
|
|
4036
|
-
if (earlyExit !== void 0 && typeof earlyExit !== "boolean") {
|
|
4037
|
-
errors.push({
|
|
4038
|
-
severity: "error",
|
|
4039
|
-
filePath,
|
|
4040
|
-
location: `${location}.early_exit`,
|
|
4041
|
-
message: "Invalid 'early_exit' field (must be a boolean)"
|
|
4042
|
-
});
|
|
4043
|
-
}
|
|
4044
|
-
const costLimit = repeat.cost_limit_usd;
|
|
4045
|
-
if (costLimit !== void 0 && (typeof costLimit !== "number" || costLimit < 0)) {
|
|
4046
|
-
errors.push({
|
|
4047
|
-
severity: "error",
|
|
4048
|
-
filePath,
|
|
4049
|
-
location: `${location}.cost_limit_usd`,
|
|
4050
|
-
message: "Invalid 'cost_limit_usd' field (must be a non-negative number)"
|
|
4402
|
+
message: "Invalid 'repeat' field (must be a positive integer). The repeat object shape has been removed; use repeat: 2."
|
|
4051
4403
|
});
|
|
4052
4404
|
}
|
|
4053
4405
|
}
|
|
@@ -4489,7 +4841,7 @@ async function validateRawCaseImportPath(testsPath, filePath, location, errors)
|
|
|
4489
4841
|
let caseIndex = 0;
|
|
4490
4842
|
for (const casePath of caseFiles) {
|
|
4491
4843
|
const statPath = casePath.match(/\.(?:mjs|cjs|js|py):[^/\\:]+$/i) ? casePath.slice(0, casePath.lastIndexOf(":")) : casePath;
|
|
4492
|
-
const pathStat = await
|
|
4844
|
+
const pathStat = await stat3(statPath).catch(() => void 0);
|
|
4493
4845
|
const externalCases = pathStat?.isDirectory() ? await loadCasesFromDirectory(casePath) : await loadCasesFromFile(casePath);
|
|
4494
4846
|
for (const externalCase of externalCases) {
|
|
4495
4847
|
await validateWorkspaceConfig(
|
|
@@ -4925,6 +5277,11 @@ async function validateCasesFile(filePath) {
|
|
|
4925
5277
|
};
|
|
4926
5278
|
}
|
|
4927
5279
|
var LEGACY_ENV_PATTERN = /\$\{\{\s*([A-Z_][A-Z0-9_]*)\s*\}\}/g;
|
|
5280
|
+
var REMOVED_RUNNER_BATCHING_FIELDS = /* @__PURE__ */ new Set([
|
|
5281
|
+
"batch_requests",
|
|
5282
|
+
"provider_batching",
|
|
5283
|
+
"providerBatching"
|
|
5284
|
+
]);
|
|
4928
5285
|
function isObject3(value) {
|
|
4929
5286
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4930
5287
|
}
|
|
@@ -4959,7 +5316,7 @@ function validateLegacyEnvTemplates(value, filePath, location, errors) {
|
|
|
4959
5316
|
}
|
|
4960
5317
|
}
|
|
4961
5318
|
}
|
|
4962
|
-
var COMMON_SETTINGS = new Set(
|
|
5319
|
+
var COMMON_SETTINGS = new Set(COMMON_PROVIDER_SETTINGS);
|
|
4963
5320
|
var RETRY_SETTINGS = /* @__PURE__ */ new Set([
|
|
4964
5321
|
"max_retries",
|
|
4965
5322
|
"retry_initial_delay_ms",
|
|
@@ -5205,6 +5562,7 @@ function validateUnknownSettings(target, provider, absolutePath, location, error
|
|
|
5205
5562
|
"name",
|
|
5206
5563
|
"label",
|
|
5207
5564
|
"provider",
|
|
5565
|
+
"provider_spec",
|
|
5208
5566
|
"config",
|
|
5209
5567
|
"prompts",
|
|
5210
5568
|
"transform",
|
|
@@ -5212,6 +5570,7 @@ function validateUnknownSettings(target, provider, absolutePath, location, error
|
|
|
5212
5570
|
"env",
|
|
5213
5571
|
"grader_target",
|
|
5214
5572
|
"judge_target",
|
|
5573
|
+
"use_target",
|
|
5215
5574
|
"workers",
|
|
5216
5575
|
"$schema",
|
|
5217
5576
|
"targets"
|
|
@@ -5227,6 +5586,9 @@ function validateUnknownSettings(target, provider, absolutePath, location, error
|
|
|
5227
5586
|
};
|
|
5228
5587
|
const removedForProvider = removedPerProvider[provider];
|
|
5229
5588
|
for (const key of Object.keys(target)) {
|
|
5589
|
+
if (REMOVED_RUNNER_BATCHING_FIELDS.has(key)) {
|
|
5590
|
+
continue;
|
|
5591
|
+
}
|
|
5230
5592
|
if (removedFields.has(key)) {
|
|
5231
5593
|
errors.push({
|
|
5232
5594
|
severity: "warning",
|
|
@@ -5245,15 +5607,6 @@ function validateUnknownSettings(target, provider, absolutePath, location, error
|
|
|
5245
5607
|
});
|
|
5246
5608
|
continue;
|
|
5247
5609
|
}
|
|
5248
|
-
if (key === "provider_batching") {
|
|
5249
|
-
errors.push({
|
|
5250
|
-
severity: "error",
|
|
5251
|
-
filePath: absolutePath,
|
|
5252
|
-
location: `${location}.${key}`,
|
|
5253
|
-
message: "The 'provider_batching' field has been removed. Use 'batch_requests' instead."
|
|
5254
|
-
});
|
|
5255
|
-
continue;
|
|
5256
|
-
}
|
|
5257
5610
|
if (removedForProvider?.has(key)) {
|
|
5258
5611
|
errors.push({
|
|
5259
5612
|
severity: "error",
|
|
@@ -5273,6 +5626,22 @@ function validateUnknownSettings(target, provider, absolutePath, location, error
|
|
|
5273
5626
|
}
|
|
5274
5627
|
}
|
|
5275
5628
|
}
|
|
5629
|
+
function buildRemovedRunnerBatchingMessage(field) {
|
|
5630
|
+
return `The '${field}' field has been removed. Runner-level batching was removed; providers should implement internal queueing/batching behind per-request invocation.`;
|
|
5631
|
+
}
|
|
5632
|
+
function validateRemovedRunnerBatchingFields(target, absolutePath, location, errors) {
|
|
5633
|
+
for (const key of Object.keys(target)) {
|
|
5634
|
+
if (!REMOVED_RUNNER_BATCHING_FIELDS.has(key)) {
|
|
5635
|
+
continue;
|
|
5636
|
+
}
|
|
5637
|
+
errors.push({
|
|
5638
|
+
severity: "error",
|
|
5639
|
+
filePath: absolutePath,
|
|
5640
|
+
location: `${location}.${key}`,
|
|
5641
|
+
message: buildRemovedRunnerBatchingMessage(key)
|
|
5642
|
+
});
|
|
5643
|
+
}
|
|
5644
|
+
}
|
|
5276
5645
|
async function validateTargetsFile(filePath) {
|
|
5277
5646
|
const errors = [];
|
|
5278
5647
|
const absolutePath = path42.resolve(filePath);
|
|
@@ -5388,11 +5757,11 @@ async function validateTargetsFile(filePath) {
|
|
|
5388
5757
|
}
|
|
5389
5758
|
return result;
|
|
5390
5759
|
}
|
|
5391
|
-
if (!isObject3(parsed)) {
|
|
5760
|
+
if (!Array.isArray(parsed) && !isObject3(parsed)) {
|
|
5392
5761
|
errors.push({
|
|
5393
5762
|
severity: "error",
|
|
5394
5763
|
filePath: absolutePath,
|
|
5395
|
-
message: "File must contain a YAML object"
|
|
5764
|
+
message: "File must contain a YAML array or an object with a providers array"
|
|
5396
5765
|
});
|
|
5397
5766
|
return {
|
|
5398
5767
|
valid: false,
|
|
@@ -5401,22 +5770,22 @@ async function validateTargetsFile(filePath) {
|
|
|
5401
5770
|
errors
|
|
5402
5771
|
};
|
|
5403
5772
|
}
|
|
5404
|
-
if (Array.isArray(parsed.
|
|
5773
|
+
if (isObject3(parsed) && Array.isArray(parsed.targets)) {
|
|
5405
5774
|
errors.push({
|
|
5406
5775
|
severity: "error",
|
|
5407
5776
|
filePath: absolutePath,
|
|
5408
|
-
location: "
|
|
5409
|
-
message: "Top-level '
|
|
5777
|
+
location: "targets",
|
|
5778
|
+
message: "Top-level 'targets' has been removed. Use 'providers'; map targets[].id to providers[].label and targets[].provider to providers[].id."
|
|
5410
5779
|
});
|
|
5411
5780
|
}
|
|
5412
|
-
const
|
|
5413
|
-
const rawTargets = isObject3(rawParsed) && Array.isArray(rawParsed.
|
|
5414
|
-
if (!Array.isArray(
|
|
5781
|
+
const providers = Array.isArray(parsed) ? parsed : parsed.providers;
|
|
5782
|
+
const rawTargets = Array.isArray(rawParsed) ? rawParsed : isObject3(rawParsed) && Array.isArray(rawParsed.providers) ? rawParsed.providers : [];
|
|
5783
|
+
if (!Array.isArray(providers)) {
|
|
5415
5784
|
errors.push({
|
|
5416
5785
|
severity: "error",
|
|
5417
5786
|
filePath: absolutePath,
|
|
5418
|
-
location: "
|
|
5419
|
-
message: "Missing or invalid '
|
|
5787
|
+
location: "providers",
|
|
5788
|
+
message: "Missing or invalid 'providers' field (must be an array)"
|
|
5420
5789
|
});
|
|
5421
5790
|
return {
|
|
5422
5791
|
valid: errors.length === 0,
|
|
@@ -5426,22 +5795,24 @@ async function validateTargetsFile(filePath) {
|
|
|
5426
5795
|
};
|
|
5427
5796
|
}
|
|
5428
5797
|
const knownProviders = [...KNOWN_PROVIDERS];
|
|
5429
|
-
for (let i = 0; i <
|
|
5430
|
-
const
|
|
5431
|
-
const location = `
|
|
5432
|
-
if (!isObject3(
|
|
5798
|
+
for (let i = 0; i < providers.length; i++) {
|
|
5799
|
+
const providerEntry = providers[i];
|
|
5800
|
+
const location = `providers[${i}]`;
|
|
5801
|
+
if (!isObject3(providerEntry)) {
|
|
5433
5802
|
errors.push({
|
|
5434
5803
|
severity: "error",
|
|
5435
5804
|
filePath: absolutePath,
|
|
5436
5805
|
location,
|
|
5437
|
-
message: "
|
|
5806
|
+
message: "Provider must be an object"
|
|
5438
5807
|
});
|
|
5439
5808
|
continue;
|
|
5440
5809
|
}
|
|
5441
|
-
validateLegacyEnvTemplates(rawTargets[i] ??
|
|
5810
|
+
validateLegacyEnvTemplates(rawTargets[i] ?? providerEntry, absolutePath, location, errors);
|
|
5442
5811
|
let normalizedTarget;
|
|
5443
5812
|
try {
|
|
5444
|
-
normalizedTarget =
|
|
5813
|
+
normalizedTarget = normalizeProviderDefinition(providerEntry, {
|
|
5814
|
+
location
|
|
5815
|
+
});
|
|
5445
5816
|
} catch (error) {
|
|
5446
5817
|
errors.push({
|
|
5447
5818
|
severity: "error",
|
|
@@ -5451,7 +5822,7 @@ async function validateTargetsFile(filePath) {
|
|
|
5451
5822
|
});
|
|
5452
5823
|
}
|
|
5453
5824
|
for (const warning of findDeprecatedCamelCaseTargetWarnings(
|
|
5454
|
-
normalizedTarget ??
|
|
5825
|
+
normalizedTarget ?? providerEntry,
|
|
5455
5826
|
location
|
|
5456
5827
|
)) {
|
|
5457
5828
|
const fieldMatch = warning.message.match(/field '([^']+)'/);
|
|
@@ -5462,10 +5833,10 @@ async function validateTargetsFile(filePath) {
|
|
|
5462
5833
|
severity: "error",
|
|
5463
5834
|
filePath: absolutePath,
|
|
5464
5835
|
location: warning.location,
|
|
5465
|
-
message: `camelCase field '${field}' is no longer supported in
|
|
5836
|
+
message: `camelCase field '${field}' is no longer supported in providers.yaml. Use '${replacement}' instead.`
|
|
5466
5837
|
});
|
|
5467
5838
|
}
|
|
5468
|
-
const id =
|
|
5839
|
+
const id = providerEntry.id;
|
|
5469
5840
|
if (typeof id !== "string" || id.trim().length === 0) {
|
|
5470
5841
|
errors.push({
|
|
5471
5842
|
severity: "error",
|
|
@@ -5474,51 +5845,51 @@ async function validateTargetsFile(filePath) {
|
|
|
5474
5845
|
message: "Missing or invalid 'id' field (must be a non-empty string)"
|
|
5475
5846
|
});
|
|
5476
5847
|
}
|
|
5477
|
-
if (typeof
|
|
5848
|
+
if (typeof providerEntry.name === "string" && providerEntry.name.trim().length > 0) {
|
|
5478
5849
|
errors.push({
|
|
5479
5850
|
severity: "error",
|
|
5480
5851
|
filePath: absolutePath,
|
|
5481
|
-
location: `${location}.
|
|
5482
|
-
message: "The
|
|
5852
|
+
location: `${location}.name`,
|
|
5853
|
+
message: "The provider 'name' field has been removed. Use 'label' instead."
|
|
5483
5854
|
});
|
|
5484
5855
|
}
|
|
5485
|
-
|
|
5856
|
+
const effectiveTarget = normalizedTarget ?? providerEntry;
|
|
5857
|
+
const provider = effectiveTarget.provider;
|
|
5858
|
+
const rawTarget = rawTargets[i];
|
|
5859
|
+
const rawUseTarget = isObject3(rawTarget) ? rawTarget.use_target : void 0;
|
|
5860
|
+
if (effectiveTarget.use_target !== void 0 || rawUseTarget !== void 0) {
|
|
5486
5861
|
errors.push({
|
|
5487
5862
|
severity: "error",
|
|
5488
5863
|
filePath: absolutePath,
|
|
5489
|
-
location: `${location}.
|
|
5490
|
-
message: "The
|
|
5864
|
+
location: `${location}.use_target`,
|
|
5865
|
+
message: "The 'use_target' field has been removed from authored providers.yaml definitions. Define a concrete provider entry instead."
|
|
5491
5866
|
});
|
|
5492
5867
|
}
|
|
5493
|
-
const effectiveTarget = normalizedTarget ?? target;
|
|
5494
|
-
const provider = effectiveTarget.provider;
|
|
5495
|
-
const rawTarget = rawTargets[i];
|
|
5496
|
-
const rawUseTarget = isObject3(rawTarget) ? rawTarget.use_target : void 0;
|
|
5497
|
-
const hasUseTarget = isNonEmptyString(effectiveTarget.use_target) || isNonEmptyString(rawUseTarget);
|
|
5498
5868
|
const providerValue = typeof provider === "string" ? provider.trim().toLowerCase() : void 0;
|
|
5499
5869
|
const isTemplated = isEnvTemplated(provider);
|
|
5500
|
-
if (
|
|
5870
|
+
if (typeof provider !== "string" || provider.trim().length === 0) {
|
|
5501
5871
|
errors.push({
|
|
5502
5872
|
severity: "error",
|
|
5503
5873
|
filePath: absolutePath,
|
|
5504
|
-
location: `${location}.
|
|
5505
|
-
message: "Missing or invalid '
|
|
5874
|
+
location: `${location}.id`,
|
|
5875
|
+
message: "Missing or invalid 'id' field (must be a non-empty provider backend string)"
|
|
5506
5876
|
});
|
|
5507
5877
|
} else if (!isTemplated && (providerValue === "claude" || providerValue === "copilot")) {
|
|
5508
5878
|
errors.push({
|
|
5509
5879
|
severity: "error",
|
|
5510
5880
|
filePath: absolutePath,
|
|
5511
|
-
location: `${location}.
|
|
5881
|
+
location: `${location}.id`,
|
|
5512
5882
|
message: `Ambiguous provider '${providerValue}' is not supported. Choose an explicit provider such as '${providerValue}-cli' or '${providerValue}-sdk'.`
|
|
5513
5883
|
});
|
|
5514
5884
|
} else if (typeof provider === "string" && !isTemplated && !knownProviders.includes(provider)) {
|
|
5515
5885
|
errors.push({
|
|
5516
5886
|
severity: "warning",
|
|
5517
5887
|
filePath: absolutePath,
|
|
5518
|
-
location: `${location}.
|
|
5888
|
+
location: `${location}.id`,
|
|
5519
5889
|
message: `Unknown provider '${provider}'. Known providers: ${knownProviders.join(", ")}`
|
|
5520
5890
|
});
|
|
5521
5891
|
}
|
|
5892
|
+
validateRemovedRunnerBatchingFields(effectiveTarget, absolutePath, location, errors);
|
|
5522
5893
|
if (providerValue === "cli") {
|
|
5523
5894
|
validateCliSettings(effectiveTarget, absolutePath, location, errors);
|
|
5524
5895
|
}
|
|
@@ -5637,6 +6008,9 @@ async function validateConfigFile(filePath, options = {}) {
|
|
|
5637
6008
|
validateRefsConfig(errors, filePath, config.refs);
|
|
5638
6009
|
validateComposableGraph(errors, filePath, config);
|
|
5639
6010
|
validateDashboardConfig(errors, filePath, config.dashboard);
|
|
6011
|
+
validateHooksConfig(errors, filePath, config.hooks);
|
|
6012
|
+
validateEnvPathConfig(errors, filePath, config.env_path);
|
|
6013
|
+
validateEnvFromConfig(errors, filePath, config.env_from);
|
|
5640
6014
|
const projects = config.projects;
|
|
5641
6015
|
if (projects !== void 0) {
|
|
5642
6016
|
if (scope === "project") {
|
|
@@ -5665,13 +6039,17 @@ async function validateConfigFile(filePath, options = {}) {
|
|
|
5665
6039
|
"results",
|
|
5666
6040
|
"repo_resolvers",
|
|
5667
6041
|
"refs",
|
|
6042
|
+
"providers",
|
|
5668
6043
|
"targets",
|
|
5669
6044
|
"graders",
|
|
5670
6045
|
"tests",
|
|
5671
6046
|
"defaults",
|
|
5672
6047
|
"projects",
|
|
5673
6048
|
"dashboard",
|
|
5674
|
-
"studio"
|
|
6049
|
+
"studio",
|
|
6050
|
+
"hooks",
|
|
6051
|
+
"env_path",
|
|
6052
|
+
"env_from"
|
|
5675
6053
|
]);
|
|
5676
6054
|
const unexpectedFields = Object.keys(config).filter((key) => !allowedFields.has(key));
|
|
5677
6055
|
if (unexpectedFields.length > 0) {
|
|
@@ -5698,7 +6076,7 @@ async function validateConfigFile(filePath, options = {}) {
|
|
|
5698
6076
|
}
|
|
5699
6077
|
function validateComposableGraph(errors, filePath, config) {
|
|
5700
6078
|
try {
|
|
5701
|
-
normalizeComposableConfigGraph(config, filePath);
|
|
6079
|
+
normalizeComposableConfigGraph(config, filePath, { allowExecutionDefaultFields: true });
|
|
5702
6080
|
} catch (error) {
|
|
5703
6081
|
addError(errors, filePath, void 0, error.message);
|
|
5704
6082
|
}
|
|
@@ -5720,6 +6098,76 @@ function validateDashboardConfig(errors, filePath, rawDashboard) {
|
|
|
5720
6098
|
);
|
|
5721
6099
|
}
|
|
5722
6100
|
}
|
|
6101
|
+
var ENV_FROM_FORMATS = /* @__PURE__ */ new Set(["shell_exports", "json"]);
|
|
6102
|
+
function validateHooksConfig(errors, filePath, rawHooks) {
|
|
6103
|
+
if (rawHooks === void 0 || rawHooks === null) {
|
|
6104
|
+
return;
|
|
6105
|
+
}
|
|
6106
|
+
if (!isPlainObject(rawHooks)) {
|
|
6107
|
+
addError(errors, filePath, "hooks", "Field 'hooks' must be an object");
|
|
6108
|
+
return;
|
|
6109
|
+
}
|
|
6110
|
+
if (rawHooks.before_session !== void 0) {
|
|
6111
|
+
validateOptionalString(errors, filePath, rawHooks.before_session, "hooks.before_session");
|
|
6112
|
+
errors.push({
|
|
6113
|
+
severity: "warning",
|
|
6114
|
+
filePath,
|
|
6115
|
+
location: "hooks.before_session",
|
|
6116
|
+
message: "'hooks.before_session' is deprecated; use 'env_path' and/or 'env_from' to load environment variables before validation and eval."
|
|
6117
|
+
});
|
|
6118
|
+
}
|
|
6119
|
+
}
|
|
6120
|
+
function validateEnvPathConfig(errors, filePath, rawEnvPath) {
|
|
6121
|
+
if (rawEnvPath === void 0 || rawEnvPath === null) {
|
|
6122
|
+
return;
|
|
6123
|
+
}
|
|
6124
|
+
const isList = Array.isArray(rawEnvPath);
|
|
6125
|
+
const entries = isList ? rawEnvPath : [rawEnvPath];
|
|
6126
|
+
entries.forEach((entry, index) => {
|
|
6127
|
+
const location = isList ? `env_path[${index}]` : "env_path";
|
|
6128
|
+
if (typeof entry !== "string" || entry.trim().length === 0) {
|
|
6129
|
+
addError(errors, filePath, location, `Field '${location}' must be a non-empty string`);
|
|
6130
|
+
}
|
|
6131
|
+
});
|
|
6132
|
+
}
|
|
6133
|
+
function validateEnvFromConfig(errors, filePath, rawEnvFrom) {
|
|
6134
|
+
if (rawEnvFrom === void 0 || rawEnvFrom === null) {
|
|
6135
|
+
return;
|
|
6136
|
+
}
|
|
6137
|
+
const isList = Array.isArray(rawEnvFrom);
|
|
6138
|
+
const entries = isList ? rawEnvFrom : [rawEnvFrom];
|
|
6139
|
+
entries.forEach((entry, index) => {
|
|
6140
|
+
const location = isList ? `env_from[${index}]` : "env_from";
|
|
6141
|
+
if (!isPlainObject(entry)) {
|
|
6142
|
+
addError(errors, filePath, location, `Field '${location}' must be an object`);
|
|
6143
|
+
return;
|
|
6144
|
+
}
|
|
6145
|
+
const command = entry.command;
|
|
6146
|
+
if (typeof command === "string") {
|
|
6147
|
+
addError(
|
|
6148
|
+
errors,
|
|
6149
|
+
filePath,
|
|
6150
|
+
`${location}.command`,
|
|
6151
|
+
`Field '${location}.command' must be an argv array of strings, not a shell command string. Use e.g. ["bun", "scripts/load-secrets.ts"].`
|
|
6152
|
+
);
|
|
6153
|
+
} else if (!Array.isArray(command) || command.length === 0 || !command.every((part) => typeof part === "string" && part.length > 0)) {
|
|
6154
|
+
addError(
|
|
6155
|
+
errors,
|
|
6156
|
+
filePath,
|
|
6157
|
+
`${location}.command`,
|
|
6158
|
+
`Field '${location}.command' must be a non-empty array of strings`
|
|
6159
|
+
);
|
|
6160
|
+
}
|
|
6161
|
+
if (entry.format !== void 0 && !ENV_FROM_FORMATS.has(entry.format)) {
|
|
6162
|
+
addError(
|
|
6163
|
+
errors,
|
|
6164
|
+
filePath,
|
|
6165
|
+
`${location}.format`,
|
|
6166
|
+
`Field '${location}.format' must be "shell_exports" or "json"`
|
|
6167
|
+
);
|
|
6168
|
+
}
|
|
6169
|
+
});
|
|
6170
|
+
}
|
|
5723
6171
|
function validateRefsConfig(errors, filePath, rawRefs) {
|
|
5724
6172
|
if (rawRefs === void 0) {
|
|
5725
6173
|
return;
|
|
@@ -5932,13 +6380,7 @@ async function validateFileReferences(evalFilePath) {
|
|
|
5932
6380
|
if (!isObject4(parsed)) {
|
|
5933
6381
|
return errors;
|
|
5934
6382
|
}
|
|
5935
|
-
|
|
5936
|
-
if (cases === void 0 && "eval_cases" in parsed) {
|
|
5937
|
-
cases = parsed.eval_cases;
|
|
5938
|
-
}
|
|
5939
|
-
if (cases === void 0 && "evalcases" in parsed) {
|
|
5940
|
-
cases = parsed.evalcases;
|
|
5941
|
-
}
|
|
6383
|
+
const cases = parsed.tests;
|
|
5942
6384
|
if (!Array.isArray(cases)) {
|
|
5943
6385
|
return errors;
|
|
5944
6386
|
}
|
|
@@ -6145,13 +6587,13 @@ var ANSI_RESET3 = "\x1B[0m";
|
|
|
6145
6587
|
function isTTY() {
|
|
6146
6588
|
return process.stdout.isTTY ?? false;
|
|
6147
6589
|
}
|
|
6148
|
-
function resolveUseTarget(name, definitions, env,
|
|
6590
|
+
function resolveUseTarget(name, definitions, env, providersFilePath) {
|
|
6149
6591
|
const maxDepth = 5;
|
|
6150
6592
|
let current = definitions.find((d) => d.name === name);
|
|
6151
6593
|
if (!current) {
|
|
6152
|
-
const available =
|
|
6594
|
+
const available = listProviderLabels(definitions).join(", ");
|
|
6153
6595
|
throw new Error(
|
|
6154
|
-
`
|
|
6596
|
+
`Provider '${name}' not found in ${providersFilePath}. Available providers: ${available}`
|
|
6155
6597
|
);
|
|
6156
6598
|
}
|
|
6157
6599
|
for (let depth = 0; depth < maxDepth; depth++) {
|
|
@@ -6162,27 +6604,82 @@ function resolveUseTarget(name, definitions, env, targetsFilePath) {
|
|
|
6162
6604
|
const envMatch = raw.match(/^\$\{\{\s*([A-Z0-9_]+)\s*\}\}$/i);
|
|
6163
6605
|
const resolved = envMatch ? env[envMatch[1]] ?? "" : raw;
|
|
6164
6606
|
if (resolved.trim().length === 0) break;
|
|
6165
|
-
const next = definitions.find(
|
|
6607
|
+
const next = definitions.find(
|
|
6608
|
+
(d) => d.name === resolved.trim()
|
|
6609
|
+
);
|
|
6166
6610
|
if (!next) {
|
|
6167
|
-
const available =
|
|
6611
|
+
const available = listProviderLabels(definitions).join(", ");
|
|
6168
6612
|
throw new Error(
|
|
6169
|
-
`
|
|
6613
|
+
`Provider '${name}' use_target '${resolved.trim()}' not found in ${providersFilePath}. Available providers: ${available}`
|
|
6170
6614
|
);
|
|
6171
6615
|
}
|
|
6172
6616
|
current = next;
|
|
6173
6617
|
}
|
|
6174
6618
|
return current;
|
|
6175
6619
|
}
|
|
6176
|
-
async function
|
|
6620
|
+
async function readTestSuiteProvider(testFilePath) {
|
|
6177
6621
|
const metadata = await readTestSuiteMetadata(testFilePath);
|
|
6178
6622
|
return metadata.target;
|
|
6179
6623
|
}
|
|
6180
|
-
function
|
|
6181
|
-
|
|
6624
|
+
async function readProviderCatalog(options) {
|
|
6625
|
+
if (!options.explicitProvidersPath && options.providerDefinitions) {
|
|
6626
|
+
return {
|
|
6627
|
+
definitions: options.providerDefinitions,
|
|
6628
|
+
sourcePath: options.providerDefinitionsSource ?? ".agentv/config.yaml:providers"
|
|
6629
|
+
};
|
|
6630
|
+
}
|
|
6631
|
+
if (!options.explicitProvidersPath && options.requireExplicitProviderCatalog) {
|
|
6632
|
+
throw new Error(
|
|
6633
|
+
"No provider catalog configured. Add `providers:` to .agentv/config.yaml, use `providers: file://providers.yaml`, or pass --providers <path>."
|
|
6634
|
+
);
|
|
6635
|
+
}
|
|
6636
|
+
const providersFilePath = await discoverProvidersFile({
|
|
6637
|
+
explicitPath: options.explicitProvidersPath,
|
|
6638
|
+
testFilePath: options.testFilePath,
|
|
6639
|
+
repoRoot: options.repoRoot,
|
|
6640
|
+
cwd: options.cwd,
|
|
6641
|
+
allowLegacyTargetFiles: options.allowLegacyTargetFiles
|
|
6642
|
+
});
|
|
6643
|
+
await validateProviderCatalogFile(providersFilePath);
|
|
6644
|
+
return {
|
|
6645
|
+
definitions: await readProviderDefinitions(providersFilePath),
|
|
6646
|
+
sourcePath: providersFilePath
|
|
6647
|
+
};
|
|
6648
|
+
}
|
|
6649
|
+
async function validateProviderCatalogFile(providersFilePath) {
|
|
6650
|
+
const validationResult = await validateTargetsFile(providersFilePath);
|
|
6651
|
+
const warnings = validationResult.errors.filter((e) => e.severity === "warning");
|
|
6652
|
+
const useColors2 = isTTY();
|
|
6653
|
+
if (warnings.length > 0) {
|
|
6654
|
+
console.warn(`
|
|
6655
|
+
Warnings in ${providersFilePath}:`);
|
|
6656
|
+
for (const warning of warnings) {
|
|
6657
|
+
const location = warning.location ? ` [${warning.location}]` : "";
|
|
6658
|
+
const prefix = useColors2 ? `${ANSI_YELLOW3} \u26A0${ANSI_RESET3}` : " \u26A0";
|
|
6659
|
+
const message = useColors2 ? `${ANSI_YELLOW3}${warning.message}${ANSI_RESET3}` : warning.message;
|
|
6660
|
+
console.warn(`${prefix}${location} ${message}`);
|
|
6661
|
+
}
|
|
6662
|
+
console.warn("");
|
|
6663
|
+
}
|
|
6664
|
+
const errors = validationResult.errors.filter((e) => e.severity === "error");
|
|
6665
|
+
if (errors.length > 0) {
|
|
6666
|
+
console.error(`
|
|
6667
|
+
Errors in ${providersFilePath}:`);
|
|
6668
|
+
for (const error of errors) {
|
|
6669
|
+
const location = error.location ? ` [${error.location}]` : "";
|
|
6670
|
+
const prefix = useColors2 ? `${ANSI_RED3} \u2717${ANSI_RESET3}` : " \u2717";
|
|
6671
|
+
const message = useColors2 ? `${ANSI_RED3}${error.message}${ANSI_RESET3}` : error.message;
|
|
6672
|
+
console.error(`${prefix}${location} ${message}`);
|
|
6673
|
+
}
|
|
6674
|
+
throw new Error(`Providers file validation failed with ${errors.length} error(s)`);
|
|
6675
|
+
}
|
|
6676
|
+
}
|
|
6677
|
+
function pickProviderLabel(options) {
|
|
6678
|
+
const cliName = options.cliProviderLabel?.trim();
|
|
6182
6679
|
if (cliName && cliName !== "default") {
|
|
6183
6680
|
return { name: cliName, source: "cli" };
|
|
6184
6681
|
}
|
|
6185
|
-
const fileName = options.
|
|
6682
|
+
const fileName = options.fileProviderLabel?.trim();
|
|
6186
6683
|
if (fileName && fileName.length > 0) {
|
|
6187
6684
|
return { name: fileName, source: "test-file" };
|
|
6188
6685
|
}
|
|
@@ -6193,12 +6690,12 @@ function withModelOverride(target, modelOverride) {
|
|
|
6193
6690
|
return model && model.length > 0 ? { ...target, model } : target;
|
|
6194
6691
|
}
|
|
6195
6692
|
function overlayTargetDefinition(params) {
|
|
6196
|
-
const { spec, definitions, env,
|
|
6693
|
+
const { spec, definitions, env, providersFilePath } = params;
|
|
6197
6694
|
if (!spec?.definition) {
|
|
6198
6695
|
return void 0;
|
|
6199
6696
|
}
|
|
6200
6697
|
if (spec.extends) {
|
|
6201
|
-
const base = resolveUseTarget(spec.extends, definitions, env,
|
|
6698
|
+
const base = resolveUseTarget(spec.extends, definitions, env, providersFilePath);
|
|
6202
6699
|
return {
|
|
6203
6700
|
...base,
|
|
6204
6701
|
...spec.definition,
|
|
@@ -6210,82 +6707,86 @@ function overlayTargetDefinition(params) {
|
|
|
6210
6707
|
function definitionsWithEffectiveTarget(definitions, effective) {
|
|
6211
6708
|
return [effective, ...definitions.filter((definition) => definition.name !== effective.name)];
|
|
6212
6709
|
}
|
|
6213
|
-
async function
|
|
6214
|
-
const
|
|
6215
|
-
|
|
6216
|
-
|
|
6710
|
+
async function resolveInlineDefinitionEnvironment(definition, testFilePath, location) {
|
|
6711
|
+
const [resolved] = await resolveProviderDefinitionEnvironments(
|
|
6712
|
+
[definition],
|
|
6713
|
+
path12.dirname(path12.resolve(testFilePath)),
|
|
6714
|
+
{ location }
|
|
6715
|
+
);
|
|
6716
|
+
return resolved ?? definition;
|
|
6717
|
+
}
|
|
6718
|
+
async function selectProvider(options) {
|
|
6719
|
+
const {
|
|
6720
|
+
testFilePath,
|
|
6721
|
+
repoRoot,
|
|
6722
|
+
cwd,
|
|
6723
|
+
explicitProvidersPath,
|
|
6724
|
+
providerDefinitions,
|
|
6725
|
+
providerDefinitionsSource,
|
|
6726
|
+
requireExplicitProviderCatalog,
|
|
6727
|
+
allowLegacyTargetFiles,
|
|
6728
|
+
cliProviderLabel,
|
|
6729
|
+
modelOverride,
|
|
6730
|
+
env
|
|
6731
|
+
} = options;
|
|
6732
|
+
const providerCatalog = await readProviderCatalog({
|
|
6733
|
+
explicitProvidersPath,
|
|
6734
|
+
providerDefinitions,
|
|
6735
|
+
providerDefinitionsSource,
|
|
6736
|
+
requireExplicitProviderCatalog,
|
|
6217
6737
|
testFilePath,
|
|
6218
6738
|
repoRoot,
|
|
6219
|
-
cwd
|
|
6739
|
+
cwd,
|
|
6740
|
+
allowLegacyTargetFiles
|
|
6220
6741
|
});
|
|
6221
|
-
const
|
|
6222
|
-
const
|
|
6223
|
-
const useColors2 = isTTY();
|
|
6224
|
-
if (warnings.length > 0) {
|
|
6225
|
-
console.warn(`
|
|
6226
|
-
Warnings in ${targetsFilePath}:`);
|
|
6227
|
-
for (const warning of warnings) {
|
|
6228
|
-
const location = warning.location ? ` [${warning.location}]` : "";
|
|
6229
|
-
const prefix = useColors2 ? `${ANSI_YELLOW3} \u26A0${ANSI_RESET3}` : " \u26A0";
|
|
6230
|
-
const message = useColors2 ? `${ANSI_YELLOW3}${warning.message}${ANSI_RESET3}` : warning.message;
|
|
6231
|
-
console.warn(`${prefix}${location} ${message}`);
|
|
6232
|
-
}
|
|
6233
|
-
console.warn("");
|
|
6234
|
-
}
|
|
6235
|
-
const errors = validationResult.errors.filter((e) => e.severity === "error");
|
|
6236
|
-
if (errors.length > 0) {
|
|
6237
|
-
console.error(`
|
|
6238
|
-
Errors in ${targetsFilePath}:`);
|
|
6239
|
-
for (const error of errors) {
|
|
6240
|
-
const location = error.location ? ` [${error.location}]` : "";
|
|
6241
|
-
const prefix = useColors2 ? `${ANSI_RED3} \u2717${ANSI_RESET3}` : " \u2717";
|
|
6242
|
-
const message = useColors2 ? `${ANSI_RED3}${error.message}${ANSI_RESET3}` : error.message;
|
|
6243
|
-
console.error(`${prefix}${location} ${message}`);
|
|
6244
|
-
}
|
|
6245
|
-
throw new Error(`Targets file validation failed with ${errors.length} error(s)`);
|
|
6246
|
-
}
|
|
6247
|
-
const definitions = await readTargetDefinitions(targetsFilePath);
|
|
6742
|
+
const definitions = providerCatalog.definitions;
|
|
6743
|
+
const providersFilePath = providerCatalog.sourcePath;
|
|
6248
6744
|
const fileTargetSpec = options.fileTargetSpec;
|
|
6249
|
-
const
|
|
6250
|
-
const
|
|
6251
|
-
const
|
|
6745
|
+
const fileProviderLabel = options.fileProviderLabel ?? fileTargetSpec?.name ?? await readTestSuiteProvider(testFilePath);
|
|
6746
|
+
const providerChoice = pickProviderLabel({ cliProviderLabel, fileProviderLabel });
|
|
6747
|
+
const rawOverlayDefinition = providerChoice.source === "test-file" ? overlayTargetDefinition({ spec: fileTargetSpec, definitions, env, providersFilePath }) : void 0;
|
|
6748
|
+
const overlayDefinition = rawOverlayDefinition ? await resolveInlineDefinitionEnvironment(rawOverlayDefinition, testFilePath, "providers") : void 0;
|
|
6252
6749
|
const targetDefinition = withModelOverride(
|
|
6253
|
-
overlayDefinition ?? resolveUseTarget(
|
|
6750
|
+
overlayDefinition ?? resolveUseTarget(providerChoice.name, definitions, env, providersFilePath),
|
|
6254
6751
|
modelOverride
|
|
6255
6752
|
);
|
|
6256
6753
|
const effectiveDefinitions = overlayDefinition !== void 0 ? definitionsWithEffectiveTarget(definitions, targetDefinition) : definitions;
|
|
6257
6754
|
try {
|
|
6258
|
-
const
|
|
6755
|
+
const resolvedProvider = resolveProviderDefinition(targetDefinition, env, testFilePath, {
|
|
6259
6756
|
emitDeprecationWarnings: false
|
|
6260
6757
|
});
|
|
6261
6758
|
return {
|
|
6262
6759
|
definitions: effectiveDefinitions,
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
...
|
|
6760
|
+
resolvedProvider,
|
|
6761
|
+
providerLabel: providerChoice.name,
|
|
6762
|
+
providerSource: providerChoice.source,
|
|
6763
|
+
providersFilePath,
|
|
6764
|
+
...providerChoice.source === "test-file" && fileTargetSpec?.hooks ? { providerHooks: fileTargetSpec.hooks } : {}
|
|
6268
6765
|
};
|
|
6269
6766
|
} catch (error) {
|
|
6270
6767
|
const message = error instanceof Error ? error.message : String(error);
|
|
6271
|
-
throw new Error(`Failed to resolve
|
|
6768
|
+
throw new Error(`Failed to resolve provider '${providerChoice.name}': ${message}`);
|
|
6272
6769
|
}
|
|
6273
6770
|
}
|
|
6274
|
-
async function
|
|
6771
|
+
async function selectMultipleProviders(options) {
|
|
6275
6772
|
const {
|
|
6276
6773
|
testFilePath,
|
|
6277
6774
|
repoRoot,
|
|
6278
6775
|
cwd,
|
|
6279
|
-
|
|
6776
|
+
explicitProvidersPath,
|
|
6777
|
+
providerDefinitions,
|
|
6778
|
+
providerDefinitionsSource,
|
|
6779
|
+
requireExplicitProviderCatalog,
|
|
6780
|
+
allowLegacyTargetFiles,
|
|
6280
6781
|
env,
|
|
6281
|
-
|
|
6282
|
-
|
|
6782
|
+
providerLabels,
|
|
6783
|
+
providerRefs,
|
|
6283
6784
|
modelOverride
|
|
6284
6785
|
} = options;
|
|
6285
6786
|
const hooksMap = /* @__PURE__ */ new Map();
|
|
6286
6787
|
const labelsMap = /* @__PURE__ */ new Map();
|
|
6287
|
-
if (
|
|
6288
|
-
for (const ref of
|
|
6788
|
+
if (providerRefs) {
|
|
6789
|
+
for (const ref of providerRefs) {
|
|
6289
6790
|
if (ref.hooks) {
|
|
6290
6791
|
hooksMap.set(ref.name, ref.hooks);
|
|
6291
6792
|
}
|
|
@@ -6294,73 +6795,54 @@ async function selectMultipleTargets(options) {
|
|
|
6294
6795
|
}
|
|
6295
6796
|
}
|
|
6296
6797
|
}
|
|
6297
|
-
const
|
|
6298
|
-
|
|
6798
|
+
const providerCatalog = await readProviderCatalog({
|
|
6799
|
+
explicitProvidersPath,
|
|
6800
|
+
providerDefinitions,
|
|
6801
|
+
providerDefinitionsSource,
|
|
6802
|
+
requireExplicitProviderCatalog,
|
|
6299
6803
|
testFilePath,
|
|
6300
6804
|
repoRoot,
|
|
6301
|
-
cwd
|
|
6805
|
+
cwd,
|
|
6806
|
+
allowLegacyTargetFiles
|
|
6302
6807
|
});
|
|
6303
|
-
const
|
|
6304
|
-
const
|
|
6305
|
-
const useColors2 = isTTY();
|
|
6306
|
-
if (warnings.length > 0) {
|
|
6307
|
-
console.warn(`
|
|
6308
|
-
Warnings in ${targetsFilePath}:`);
|
|
6309
|
-
for (const warning of warnings) {
|
|
6310
|
-
const location = warning.location ? ` [${warning.location}]` : "";
|
|
6311
|
-
const prefix = useColors2 ? `${ANSI_YELLOW3} \u26A0${ANSI_RESET3}` : " \u26A0";
|
|
6312
|
-
const message = useColors2 ? `${ANSI_YELLOW3}${warning.message}${ANSI_RESET3}` : warning.message;
|
|
6313
|
-
console.warn(`${prefix}${location} ${message}`);
|
|
6314
|
-
}
|
|
6315
|
-
console.warn("");
|
|
6316
|
-
}
|
|
6317
|
-
const errors = validationResult.errors.filter((e) => e.severity === "error");
|
|
6318
|
-
if (errors.length > 0) {
|
|
6319
|
-
console.error(`
|
|
6320
|
-
Errors in ${targetsFilePath}:`);
|
|
6321
|
-
for (const error of errors) {
|
|
6322
|
-
const location = error.location ? ` [${error.location}]` : "";
|
|
6323
|
-
const prefix = useColors2 ? `${ANSI_RED3} \u2717${ANSI_RESET3}` : " \u2717";
|
|
6324
|
-
const message = useColors2 ? `${ANSI_RED3}${error.message}${ANSI_RESET3}` : error.message;
|
|
6325
|
-
console.error(`${prefix}${location} ${message}`);
|
|
6326
|
-
}
|
|
6327
|
-
throw new Error(`Targets file validation failed with ${errors.length} error(s)`);
|
|
6328
|
-
}
|
|
6329
|
-
const fileDefinitions = await readTargetDefinitions(targetsFilePath);
|
|
6808
|
+
const providersFilePath = providerCatalog.sourcePath;
|
|
6809
|
+
const fileDefinitions = providerCatalog.definitions;
|
|
6330
6810
|
const definitions = [...fileDefinitions];
|
|
6331
|
-
if (
|
|
6332
|
-
for (const ref of
|
|
6811
|
+
if (providerRefs) {
|
|
6812
|
+
for (const ref of providerRefs) {
|
|
6333
6813
|
if (ref.definition && !fileDefinitions.some((d) => d.name === ref.name)) {
|
|
6334
|
-
definitions.push(
|
|
6814
|
+
definitions.push(
|
|
6815
|
+
await resolveInlineDefinitionEnvironment(ref.definition, testFilePath, "providers")
|
|
6816
|
+
);
|
|
6335
6817
|
} else if (ref.use_target && !fileDefinitions.some((d) => d.name === ref.name)) {
|
|
6336
6818
|
definitions.push({ name: ref.name, use_target: ref.use_target });
|
|
6337
6819
|
}
|
|
6338
6820
|
}
|
|
6339
6821
|
}
|
|
6340
6822
|
const results = [];
|
|
6341
|
-
for (const name of
|
|
6823
|
+
for (const name of providerLabels) {
|
|
6342
6824
|
const targetDefinition = withModelOverride(
|
|
6343
|
-
resolveUseTarget(name, definitions, env,
|
|
6825
|
+
resolveUseTarget(name, definitions, env, providersFilePath),
|
|
6344
6826
|
modelOverride
|
|
6345
6827
|
);
|
|
6346
6828
|
const hooks = hooksMap.get(name);
|
|
6347
|
-
const
|
|
6829
|
+
const providerDisplayLabel = labelsMap.get(name);
|
|
6348
6830
|
try {
|
|
6349
|
-
const
|
|
6831
|
+
const resolvedProvider = resolveProviderDefinition(targetDefinition, env, testFilePath, {
|
|
6350
6832
|
emitDeprecationWarnings: false
|
|
6351
6833
|
});
|
|
6352
6834
|
results.push({
|
|
6353
6835
|
definitions,
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
...
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
...hooks && {
|
|
6836
|
+
resolvedProvider,
|
|
6837
|
+
providerLabel: name,
|
|
6838
|
+
...providerDisplayLabel ? { providerDisplayLabel } : {},
|
|
6839
|
+
providerSource: options.providerSource ?? "cli",
|
|
6840
|
+
providersFilePath,
|
|
6841
|
+
...hooks && { providerHooks: hooks }
|
|
6360
6842
|
});
|
|
6361
6843
|
} catch (error) {
|
|
6362
6844
|
const message = error instanceof Error ? error.message : String(error);
|
|
6363
|
-
throw new Error(`Failed to resolve
|
|
6845
|
+
throw new Error(`Failed to resolve provider '${name}': ${message}`);
|
|
6364
6846
|
}
|
|
6365
6847
|
}
|
|
6366
6848
|
return results;
|
|
@@ -6459,7 +6941,7 @@ var DEFAULT_WORKERS = 3;
|
|
|
6459
6941
|
var loadCjsModule = createNodeRequire(import.meta.url);
|
|
6460
6942
|
var micromatch = loadCjsModule("micromatch");
|
|
6461
6943
|
async function loadCliEvalSuite(testFilePath, repoRoot, options) {
|
|
6462
|
-
if (
|
|
6944
|
+
if (path13.extname(testFilePath).toLowerCase() === ".json") {
|
|
6463
6945
|
const adapterSuite = readAgentSkillsEvalsFile(testFilePath);
|
|
6464
6946
|
return loadTestSuiteFromYamlObject(
|
|
6465
6947
|
testFilePath,
|
|
@@ -6575,8 +7057,8 @@ function resultsRepoOverride(value) {
|
|
|
6575
7057
|
if (!value) {
|
|
6576
7058
|
return {};
|
|
6577
7059
|
}
|
|
6578
|
-
if (value === "current" || value === "." || value.startsWith("./") || value.startsWith("../") || value.startsWith("/") || value.startsWith("~/") || value.startsWith("~\\") || /^[A-Za-z]:[/\\]/.test(value)) {
|
|
6579
|
-
return { repo_path: value === "current" ? "." : value };
|
|
7060
|
+
if (value === "current" || value === "current/." || value === "." || value.startsWith("./") || value.startsWith("../") || value.startsWith("/") || value.startsWith("~/") || value.startsWith("~\\") || /^[A-Za-z]:[/\\]/.test(value)) {
|
|
7061
|
+
return { repo_path: value === "current" || value === "current/." ? "." : value };
|
|
6580
7062
|
}
|
|
6581
7063
|
return { repo: value };
|
|
6582
7064
|
}
|
|
@@ -6613,13 +7095,32 @@ function normalizeSourceMetadataByEvalFile(value) {
|
|
|
6613
7095
|
const entries = [...value.entries()].filter(
|
|
6614
7096
|
(entry) => typeof entry[0] === "string" && typeof entry[1] === "object" && entry[1] !== null && !Array.isArray(entry[1])
|
|
6615
7097
|
);
|
|
6616
|
-
return entries.length > 0 ? new Map(entries.map(([key, metadata]) => [
|
|
7098
|
+
return entries.length > 0 ? new Map(entries.map(([key, metadata]) => [path13.resolve(key), metadata])) : void 0;
|
|
6617
7099
|
}
|
|
6618
7100
|
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
6619
7101
|
const entries = Object.entries(value).filter(
|
|
6620
7102
|
(entry) => typeof entry[1] === "object" && entry[1] !== null && !Array.isArray(entry[1])
|
|
6621
7103
|
);
|
|
6622
|
-
return entries.length > 0 ? new Map(entries.map(([key, metadata]) => [
|
|
7104
|
+
return entries.length > 0 ? new Map(entries.map(([key, metadata]) => [path13.resolve(key), metadata])) : void 0;
|
|
7105
|
+
}
|
|
7106
|
+
return void 0;
|
|
7107
|
+
}
|
|
7108
|
+
function normalizeProviderCatalogPathByEvalFile(value) {
|
|
7109
|
+
if (value instanceof Map) {
|
|
7110
|
+
const entries = [...value.entries()].filter(
|
|
7111
|
+
(entry) => typeof entry[0] === "string" && typeof entry[1] === "string" && entry[1].trim().length > 0
|
|
7112
|
+
);
|
|
7113
|
+
return entries.length > 0 ? new Map(
|
|
7114
|
+
entries.map(([key, providerPath]) => [path13.resolve(key), path13.resolve(providerPath)])
|
|
7115
|
+
) : void 0;
|
|
7116
|
+
}
|
|
7117
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
7118
|
+
const entries = Object.entries(value).filter(
|
|
7119
|
+
(entry) => typeof entry[1] === "string" && entry[1].trim().length > 0
|
|
7120
|
+
);
|
|
7121
|
+
return entries.length > 0 ? new Map(
|
|
7122
|
+
entries.map(([key, providerPath]) => [path13.resolve(key), path13.resolve(providerPath)])
|
|
7123
|
+
) : void 0;
|
|
6623
7124
|
}
|
|
6624
7125
|
return void 0;
|
|
6625
7126
|
}
|
|
@@ -6633,10 +7134,10 @@ var LEGACY_OUTPUT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
6633
7134
|
".htm"
|
|
6634
7135
|
]);
|
|
6635
7136
|
function looksLikeLegacyOutputFilePath(value) {
|
|
6636
|
-
return LEGACY_OUTPUT_FILE_EXTENSIONS.has(
|
|
7137
|
+
return LEGACY_OUTPUT_FILE_EXTENSIONS.has(path13.extname(value).toLowerCase());
|
|
6637
7138
|
}
|
|
6638
7139
|
function outputFileMigrationMessage(value) {
|
|
6639
|
-
const ext =
|
|
7140
|
+
const ext = path13.extname(value).toLowerCase();
|
|
6640
7141
|
const removalHint = ext === ".xml" ? "JUnit XML export from agentv eval has been removed." : "Flat result file export from agentv eval has been removed.";
|
|
6641
7142
|
return `--output expects a run directory, not a file path: ${value}
|
|
6642
7143
|
${removalHint} Set --output <dir> for the canonical run artifacts; AgentV always writes <dir>/${RESULT_INDEX_FILENAME}.`;
|
|
@@ -6644,7 +7145,7 @@ ${removalHint} Set --output <dir> for the canonical run artifacts; AgentV always
|
|
|
6644
7145
|
function artifactsMigrationMessage(artifactsDir, outputDir) {
|
|
6645
7146
|
const lines = [`--artifacts was removed from agentv eval. Use --output ${artifactsDir} instead.`];
|
|
6646
7147
|
if (outputDir && looksLikeLegacyOutputFilePath(outputDir)) {
|
|
6647
|
-
const ext =
|
|
7148
|
+
const ext = path13.extname(outputDir).toLowerCase();
|
|
6648
7149
|
lines.push(
|
|
6649
7150
|
ext === ".xml" ? "JUnit XML export from agentv eval has been removed." : "Flat result file export from agentv eval has been removed."
|
|
6650
7151
|
);
|
|
@@ -6737,17 +7238,19 @@ function normalizeOptions(rawOptions, config, yamlExecution) {
|
|
|
6737
7238
|
const configWorkers = config?.execution?.maxConcurrency ?? yamlExecution?.max_concurrency;
|
|
6738
7239
|
const workers = cliWorkers ?? configWorkers ?? 0;
|
|
6739
7240
|
const cliOutputDir = normalizeString(rawOptions.output);
|
|
6740
|
-
const
|
|
6741
|
-
let
|
|
6742
|
-
let
|
|
6743
|
-
if (Array.isArray(
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
7241
|
+
const rawProvider = rawOptions.provider;
|
|
7242
|
+
let cliProviderLabels = [];
|
|
7243
|
+
let singleProvider;
|
|
7244
|
+
if (Array.isArray(rawProvider)) {
|
|
7245
|
+
cliProviderLabels = rawProvider.filter(
|
|
7246
|
+
(v) => typeof v === "string" && v.trim().length > 0
|
|
7247
|
+
);
|
|
7248
|
+
singleProvider = cliProviderLabels.length === 1 ? cliProviderLabels[0] : void 0;
|
|
7249
|
+
} else if (typeof rawProvider === "string") {
|
|
7250
|
+
const trimmed = rawProvider.trim();
|
|
6748
7251
|
if (trimmed.length > 0 && trimmed !== "default") {
|
|
6749
|
-
|
|
6750
|
-
|
|
7252
|
+
cliProviderLabels = [trimmed];
|
|
7253
|
+
singleProvider = trimmed;
|
|
6751
7254
|
}
|
|
6752
7255
|
}
|
|
6753
7256
|
const cliAgentTimeout = normalizeOptionalNumber(rawOptions.agentTimeout);
|
|
@@ -6783,9 +7286,13 @@ function normalizeOptions(rawOptions, config, yamlExecution) {
|
|
|
6783
7286
|
};
|
|
6784
7287
|
const cliTags = splitCliTags(rawOptions.tag);
|
|
6785
7288
|
return {
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
7289
|
+
provider: singleProvider,
|
|
7290
|
+
cliProviderLabels,
|
|
7291
|
+
providersPath: normalizeString(rawOptions.providers),
|
|
7292
|
+
allowLegacyTargetFiles: normalizeBoolean(rawOptions.allowLegacyTargetFiles),
|
|
7293
|
+
providerCatalogPathByEvalFile: normalizeProviderCatalogPathByEvalFile(
|
|
7294
|
+
rawOptions.providerCatalogPathByEvalFile
|
|
7295
|
+
),
|
|
6789
7296
|
filter: normalizeFilter(rawOptions.filter),
|
|
6790
7297
|
workers: workers > 0 ? workers : void 0,
|
|
6791
7298
|
outputDir: cliOutputDir ?? configOutputDir,
|
|
@@ -6832,7 +7339,7 @@ function normalizeOptions(rawOptions, config, yamlExecution) {
|
|
|
6832
7339
|
};
|
|
6833
7340
|
}
|
|
6834
7341
|
function withSourceMetadata(result, testFilePath, options) {
|
|
6835
|
-
const sourceMetadata = options.sourceMetadataByEvalFile?.get(
|
|
7342
|
+
const sourceMetadata = options.sourceMetadataByEvalFile?.get(path13.resolve(testFilePath));
|
|
6836
7343
|
if (!sourceMetadata) {
|
|
6837
7344
|
return result;
|
|
6838
7345
|
}
|
|
@@ -6855,11 +7362,11 @@ function deriveEvalResultGroupName(evalFilePath) {
|
|
|
6855
7362
|
if (!evalFilePath) {
|
|
6856
7363
|
return "eval";
|
|
6857
7364
|
}
|
|
6858
|
-
return
|
|
7365
|
+
return path13.basename(evalFilePath).replace(/\.eval\.ya?ml$/i, "").replace(/\.ya?ml$/i, "").replace(/[^A-Za-z0-9._-]/g, "-") || "eval";
|
|
6859
7366
|
}
|
|
6860
7367
|
var CLI_RUNTIME_SOURCE_OPTION_KEYS = [
|
|
6861
|
-
"
|
|
6862
|
-
"
|
|
7368
|
+
"provider",
|
|
7369
|
+
"providers",
|
|
6863
7370
|
"filter",
|
|
6864
7371
|
"tag",
|
|
6865
7372
|
"excludeTag",
|
|
@@ -6902,10 +7409,10 @@ function toRuntimeSourcePath(cwd, filePath) {
|
|
|
6902
7409
|
if (!trimmed) {
|
|
6903
7410
|
return void 0;
|
|
6904
7411
|
}
|
|
6905
|
-
const resolved =
|
|
6906
|
-
const relative =
|
|
6907
|
-
const displayPath = relative && !relative.startsWith("..") && !
|
|
6908
|
-
return displayPath.split(
|
|
7412
|
+
const resolved = path13.isAbsolute(trimmed) ? trimmed : path13.resolve(cwd, trimmed);
|
|
7413
|
+
const relative = path13.relative(cwd, resolved);
|
|
7414
|
+
const displayPath = relative && !relative.startsWith("..") && !path13.isAbsolute(relative) ? relative : trimmed;
|
|
7415
|
+
return displayPath.split(path13.sep).join("/");
|
|
6909
7416
|
}
|
|
6910
7417
|
function uniqueRuntimeSourcePaths(values) {
|
|
6911
7418
|
return [...new Set([...values].filter((value) => Boolean(value)))].sort();
|
|
@@ -6915,7 +7422,7 @@ function testSourceEvalPath(cwd, test) {
|
|
|
6915
7422
|
}
|
|
6916
7423
|
function testSourceEvalPathForComparison(test) {
|
|
6917
7424
|
const sourcePath = test.source?.evalFileAbsolutePath ?? test.source?.evalFilePath;
|
|
6918
|
-
return sourcePath ?
|
|
7425
|
+
return sourcePath ? path13.resolve(sourcePath) : void 0;
|
|
6919
7426
|
}
|
|
6920
7427
|
function buildRuntimeConfigSource(params) {
|
|
6921
7428
|
const inlineFingerprints = /* @__PURE__ */ new Set();
|
|
@@ -6946,7 +7453,7 @@ function buildRuntimeSourceMetadata(params) {
|
|
|
6946
7453
|
params.activeTestFiles.map((filePath) => toRuntimeSourcePath(params.cwd, filePath))
|
|
6947
7454
|
);
|
|
6948
7455
|
const activeResolvedFiles = new Set(
|
|
6949
|
-
params.activeTestFiles.map((filePath) =>
|
|
7456
|
+
params.activeTestFiles.map((filePath) => path13.resolve(filePath))
|
|
6950
7457
|
);
|
|
6951
7458
|
const sourceEvalFiles = uniqueRuntimeSourcePaths(
|
|
6952
7459
|
params.sourceTests.map((test) => testSourceEvalPath(params.cwd, test))
|
|
@@ -6977,22 +7484,21 @@ function applyExperimentOptions(options, experiment) {
|
|
|
6977
7484
|
if (!experiment) {
|
|
6978
7485
|
return options;
|
|
6979
7486
|
}
|
|
6980
|
-
const
|
|
6981
|
-
const
|
|
7487
|
+
const experimentProviderRefs = buildExperimentTargetRefs(experiment);
|
|
7488
|
+
const experimentProviderLabels = experimentProviderRefs?.map((target) => target.name) ?? [];
|
|
6982
7489
|
const experimentTarget = experiment.target && experiment.target.trim().length > 0 ? experiment.target : void 0;
|
|
6983
|
-
const
|
|
7490
|
+
const experimentProviders = options.cliProviderLabels.length === 0 ? experimentProviderLabels.length > 0 ? experimentProviderLabels : experimentTarget ? [experimentTarget] : void 0 : void 0;
|
|
6984
7491
|
return {
|
|
6985
7492
|
...options,
|
|
6986
|
-
target: options.target,
|
|
6987
7493
|
agentTimeoutSeconds: options.agentTimeoutSeconds ?? experiment.timeoutSeconds,
|
|
6988
7494
|
workspacePath: options.workspacePath,
|
|
6989
7495
|
budgetUsd: options.budgetUsd ?? experiment.budgetUsd,
|
|
6990
7496
|
threshold: options.threshold ?? experiment.threshold,
|
|
6991
7497
|
experimentConfig: experiment,
|
|
6992
7498
|
experimentMetadata: buildExperimentArtifactMetadata(experiment),
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
7499
|
+
experimentProviderLabels: experimentProviders,
|
|
7500
|
+
experimentProviderRefs: options.cliProviderLabels.length === 0 ? experimentProviderRefs : void 0,
|
|
7501
|
+
providerModelOverride: options.providerModelOverride ?? experiment.model,
|
|
6996
7502
|
experimentTrialsConfig: buildExperimentTrialsConfig(experiment)
|
|
6997
7503
|
};
|
|
6998
7504
|
}
|
|
@@ -7020,11 +7526,7 @@ function buildExperimentTrialsConfig(experiment) {
|
|
|
7020
7526
|
}
|
|
7021
7527
|
return {
|
|
7022
7528
|
count: experiment.repeat.count,
|
|
7023
|
-
strategy: experiment.repeat.strategy
|
|
7024
|
-
...experiment.repeat.costLimitUsd !== void 0 && {
|
|
7025
|
-
costLimitUsd: experiment.repeat.costLimitUsd
|
|
7026
|
-
},
|
|
7027
|
-
...experiment.repeat.earlyExit !== void 0 && { earlyExit: experiment.repeat.earlyExit }
|
|
7529
|
+
strategy: experiment.repeat.strategy
|
|
7028
7530
|
};
|
|
7029
7531
|
}
|
|
7030
7532
|
return void 0;
|
|
@@ -7036,9 +7538,7 @@ function buildRunOverrideTrialsConfig(run) {
|
|
|
7036
7538
|
}
|
|
7037
7539
|
return {
|
|
7038
7540
|
count: repeat.count,
|
|
7039
|
-
strategy: repeat.strategy
|
|
7040
|
-
...repeat.costLimitUsd !== void 0 && { costLimitUsd: repeat.costLimitUsd },
|
|
7041
|
-
...repeat.earlyExit !== void 0 && { earlyExit: repeat.earlyExit }
|
|
7541
|
+
strategy: repeat.strategy
|
|
7042
7542
|
};
|
|
7043
7543
|
}
|
|
7044
7544
|
function resolveEffectiveRunPolicy(params) {
|
|
@@ -7100,7 +7600,7 @@ function createProgressReporter(maxWorkers, options) {
|
|
|
7100
7600
|
};
|
|
7101
7601
|
}
|
|
7102
7602
|
function makeTestCaseKey(testFilePath, testId) {
|
|
7103
|
-
return `${
|
|
7603
|
+
return `${path13.resolve(testFilePath)}::${testId}`;
|
|
7104
7604
|
}
|
|
7105
7605
|
function resolveTargetLabel(requestedName, resolvedName) {
|
|
7106
7606
|
if (resolvedName !== requestedName) {
|
|
@@ -7139,23 +7639,23 @@ function buildTargetLabelSuffix(providerLabel, target) {
|
|
|
7139
7639
|
return `[${parts.join(", ")}]`;
|
|
7140
7640
|
}
|
|
7141
7641
|
function applyVerboseOverride(selection, cliVerbose) {
|
|
7142
|
-
const {
|
|
7143
|
-
if (
|
|
7642
|
+
const { resolvedProvider } = selection;
|
|
7643
|
+
if (resolvedProvider.kind !== "cli") {
|
|
7144
7644
|
return selection;
|
|
7145
7645
|
}
|
|
7146
7646
|
return {
|
|
7147
7647
|
...selection,
|
|
7148
|
-
|
|
7149
|
-
...
|
|
7648
|
+
resolvedProvider: {
|
|
7649
|
+
...resolvedProvider,
|
|
7150
7650
|
config: {
|
|
7151
|
-
...
|
|
7651
|
+
...resolvedProvider.config,
|
|
7152
7652
|
verbose: cliVerbose
|
|
7153
7653
|
}
|
|
7154
7654
|
}
|
|
7155
7655
|
};
|
|
7156
7656
|
}
|
|
7157
7657
|
function targetVariantForSelection(selection) {
|
|
7158
|
-
const target = selection.
|
|
7658
|
+
const target = selection.resolvedProvider;
|
|
7159
7659
|
if (target.kind === "replay") {
|
|
7160
7660
|
return target.config.variant;
|
|
7161
7661
|
}
|
|
@@ -7197,20 +7697,24 @@ async function readExistingResultsFromRunDir(runDir) {
|
|
|
7197
7697
|
}
|
|
7198
7698
|
return results;
|
|
7199
7699
|
}
|
|
7700
|
+
async function collectTerminalSummaryResults(params) {
|
|
7701
|
+
const rawResults = params.isResumeAppend ? await (params.readExistingResults ?? readExistingResultsFromRunDir)(params.runDir) : params.allResults;
|
|
7702
|
+
return deduplicateByTestIdTarget(rawResults);
|
|
7703
|
+
}
|
|
7200
7704
|
async function resolveRerunFailedRunDir(cwd, source) {
|
|
7201
7705
|
const trimmed = source.trim();
|
|
7202
7706
|
if (!trimmed) {
|
|
7203
7707
|
throw new Error("--rerun-failed requires a run ID, run workspace, or index.jsonl path.");
|
|
7204
7708
|
}
|
|
7205
|
-
const candidate =
|
|
7709
|
+
const candidate = path13.isAbsolute(trimmed) ? trimmed : path13.resolve(cwd, trimmed);
|
|
7206
7710
|
if (existsSync5(candidate)) {
|
|
7207
|
-
if (
|
|
7711
|
+
if (path13.basename(candidate) !== RESULT_INDEX_FILENAME) {
|
|
7208
7712
|
return candidate;
|
|
7209
7713
|
}
|
|
7210
|
-
const manifestDir =
|
|
7211
|
-
return
|
|
7714
|
+
const manifestDir = path13.dirname(candidate);
|
|
7715
|
+
return path13.basename(manifestDir) === ".internal" ? path13.dirname(manifestDir) : manifestDir;
|
|
7212
7716
|
}
|
|
7213
|
-
const runIdCandidate =
|
|
7717
|
+
const runIdCandidate = path13.join(cwd, ".agentv", "results", trimmed);
|
|
7214
7718
|
if (existsSync5(runIdCandidate)) {
|
|
7215
7719
|
return runIdCandidate;
|
|
7216
7720
|
}
|
|
@@ -7219,14 +7723,23 @@ async function resolveRerunFailedRunDir(cwd, source) {
|
|
|
7219
7723
|
);
|
|
7220
7724
|
}
|
|
7221
7725
|
async function prepareFileMetadata(params) {
|
|
7222
|
-
const {
|
|
7726
|
+
const {
|
|
7727
|
+
testFilePath,
|
|
7728
|
+
repoRoot,
|
|
7729
|
+
cwd,
|
|
7730
|
+
options,
|
|
7731
|
+
providerCatalogPath,
|
|
7732
|
+
providerDefinitions,
|
|
7733
|
+
providerDefinitionsSource,
|
|
7734
|
+
suiteFilter
|
|
7735
|
+
} = params;
|
|
7223
7736
|
await ensureFileExists(testFilePath, "Test file");
|
|
7224
7737
|
await loadEnvFromHierarchy({
|
|
7225
7738
|
testFilePath,
|
|
7226
7739
|
repoRoot,
|
|
7227
7740
|
verbose: options.verbose
|
|
7228
7741
|
});
|
|
7229
|
-
const relativePath =
|
|
7742
|
+
const relativePath = path13.relative(cwd, testFilePath);
|
|
7230
7743
|
const category = deriveCategory(relativePath);
|
|
7231
7744
|
const suite = await loadCliEvalSuite(testFilePath, repoRoot, {
|
|
7232
7745
|
verbose: options.verbose,
|
|
@@ -7235,21 +7748,24 @@ async function prepareFileMetadata(params) {
|
|
|
7235
7748
|
});
|
|
7236
7749
|
const experimentOptions = applyExperimentOptions(options, suite.experimentConfig);
|
|
7237
7750
|
const effectiveOptions = experimentOptions.workers === void 0 && suite.workers !== void 0 ? { ...experimentOptions, workers: suite.workers } : experimentOptions;
|
|
7751
|
+
const effectiveProviderCatalogPath = effectiveOptions.providersPath ?? providerCatalogPath;
|
|
7238
7752
|
const testCases = suiteFilter && effectiveOptions.filter ? suite.tests.filter(
|
|
7239
7753
|
(testCase) => matchesTestFilter(testCase.id, effectiveOptions.filter ?? "")
|
|
7240
7754
|
) : suite.tests;
|
|
7241
7755
|
const testIds = testCases.map((value) => value.id);
|
|
7242
7756
|
const suiteTargetSpec = suite.targetSpec;
|
|
7757
|
+
const suiteDefaults = suite.defaults;
|
|
7243
7758
|
const suiteTargets = suiteTargetSpec ? [suiteTargetSpec.name] : suite.targets;
|
|
7759
|
+
const fileOptions = suiteDefaults?.grader && !effectiveOptions.graderTarget ? { ...effectiveOptions, defaultGraderTarget: suiteDefaults.grader } : effectiveOptions;
|
|
7244
7760
|
const defaultBudgetUsd = effectiveOptions.cliBudgetUsd === void 0 ? effectiveOptions.budgetUsd ?? suite.budgetUsd : void 0;
|
|
7245
7761
|
const suiteDefaultThreshold = suite.defaultTest?.threshold ?? suite.threshold;
|
|
7246
7762
|
if (testCases.length === 0) {
|
|
7247
7763
|
return {
|
|
7248
|
-
options:
|
|
7764
|
+
options: fileOptions,
|
|
7249
7765
|
testIds,
|
|
7250
7766
|
testCases,
|
|
7251
7767
|
selections: [],
|
|
7252
|
-
trialsConfig:
|
|
7768
|
+
trialsConfig: fileOptions.experimentTrialsConfig,
|
|
7253
7769
|
suiteTargets,
|
|
7254
7770
|
yamlCache: suite.cacheConfig?.enabled,
|
|
7255
7771
|
yamlCachePath: suite.cacheConfig?.cachePath,
|
|
@@ -7261,42 +7777,47 @@ async function prepareFileMetadata(params) {
|
|
|
7261
7777
|
};
|
|
7262
7778
|
}
|
|
7263
7779
|
let selections;
|
|
7264
|
-
if (
|
|
7780
|
+
if (fileOptions.transcript) {
|
|
7265
7781
|
const transcriptSelection = {
|
|
7266
7782
|
definitions: [],
|
|
7267
|
-
|
|
7783
|
+
resolvedProvider: {
|
|
7268
7784
|
kind: "transcript",
|
|
7269
7785
|
name: "transcript",
|
|
7270
7786
|
config: {}
|
|
7271
7787
|
},
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7788
|
+
providerLabel: "transcript",
|
|
7789
|
+
providerSource: "cli",
|
|
7790
|
+
providersFilePath: fileOptions.transcript
|
|
7275
7791
|
};
|
|
7276
7792
|
selections = [
|
|
7277
7793
|
{
|
|
7278
7794
|
selection: transcriptSelection,
|
|
7279
|
-
inlineTargetLabel: `transcript (${
|
|
7795
|
+
inlineTargetLabel: `transcript (${path13.basename(fileOptions.transcript)})`
|
|
7280
7796
|
}
|
|
7281
7797
|
];
|
|
7282
|
-
} else if (suite.inlineTarget &&
|
|
7798
|
+
} else if (suite.inlineTarget && fileOptions.cliProviderLabels.length === 0) {
|
|
7283
7799
|
const targetDefinition = suite.inlineTarget;
|
|
7284
|
-
const
|
|
7285
|
-
|
|
7286
|
-
|
|
7800
|
+
const resolvedProvider = resolveProviderDefinition(
|
|
7801
|
+
targetDefinition,
|
|
7802
|
+
process.env,
|
|
7803
|
+
testFilePath,
|
|
7804
|
+
{
|
|
7805
|
+
emitDeprecationWarnings: false
|
|
7806
|
+
}
|
|
7807
|
+
);
|
|
7287
7808
|
selections = [
|
|
7288
7809
|
{
|
|
7289
7810
|
selection: {
|
|
7290
7811
|
definitions: [targetDefinition],
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7812
|
+
resolvedProvider,
|
|
7813
|
+
providerLabel: targetDefinition.name,
|
|
7814
|
+
providerSource: "test-file",
|
|
7815
|
+
providersFilePath: testFilePath
|
|
7295
7816
|
},
|
|
7296
|
-
inlineTargetLabel: resolveTargetLabel(targetDefinition.name,
|
|
7817
|
+
inlineTargetLabel: resolveTargetLabel(targetDefinition.name, resolvedProvider.name)
|
|
7297
7818
|
}
|
|
7298
7819
|
];
|
|
7299
|
-
} else if (suite.providerFactory &&
|
|
7820
|
+
} else if (suite.providerFactory && fileOptions.cliProviderLabels.length === 0) {
|
|
7300
7821
|
const taskTarget = {
|
|
7301
7822
|
kind: "mock",
|
|
7302
7823
|
name: "custom-task",
|
|
@@ -7307,89 +7828,100 @@ async function prepareFileMetadata(params) {
|
|
|
7307
7828
|
{
|
|
7308
7829
|
selection: {
|
|
7309
7830
|
definitions: [],
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7831
|
+
resolvedProvider: taskTarget,
|
|
7832
|
+
providerLabel: "custom-task",
|
|
7833
|
+
providerSource: "test-file",
|
|
7834
|
+
providersFilePath: testFilePath
|
|
7314
7835
|
},
|
|
7315
7836
|
inlineTargetLabel: "custom-task"
|
|
7316
7837
|
}
|
|
7317
7838
|
];
|
|
7318
7839
|
} else {
|
|
7319
|
-
const
|
|
7320
|
-
const
|
|
7840
|
+
const cliProviderLabels = fileOptions.cliProviderLabels;
|
|
7841
|
+
const experimentProviderLabels = fileOptions.experimentProviderLabels ?? [];
|
|
7321
7842
|
const suiteTargetSpec2 = suite.targetSpec;
|
|
7322
|
-
const
|
|
7323
|
-
const
|
|
7324
|
-
const
|
|
7325
|
-
let
|
|
7326
|
-
let
|
|
7327
|
-
let
|
|
7328
|
-
if (
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
} else if (
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
} else if (
|
|
7336
|
-
|
|
7337
|
-
|
|
7843
|
+
const suiteProviderLabels = suiteTargetSpec2 ? [suiteTargetSpec2.name] : suite.targets;
|
|
7844
|
+
const suiteProviderRefs = suite.targetRefs;
|
|
7845
|
+
const experimentProviderRefs = fileOptions.experimentProviderRefs;
|
|
7846
|
+
let providerLabels;
|
|
7847
|
+
let providerRefs;
|
|
7848
|
+
let providerSource = "test-file";
|
|
7849
|
+
if (cliProviderLabels.length > 0) {
|
|
7850
|
+
providerLabels = cliProviderLabels;
|
|
7851
|
+
providerRefs = experimentProviderRefs;
|
|
7852
|
+
providerSource = "cli";
|
|
7853
|
+
} else if (experimentProviderLabels.length > 0) {
|
|
7854
|
+
providerLabels = experimentProviderLabels;
|
|
7855
|
+
providerRefs = experimentProviderRefs;
|
|
7856
|
+
} else if (suiteProviderLabels && suiteProviderLabels.length > 0) {
|
|
7857
|
+
providerLabels = suiteProviderLabels;
|
|
7858
|
+
providerRefs = suiteProviderRefs;
|
|
7859
|
+
} else if (suiteDefaults?.provider) {
|
|
7860
|
+
providerLabels = [suiteDefaults.provider];
|
|
7861
|
+
providerRefs = void 0;
|
|
7338
7862
|
} else {
|
|
7339
|
-
|
|
7340
|
-
|
|
7863
|
+
providerLabels = [];
|
|
7864
|
+
providerRefs = void 0;
|
|
7341
7865
|
}
|
|
7342
|
-
if (
|
|
7343
|
-
const multiSelections = await
|
|
7866
|
+
if (providerLabels.length > 1 || providerLabels.length === 1 && providerRefs) {
|
|
7867
|
+
const multiSelections = await selectMultipleProviders({
|
|
7344
7868
|
testFilePath,
|
|
7345
7869
|
repoRoot,
|
|
7346
7870
|
cwd,
|
|
7347
|
-
|
|
7871
|
+
explicitProvidersPath: effectiveProviderCatalogPath,
|
|
7872
|
+
providerDefinitions,
|
|
7873
|
+
providerDefinitionsSource,
|
|
7874
|
+
requireExplicitProviderCatalog: true,
|
|
7875
|
+
allowLegacyTargetFiles: fileOptions.allowLegacyTargetFiles,
|
|
7348
7876
|
env: process.env,
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
modelOverride:
|
|
7877
|
+
providerLabels,
|
|
7878
|
+
providerRefs,
|
|
7879
|
+
providerSource,
|
|
7880
|
+
modelOverride: fileOptions.providerModelOverride
|
|
7353
7881
|
});
|
|
7354
7882
|
selections = multiSelections.map((sel) => ({
|
|
7355
7883
|
selection: sel,
|
|
7356
|
-
inlineTargetLabel: sel.
|
|
7884
|
+
inlineTargetLabel: sel.providerDisplayLabel ?? resolveTargetLabel(sel.providerLabel, sel.resolvedProvider.name)
|
|
7357
7885
|
}));
|
|
7358
7886
|
} else {
|
|
7359
|
-
const selection = await
|
|
7887
|
+
const selection = await selectProvider({
|
|
7360
7888
|
testFilePath,
|
|
7361
7889
|
repoRoot,
|
|
7362
7890
|
cwd,
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7891
|
+
explicitProvidersPath: effectiveProviderCatalogPath,
|
|
7892
|
+
providerDefinitions,
|
|
7893
|
+
providerDefinitionsSource,
|
|
7894
|
+
requireExplicitProviderCatalog: true,
|
|
7895
|
+
allowLegacyTargetFiles: fileOptions.allowLegacyTargetFiles,
|
|
7896
|
+
cliProviderLabel: providerSource === "cli" ? providerLabels.length === 1 ? providerLabels[0] : fileOptions.provider : fileOptions.provider,
|
|
7897
|
+
fileProviderLabel: providerSource === "test-file" && providerLabels.length === 1 ? providerLabels[0] : void 0,
|
|
7898
|
+
fileTargetSpec: providerSource === "test-file" && providerLabels.length === 1 ? suiteTargetSpec2 : void 0,
|
|
7899
|
+
modelOverride: fileOptions.providerModelOverride,
|
|
7368
7900
|
env: process.env
|
|
7369
7901
|
});
|
|
7370
|
-
const
|
|
7902
|
+
const singleProviderRef = providerRefs?.find((ref) => ref.name === selection.providerLabel);
|
|
7371
7903
|
const augmentedSelection = {
|
|
7372
7904
|
...selection,
|
|
7373
|
-
...
|
|
7374
|
-
...
|
|
7905
|
+
...singleProviderRef?.label ? { providerDisplayLabel: singleProviderRef.label } : {},
|
|
7906
|
+
...singleProviderRef?.hooks ? { providerHooks: singleProviderRef.hooks } : {}
|
|
7375
7907
|
};
|
|
7376
7908
|
selections = [
|
|
7377
7909
|
{
|
|
7378
7910
|
selection: augmentedSelection,
|
|
7379
|
-
inlineTargetLabel: augmentedSelection.
|
|
7380
|
-
augmentedSelection.
|
|
7381
|
-
augmentedSelection.
|
|
7911
|
+
inlineTargetLabel: augmentedSelection.providerDisplayLabel ?? resolveTargetLabel(
|
|
7912
|
+
augmentedSelection.providerLabel,
|
|
7913
|
+
augmentedSelection.resolvedProvider.name
|
|
7382
7914
|
)
|
|
7383
7915
|
}
|
|
7384
7916
|
];
|
|
7385
7917
|
}
|
|
7386
7918
|
}
|
|
7387
7919
|
return {
|
|
7388
|
-
options:
|
|
7920
|
+
options: fileOptions,
|
|
7389
7921
|
testIds,
|
|
7390
7922
|
testCases,
|
|
7391
7923
|
selections,
|
|
7392
|
-
trialsConfig:
|
|
7924
|
+
trialsConfig: fileOptions.experimentTrialsConfig,
|
|
7393
7925
|
suiteTargets,
|
|
7394
7926
|
yamlCache: suite.cacheConfig?.enabled,
|
|
7395
7927
|
yamlCachePath: suite.cacheConfig?.cachePath,
|
|
@@ -7400,7 +7932,7 @@ async function prepareFileMetadata(params) {
|
|
|
7400
7932
|
providerFactory: suite.providerFactory
|
|
7401
7933
|
};
|
|
7402
7934
|
}
|
|
7403
|
-
function
|
|
7935
|
+
function buildTaskBundleProviderSelections(activeTestFiles, fileMetadata) {
|
|
7404
7936
|
return activeTestFiles.flatMap((testFilePath) => {
|
|
7405
7937
|
const meta = fileMetadata.get(testFilePath);
|
|
7406
7938
|
if (!meta) {
|
|
@@ -7408,8 +7940,8 @@ function buildTaskBundleTargetSelections(activeTestFiles, fileMetadata) {
|
|
|
7408
7940
|
}
|
|
7409
7941
|
return meta.selections.map(({ selection }) => ({
|
|
7410
7942
|
evalFileAbsolutePath: testFilePath,
|
|
7411
|
-
|
|
7412
|
-
|
|
7943
|
+
providerLabel: selection.providerLabel,
|
|
7944
|
+
resolvedProviderName: selection.resolvedProvider.name,
|
|
7413
7945
|
definitions: selection.definitions
|
|
7414
7946
|
}));
|
|
7415
7947
|
});
|
|
@@ -7438,22 +7970,22 @@ async function runSingleEvalFile(params) {
|
|
|
7438
7970
|
failOnError,
|
|
7439
7971
|
providerFactory
|
|
7440
7972
|
} = params;
|
|
7441
|
-
const
|
|
7973
|
+
const providerLabel = selection.providerLabel;
|
|
7442
7974
|
const replayRecording = options.recordReplay ? {
|
|
7443
|
-
fixturesPath:
|
|
7444
|
-
sourceTarget:
|
|
7975
|
+
fixturesPath: path13.resolve(options.recordReplay),
|
|
7976
|
+
sourceTarget: providerLabel,
|
|
7445
7977
|
variant: options.recordReplayVariant
|
|
7446
7978
|
} : void 0;
|
|
7447
7979
|
await ensureFileExists(testFilePath, "Test file");
|
|
7448
|
-
const
|
|
7449
|
-
const explicitVariant = targetVariantForSelection(
|
|
7450
|
-
const
|
|
7451
|
-
const targetMessage = options.verbose ? `Using
|
|
7980
|
+
const resolvedProviderSelection = applyVerboseOverride(selection, options.verbose);
|
|
7981
|
+
const explicitVariant = targetVariantForSelection(resolvedProviderSelection);
|
|
7982
|
+
const providerId = resolvedProviderSelection.resolvedProvider.kind;
|
|
7983
|
+
const targetMessage = options.verbose ? `Using provider (${resolvedProviderSelection.providerSource}): ${resolvedProviderSelection.providerLabel} ${buildTargetLabelSuffix(providerId, resolvedProviderSelection.resolvedProvider)} via ${resolvedProviderSelection.providersFilePath}` : `Using provider: ${inlineTargetLabel}`;
|
|
7452
7984
|
if (!progressReporter.isInteractive || options.verbose) {
|
|
7453
7985
|
console.log(`${targetMessage}`);
|
|
7454
7986
|
}
|
|
7455
|
-
const
|
|
7456
|
-
if (
|
|
7987
|
+
const providerKind = resolvedProviderSelection.resolvedProvider.kind;
|
|
7988
|
+
if (providerKind === "claude-cli" || providerKind === "copilot-cli") {
|
|
7457
7989
|
console.log("");
|
|
7458
7990
|
console.log(" TIP: For subagent-mode evals, use `agentv pipeline` instead of `eval run`.");
|
|
7459
7991
|
console.log(" The agent orchestrates executor + grader subagents directly.");
|
|
@@ -7462,12 +7994,12 @@ async function runSingleEvalFile(params) {
|
|
|
7462
7994
|
}
|
|
7463
7995
|
const agentTimeoutMs = agentTimeoutSeconds != null ? Math.max(0, agentTimeoutSeconds) * 1e3 : void 0;
|
|
7464
7996
|
const workerPreference = workersOverride ?? options.workers;
|
|
7465
|
-
let resolvedWorkers = workerPreference ??
|
|
7997
|
+
let resolvedWorkers = workerPreference ?? resolvedProviderSelection.resolvedProvider.workers ?? DEFAULT_WORKERS;
|
|
7466
7998
|
if (resolvedWorkers < 1 || resolvedWorkers > 50) {
|
|
7467
7999
|
throw new Error(`Workers must be between 1 and 50, got: ${resolvedWorkers}`);
|
|
7468
8000
|
}
|
|
7469
8001
|
const isVSCodeProvider = ["vscode", "vscode-insiders"].includes(
|
|
7470
|
-
|
|
8002
|
+
resolvedProviderSelection.resolvedProvider.kind
|
|
7471
8003
|
);
|
|
7472
8004
|
if (isVSCodeProvider && resolvedWorkers > 1) {
|
|
7473
8005
|
console.warn(
|
|
@@ -7476,9 +8008,9 @@ async function runSingleEvalFile(params) {
|
|
|
7476
8008
|
resolvedWorkers = 1;
|
|
7477
8009
|
}
|
|
7478
8010
|
if (isVSCodeProvider) {
|
|
7479
|
-
const vsConfig =
|
|
8011
|
+
const vsConfig = resolvedProviderSelection.resolvedProvider.config;
|
|
7480
8012
|
await ensureVSCodeSubagents({
|
|
7481
|
-
kind:
|
|
8013
|
+
kind: resolvedProviderSelection.resolvedProvider.kind,
|
|
7482
8014
|
count: resolvedWorkers,
|
|
7483
8015
|
verbose: options.verbose,
|
|
7484
8016
|
vscodeCmd: vsConfig.executable
|
|
@@ -7487,15 +8019,15 @@ async function runSingleEvalFile(params) {
|
|
|
7487
8019
|
const results = await evaluationRunner({
|
|
7488
8020
|
testFilePath,
|
|
7489
8021
|
repoRoot,
|
|
7490
|
-
target:
|
|
7491
|
-
targets:
|
|
8022
|
+
target: resolvedProviderSelection.resolvedProvider,
|
|
8023
|
+
targets: resolvedProviderSelection.definitions,
|
|
7492
8024
|
env: process.env,
|
|
7493
8025
|
maxRetries: Math.max(0, options.maxRetries),
|
|
7494
8026
|
agentTimeoutMs,
|
|
7495
8027
|
cache,
|
|
7496
8028
|
useCache: (() => {
|
|
7497
8029
|
if (!cache) return false;
|
|
7498
|
-
const targetConfig =
|
|
8030
|
+
const targetConfig = resolvedProviderSelection.resolvedProvider.config;
|
|
7499
8031
|
if (shouldSkipCacheForTemperature(targetConfig)) {
|
|
7500
8032
|
if (options.verbose) {
|
|
7501
8033
|
console.log("Cache skipped: target temperature > 0");
|
|
@@ -7515,9 +8047,10 @@ async function runSingleEvalFile(params) {
|
|
|
7515
8047
|
runBudgetTracker,
|
|
7516
8048
|
failOnError,
|
|
7517
8049
|
graderTarget: options.graderTarget,
|
|
8050
|
+
defaultGraderTarget: options.defaultGraderTarget,
|
|
7518
8051
|
model: options.model,
|
|
7519
8052
|
threshold: params.threshold,
|
|
7520
|
-
targetHooks:
|
|
8053
|
+
targetHooks: resolvedProviderSelection.providerHooks,
|
|
7521
8054
|
replayRecording,
|
|
7522
8055
|
providerFactory,
|
|
7523
8056
|
onResult: async (result) => {
|
|
@@ -7527,7 +8060,7 @@ async function runSingleEvalFile(params) {
|
|
|
7527
8060
|
await outputWriter.append(trimmedResult);
|
|
7528
8061
|
},
|
|
7529
8062
|
onProgress: async (event) => {
|
|
7530
|
-
const testCaseKeyId = matrixMode ? `${event.testId}@${
|
|
8063
|
+
const testCaseKeyId = matrixMode ? `${event.testId}@${providerLabel}` : event.testId;
|
|
7531
8064
|
const testCaseKey = makeTestCaseKey(testFilePath, testCaseKeyId);
|
|
7532
8065
|
if (event.status === "pending" && !seenTestCases.has(testCaseKey)) {
|
|
7533
8066
|
seenTestCases.add(testCaseKey);
|
|
@@ -7540,7 +8073,7 @@ async function runSingleEvalFile(params) {
|
|
|
7540
8073
|
else if (event.executionStatus === "execution_error") verdict = "ERROR";
|
|
7541
8074
|
progressReporter.update(displayId, {
|
|
7542
8075
|
workerId: displayId,
|
|
7543
|
-
testId: matrixMode ? `${event.testId}@${
|
|
8076
|
+
testId: matrixMode ? `${event.testId}@${providerLabel}` : event.testId,
|
|
7544
8077
|
status: event.status,
|
|
7545
8078
|
startedAt: event.startedAt,
|
|
7546
8079
|
completedAt: event.completedAt,
|
|
@@ -7574,7 +8107,7 @@ async function runEvalCommand(input) {
|
|
|
7574
8107
|
);
|
|
7575
8108
|
}
|
|
7576
8109
|
const repoRoot = await findRepoRoot(cwd);
|
|
7577
|
-
const yamlConfig = await loadConfig(
|
|
8110
|
+
const yamlConfig = await loadConfig(path13.join(cwd, "_"), repoRoot);
|
|
7578
8111
|
let requiredVersionCheck;
|
|
7579
8112
|
if (yamlConfig?.required_version) {
|
|
7580
8113
|
requiredVersionCheck = await enforceRequiredVersion(yamlConfig.required_version, {
|
|
@@ -7582,10 +8115,19 @@ async function runEvalCommand(input) {
|
|
|
7582
8115
|
});
|
|
7583
8116
|
}
|
|
7584
8117
|
let options = normalizeOptions(input.rawOptions, config, yamlConfig?.execution);
|
|
8118
|
+
if (yamlConfig?.defaults?.provider && options.cliProviderLabels.length === 0 && !options.provider) {
|
|
8119
|
+
options = { ...options, provider: yamlConfig.defaults.provider };
|
|
8120
|
+
}
|
|
8121
|
+
if (yamlConfig?.defaults?.grader) {
|
|
8122
|
+
options = { ...options, defaultGraderTarget: yamlConfig.defaults.grader };
|
|
8123
|
+
}
|
|
8124
|
+
const providerCatalogPath = yamlConfig?.providerCatalogPath;
|
|
8125
|
+
const providerDefinitions = yamlConfig?.providerDefinitions;
|
|
8126
|
+
const providerDefinitionsSource = providerDefinitions ? providerCatalogPath ?? ".agentv/config.yaml:providers" : void 0;
|
|
7585
8127
|
const resolvedExperiment = resolveExperimentForRun(options.experiment);
|
|
7586
8128
|
const evalPathInputs = input.testFiles.length > 0 ? [...input.testFiles] : [];
|
|
7587
8129
|
if (evalPathInputs.length === 0 && process.stdin.isTTY) {
|
|
7588
|
-
const { launchInteractiveWizard } = await import("./interactive-
|
|
8130
|
+
const { launchInteractiveWizard } = await import("./interactive-DL7N2C7K.js");
|
|
7589
8131
|
await launchInteractiveWizard();
|
|
7590
8132
|
return void 0;
|
|
7591
8133
|
}
|
|
@@ -7596,7 +8138,7 @@ async function runEvalCommand(input) {
|
|
|
7596
8138
|
const primarySuite = resolvedTestFiles.length > 0 ? await loadCliEvalSuite(resolvedTestFiles[0], repoRoot, {
|
|
7597
8139
|
verbose: options.verbose,
|
|
7598
8140
|
filter: options.filter,
|
|
7599
|
-
category: deriveCategory(
|
|
8141
|
+
category: deriveCategory(path13.relative(cwd, resolvedTestFiles[0]))
|
|
7600
8142
|
}) : void 0;
|
|
7601
8143
|
const resultGroupName = resolvedTestFiles.length === 1 ? primarySuite?.metadata?.name ?? fallbackResultGroupName : fallbackResultGroupName;
|
|
7602
8144
|
const resolvedTags = resolveEffectiveTags({
|
|
@@ -7625,7 +8167,7 @@ async function runEvalCommand(input) {
|
|
|
7625
8167
|
process.env.AGENTV_EXPERIMENT = normalizedExperiment;
|
|
7626
8168
|
}
|
|
7627
8169
|
if (options.graderTarget === "agentv" && !options.model) {
|
|
7628
|
-
throw new Error("--grader-
|
|
8170
|
+
throw new Error("--grader-provider agentv requires --model (e.g., --model openai:gpt-5-mini)");
|
|
7629
8171
|
}
|
|
7630
8172
|
if (options.removedOut) {
|
|
7631
8173
|
throw new Error(
|
|
@@ -7649,7 +8191,7 @@ async function runEvalCommand(input) {
|
|
|
7649
8191
|
}
|
|
7650
8192
|
let retryNonErrorResults;
|
|
7651
8193
|
if (options.retryErrors) {
|
|
7652
|
-
const retryPath =
|
|
8194
|
+
const retryPath = path13.resolve(options.retryErrors);
|
|
7653
8195
|
await ensureFileExists(retryPath, "Retry-errors JSONL file");
|
|
7654
8196
|
const completedIds = await loadFullyCompletedTestIds(retryPath);
|
|
7655
8197
|
const errorIds = await loadErrorTestIds(retryPath);
|
|
@@ -7666,7 +8208,7 @@ async function runEvalCommand(input) {
|
|
|
7666
8208
|
const cachedDir = await resolveCachedRunDir(cwd);
|
|
7667
8209
|
if (cachedDir) {
|
|
7668
8210
|
options = { ...options, outputDir: cachedDir };
|
|
7669
|
-
const displayDir =
|
|
8211
|
+
const displayDir = path13.relative(cwd, cachedDir) || cachedDir;
|
|
7670
8212
|
console.log(`Auto-detected last run dir for --resume: ${displayDir}`);
|
|
7671
8213
|
}
|
|
7672
8214
|
}
|
|
@@ -7674,7 +8216,7 @@ async function runEvalCommand(input) {
|
|
|
7674
8216
|
let rerunIncludeKeys;
|
|
7675
8217
|
let isResumeAppend = false;
|
|
7676
8218
|
if (options.resume && !options.retryErrors) {
|
|
7677
|
-
const sourceRunDir = options.rerunFailedSource ? await resolveRerunFailedRunDir(cwd, options.rerunFailedSource) : options.outputDir ?
|
|
8219
|
+
const sourceRunDir = options.rerunFailedSource ? await resolveRerunFailedRunDir(cwd, options.rerunFailedSource) : options.outputDir ? path13.resolve(options.outputDir) : void 0;
|
|
7678
8220
|
if (sourceRunDir) {
|
|
7679
8221
|
if (options.rerunFailedSource && !options.outputDir) {
|
|
7680
8222
|
options = { ...options, outputDir: sourceRunDir };
|
|
@@ -7693,7 +8235,7 @@ async function runEvalCommand(input) {
|
|
|
7693
8235
|
addResumeIdentityEntry(rerunIncludeKeys, entry);
|
|
7694
8236
|
}
|
|
7695
8237
|
}
|
|
7696
|
-
isResumeAppend = options.outputDir !== void 0 &&
|
|
8238
|
+
isResumeAppend = options.outputDir !== void 0 && path13.resolve(options.outputDir) === path13.resolve(sourceRunDir);
|
|
7697
8239
|
const modeLabel = options.rerunFailed ? "Rerun-failed" : "Resume";
|
|
7698
8240
|
console.log(
|
|
7699
8241
|
`${modeLabel}: found ${existingResults.length} existing result(s), skipping ${completedResultCount} completed.`
|
|
@@ -7711,10 +8253,10 @@ async function runEvalCommand(input) {
|
|
|
7711
8253
|
}
|
|
7712
8254
|
}
|
|
7713
8255
|
if (options.workspacePath) {
|
|
7714
|
-
const resolvedWorkspace =
|
|
8256
|
+
const resolvedWorkspace = path13.resolve(options.workspacePath);
|
|
7715
8257
|
try {
|
|
7716
|
-
const { stat:
|
|
7717
|
-
const stats = await
|
|
8258
|
+
const { stat: stat4 } = await import("node:fs/promises");
|
|
8259
|
+
const stats = await stat4(resolvedWorkspace);
|
|
7718
8260
|
if (!stats.isDirectory()) {
|
|
7719
8261
|
throw new Error(`--workspace-path is not a directory: ${resolvedWorkspace}`);
|
|
7720
8262
|
}
|
|
@@ -7734,7 +8276,7 @@ async function runEvalCommand(input) {
|
|
|
7734
8276
|
let outputPath;
|
|
7735
8277
|
let runDirName = process.env.AGENTV_RUN_TIMESTAMP?.trim() || createRunDirName();
|
|
7736
8278
|
if (explicitDir) {
|
|
7737
|
-
runDir =
|
|
8279
|
+
runDir = path13.resolve(explicitDir);
|
|
7738
8280
|
mkdirSync(runDir, { recursive: true });
|
|
7739
8281
|
outputPath = runDir;
|
|
7740
8282
|
} else {
|
|
@@ -7749,7 +8291,7 @@ async function runEvalCommand(input) {
|
|
|
7749
8291
|
outputPath = runDir;
|
|
7750
8292
|
}
|
|
7751
8293
|
if (!process.env.AGENTV_RUN_TIMESTAMP) {
|
|
7752
|
-
process.env.AGENTV_RUN_TIMESTAMP =
|
|
8294
|
+
process.env.AGENTV_RUN_TIMESTAMP = path13.basename(runDir);
|
|
7753
8295
|
}
|
|
7754
8296
|
process.env.AGENTV_RUN_DIR = runDir;
|
|
7755
8297
|
console.log(`Artifact directory: ${runDir}`);
|
|
@@ -7764,11 +8306,15 @@ async function runEvalCommand(input) {
|
|
|
7764
8306
|
}
|
|
7765
8307
|
const fileMetadata = /* @__PURE__ */ new Map();
|
|
7766
8308
|
for (const testFilePath of resolvedTestFiles) {
|
|
8309
|
+
const fileProviderCatalogPath = options.providerCatalogPathByEvalFile?.get(path13.resolve(testFilePath)) ?? providerCatalogPath;
|
|
7767
8310
|
const meta = await prepareFileMetadata({
|
|
7768
8311
|
testFilePath,
|
|
7769
8312
|
repoRoot,
|
|
7770
8313
|
cwd,
|
|
7771
8314
|
options,
|
|
8315
|
+
providerCatalogPath: fileProviderCatalogPath,
|
|
8316
|
+
providerDefinitions,
|
|
8317
|
+
providerDefinitionsSource: fileProviderCatalogPath ? fileProviderCatalogPath === providerCatalogPath ? providerDefinitionsSource : void 0 : providerDefinitionsSource,
|
|
7772
8318
|
suiteFilter: void 0
|
|
7773
8319
|
});
|
|
7774
8320
|
fileMetadata.set(testFilePath, meta);
|
|
@@ -7779,7 +8325,7 @@ async function runEvalCommand(input) {
|
|
|
7779
8325
|
for (const [testFilePath, meta] of fileMetadata.entries()) {
|
|
7780
8326
|
if (!matchesTagFilters(meta.tags, options.tags, options.excludeTags)) {
|
|
7781
8327
|
fileMetadata.delete(testFilePath);
|
|
7782
|
-
skippedFiles.push(
|
|
8328
|
+
skippedFiles.push(path13.relative(cwd, testFilePath));
|
|
7783
8329
|
}
|
|
7784
8330
|
}
|
|
7785
8331
|
if (skippedFiles.length > 0 && options.verbose) {
|
|
@@ -7802,12 +8348,12 @@ async function runEvalCommand(input) {
|
|
|
7802
8348
|
tsConfigCache: options.tsConfigCache
|
|
7803
8349
|
});
|
|
7804
8350
|
const activeCachePath = options.cachePath ?? yamlCachePath ?? options.tsConfigCachePath;
|
|
7805
|
-
const cache = cacheEnabled ? new ResponseCache(activeCachePath ?
|
|
8351
|
+
const cache = cacheEnabled ? new ResponseCache(activeCachePath ? path13.resolve(activeCachePath) : void 0) : void 0;
|
|
7806
8352
|
if (cache) {
|
|
7807
8353
|
console.log(`Response cache: enabled (${cache.cachePath})`);
|
|
7808
8354
|
}
|
|
7809
8355
|
if (options.recordReplay) {
|
|
7810
|
-
console.log(`Replay recording: ${
|
|
8356
|
+
console.log(`Replay recording: ${path13.resolve(options.recordReplay)}`);
|
|
7811
8357
|
}
|
|
7812
8358
|
const yamlThreshold = firstMeta?.threshold;
|
|
7813
8359
|
const resolvedThreshold = options.threshold ?? yamlThreshold;
|
|
@@ -7821,7 +8367,7 @@ async function runEvalCommand(input) {
|
|
|
7821
8367
|
for (const meta of fileMetadata.values()) {
|
|
7822
8368
|
for (const test of meta.testCases) {
|
|
7823
8369
|
for (const { selection } of meta.selections) {
|
|
7824
|
-
const target = selection.
|
|
8370
|
+
const target = selection.providerLabel;
|
|
7825
8371
|
const variant = targetVariantForSelection(selection);
|
|
7826
8372
|
if (rerunIncludeKeys) {
|
|
7827
8373
|
if (resumeIdentityMatches(rerunIncludeKeys, test, target, variant)) {
|
|
@@ -7893,13 +8439,13 @@ async function runEvalCommand(input) {
|
|
|
7893
8439
|
for (const testId of meta.testIds) {
|
|
7894
8440
|
const testCaseKey = makeTestCaseKey(
|
|
7895
8441
|
testFilePath,
|
|
7896
|
-
meta.selections.length > 1 ? `${testId}@${selection.
|
|
8442
|
+
meta.selections.length > 1 ? `${testId}@${selection.providerLabel}` : testId
|
|
7897
8443
|
);
|
|
7898
8444
|
seenTestCases.add(testCaseKey);
|
|
7899
8445
|
const displayId = displayIdTracker.getOrAssign(testCaseKey);
|
|
7900
8446
|
progressReporter.update(displayId, {
|
|
7901
8447
|
workerId: displayId,
|
|
7902
|
-
testId: meta.selections.length > 1 ? `${testId}@${selection.
|
|
8448
|
+
testId: meta.selections.length > 1 ? `${testId}@${selection.providerLabel}` : testId,
|
|
7903
8449
|
status: "pending",
|
|
7904
8450
|
targetLabel: inlineTargetLabel
|
|
7905
8451
|
});
|
|
@@ -7925,7 +8471,7 @@ async function runEvalCommand(input) {
|
|
|
7925
8471
|
});
|
|
7926
8472
|
let transcriptProviderFactory;
|
|
7927
8473
|
if (options.transcript) {
|
|
7928
|
-
const { TranscriptProvider } = await import("./dist-
|
|
8474
|
+
const { TranscriptProvider } = await import("./dist-A3SGR7TW.js");
|
|
7929
8475
|
const transcriptProvider = await TranscriptProvider.fromFile(options.transcript);
|
|
7930
8476
|
const totalTests = [...fileMetadata.values()].reduce(
|
|
7931
8477
|
(sum, meta) => sum + meta.testCases.length,
|
|
@@ -7958,12 +8504,12 @@ async function runEvalCommand(input) {
|
|
|
7958
8504
|
);
|
|
7959
8505
|
}
|
|
7960
8506
|
if (!isResumeAppend && totalEvalCount > 0) {
|
|
7961
|
-
const evalFile = activeTestFiles.length === 1 ? activeTestFiles[0] : "";
|
|
8507
|
+
const evalFile = activeTestFiles.length === 1 ? path13.relative(cwd, activeTestFiles[0]) : "";
|
|
7962
8508
|
await writeInitialRunSummaryArtifact(runDir, {
|
|
7963
8509
|
evalFile,
|
|
7964
8510
|
plannedTestCount: totalEvalCount,
|
|
7965
8511
|
experiment: normalizeExperimentName(options.experiment),
|
|
7966
|
-
runId:
|
|
8512
|
+
runId: path13.basename(runDir),
|
|
7967
8513
|
experimentMetadata: runExperimentMetadata,
|
|
7968
8514
|
runtimeSource: runtimeSourceMetadata,
|
|
7969
8515
|
tags: emittedTags
|
|
@@ -7999,7 +8545,7 @@ async function runEvalCommand(input) {
|
|
|
7999
8545
|
if (fileBudgetTracker?.isExceeded()) {
|
|
8000
8546
|
const budgetMsg = `Run budget exceeded ($${fileBudgetTracker.currentCostUsd.toFixed(4)} / $${fileBudgetTracker.budgetCapUsd.toFixed(4)})`;
|
|
8001
8547
|
console.log(`
|
|
8002
|
-
\u26A0 ${budgetMsg} \u2014 skipping ${
|
|
8548
|
+
\u26A0 ${budgetMsg} \u2014 skipping ${path13.basename(testFilePath)}`);
|
|
8003
8549
|
for (const { selection } of targetPrep.selections) {
|
|
8004
8550
|
const explicitVariant = targetVariantForSelection(selection);
|
|
8005
8551
|
const skippedResults = targetPrep.testCases.map((testCase) => ({
|
|
@@ -8013,7 +8559,7 @@ async function runEvalCommand(input) {
|
|
|
8013
8559
|
input: testCase.input,
|
|
8014
8560
|
output: [{ role: "assistant", content: budgetMsg }],
|
|
8015
8561
|
finalOutput: budgetMsg,
|
|
8016
|
-
target: selection.
|
|
8562
|
+
target: selection.providerLabel,
|
|
8017
8563
|
testId: testCase.testId ?? testCase.id,
|
|
8018
8564
|
conversationId: testCase.conversation_id,
|
|
8019
8565
|
error: budgetMsg
|
|
@@ -8024,7 +8570,7 @@ async function runEvalCommand(input) {
|
|
|
8024
8570
|
failureStage: "setup",
|
|
8025
8571
|
failureReasonCode: "budget_exceeded",
|
|
8026
8572
|
executionError: { message: budgetMsg, stage: "setup" },
|
|
8027
|
-
target: selection.
|
|
8573
|
+
target: selection.providerLabel,
|
|
8028
8574
|
variant: explicitVariant
|
|
8029
8575
|
}));
|
|
8030
8576
|
for (const r of skippedResults) {
|
|
@@ -8043,18 +8589,18 @@ async function runEvalCommand(input) {
|
|
|
8043
8589
|
const targetResults = await Promise.all(
|
|
8044
8590
|
targetPrep.selections.map(
|
|
8045
8591
|
({ selection, inlineTargetLabel }) => limitTarget(async () => {
|
|
8046
|
-
const
|
|
8592
|
+
const providerLabel = selection.providerLabel;
|
|
8047
8593
|
const applicableTestCases = targetPrep.testCases;
|
|
8048
8594
|
const filteredTestCases = rerunIncludeKeys ? applicableTestCases.filter(
|
|
8049
8595
|
(test) => resumeIdentityMatches(
|
|
8050
8596
|
rerunIncludeKeys,
|
|
8051
8597
|
test,
|
|
8052
|
-
|
|
8598
|
+
providerLabel,
|
|
8053
8599
|
targetVariantForSelection(selection)
|
|
8054
8600
|
)
|
|
8055
8601
|
) : resumeSkipKeys ? applicableTestCases.filter((test) => {
|
|
8056
8602
|
const variant = targetVariantForSelection(selection);
|
|
8057
|
-
return !resumeIdentityMatches(resumeSkipKeys, test,
|
|
8603
|
+
return !resumeIdentityMatches(resumeSkipKeys, test, providerLabel, variant);
|
|
8058
8604
|
}) : applicableTestCases;
|
|
8059
8605
|
if (filteredTestCases.length === 0) {
|
|
8060
8606
|
return [];
|
|
@@ -8097,7 +8643,7 @@ async function runEvalCommand(input) {
|
|
|
8097
8643
|
});
|
|
8098
8644
|
groupResults.push(...result.results);
|
|
8099
8645
|
}
|
|
8100
|
-
const evalFile =
|
|
8646
|
+
const evalFile = path13.relative(cwd, testFilePath);
|
|
8101
8647
|
const existingSummary = remoteEvalSummaries.find(
|
|
8102
8648
|
(summary2) => summary2.evalFile === evalFile
|
|
8103
8649
|
);
|
|
@@ -8114,7 +8660,7 @@ async function runEvalCommand(input) {
|
|
|
8114
8660
|
const message = fileError instanceof Error ? fileError.message : String(fileError);
|
|
8115
8661
|
console.error(
|
|
8116
8662
|
`
|
|
8117
|
-
[ERROR] \u26A0 Eval file failed: ${
|
|
8663
|
+
[ERROR] \u26A0 Eval file failed: ${path13.basename(testFilePath)} \u2014 ${message}
|
|
8118
8664
|
`
|
|
8119
8665
|
);
|
|
8120
8666
|
const explicitVariant = targetVariantForSelection(selection);
|
|
@@ -8131,7 +8677,7 @@ async function runEvalCommand(input) {
|
|
|
8131
8677
|
input: testCase.input,
|
|
8132
8678
|
output: [{ role: "assistant", content: message }],
|
|
8133
8679
|
finalOutput: message,
|
|
8134
|
-
target: selection.
|
|
8680
|
+
target: selection.providerLabel,
|
|
8135
8681
|
testId: testCase.testId ?? testCase.id,
|
|
8136
8682
|
conversationId: testCase.conversation_id,
|
|
8137
8683
|
error: message
|
|
@@ -8143,7 +8689,7 @@ async function runEvalCommand(input) {
|
|
|
8143
8689
|
failureReasonCode: "setup_error",
|
|
8144
8690
|
durationMs: 0,
|
|
8145
8691
|
tokenUsage: { input: 0, output: 0 },
|
|
8146
|
-
target: selection.
|
|
8692
|
+
target: selection.providerLabel,
|
|
8147
8693
|
variant: explicitVariant
|
|
8148
8694
|
},
|
|
8149
8695
|
testFilePath,
|
|
@@ -8173,7 +8719,11 @@ async function runEvalCommand(input) {
|
|
|
8173
8719
|
);
|
|
8174
8720
|
}
|
|
8175
8721
|
await outputWriter.close().catch(() => void 0);
|
|
8176
|
-
const summaryResults =
|
|
8722
|
+
const summaryResults = await collectTerminalSummaryResults({
|
|
8723
|
+
allResults,
|
|
8724
|
+
isResumeAppend,
|
|
8725
|
+
runDir
|
|
8726
|
+
});
|
|
8177
8727
|
const thresholdOpts = hasScopedRunPolicies || hasPerFileRuntimeThresholds ? { thresholdLabel: "configured threshold(s)", useExecutionStatus: true } : resolvedThreshold !== void 0 ? { threshold: resolvedThreshold } : void 0;
|
|
8178
8728
|
const summary = calculateEvaluationSummary(summaryResults, thresholdOpts);
|
|
8179
8729
|
console.log(formatEvaluationSummary(summary, thresholdOpts));
|
|
@@ -8187,14 +8737,14 @@ ${formatRequiredVersionFailureNote(requiredVersionCheck)}`);
|
|
|
8187
8737
|
console.log(formatMatrixSummary(summaryResults));
|
|
8188
8738
|
}
|
|
8189
8739
|
if (allResults.length > 0) {
|
|
8190
|
-
const evalFile = activeTestFiles.length === 1 ? activeTestFiles[0] : "";
|
|
8740
|
+
const evalFile = activeTestFiles.length === 1 ? path13.relative(cwd, activeTestFiles[0]) : "";
|
|
8191
8741
|
const sourceTests = activeSourceTests;
|
|
8192
|
-
const taskBundleTargets =
|
|
8742
|
+
const taskBundleTargets = buildTaskBundleProviderSelections(activeTestFiles, fileMetadata);
|
|
8193
8743
|
if (isResumeAppend) {
|
|
8194
|
-
const { writePerTestArtifacts } = await import("./artifact-writer-
|
|
8744
|
+
const { writePerTestArtifacts } = await import("./artifact-writer-KJEOROKQ.js");
|
|
8195
8745
|
await writePerTestArtifacts(allResults, runDir, {
|
|
8196
8746
|
experiment: normalizeExperimentName(options.experiment),
|
|
8197
|
-
runId:
|
|
8747
|
+
runId: path13.basename(runDir),
|
|
8198
8748
|
resultGroup: resultGroupName,
|
|
8199
8749
|
cwd,
|
|
8200
8750
|
repoRoot,
|
|
@@ -8206,7 +8756,7 @@ ${formatRequiredVersionFailureNote(requiredVersionCheck)}`);
|
|
|
8206
8756
|
const { summaryPath } = await aggregateRunDir(runDir, {
|
|
8207
8757
|
evalFile,
|
|
8208
8758
|
experiment: normalizeExperimentName(options.experiment),
|
|
8209
|
-
runId:
|
|
8759
|
+
runId: path13.basename(runDir),
|
|
8210
8760
|
experimentMetadata: runExperimentMetadata,
|
|
8211
8761
|
runtimeSource: runtimeSourceMetadata,
|
|
8212
8762
|
tags: emittedTags
|
|
@@ -8223,7 +8773,7 @@ ${formatRequiredVersionFailureNote(requiredVersionCheck)}`);
|
|
|
8223
8773
|
{
|
|
8224
8774
|
evalFile,
|
|
8225
8775
|
experiment: normalizeExperimentName(options.experiment),
|
|
8226
|
-
runId:
|
|
8776
|
+
runId: path13.basename(runDir),
|
|
8227
8777
|
experimentMetadata: runExperimentMetadata,
|
|
8228
8778
|
resultGroup: resultGroupName,
|
|
8229
8779
|
cwd,
|
|
@@ -8286,9 +8836,9 @@ Results written under: ${runDir}`);
|
|
|
8286
8836
|
});
|
|
8287
8837
|
}
|
|
8288
8838
|
if (summary.executionErrorCount > 0 && !options.retryErrors && !options.resume) {
|
|
8289
|
-
const evalFileArgs = activeTestFiles.map((f) =>
|
|
8290
|
-
const targetFlag = options.
|
|
8291
|
-
const relativeRunDir =
|
|
8839
|
+
const evalFileArgs = activeTestFiles.map((f) => path13.relative(cwd, f)).join(" ");
|
|
8840
|
+
const targetFlag = options.provider ? ` --provider ${options.provider}` : "";
|
|
8841
|
+
const relativeRunDir = path13.relative(cwd, runDir);
|
|
8292
8842
|
console.log(
|
|
8293
8843
|
`
|
|
8294
8844
|
Tip: ${summary.executionErrorCount} execution error(s) detected. Re-run failed tests with:
|
|
@@ -8310,7 +8860,7 @@ Tip: ${summary.executionErrorCount} execution error(s) detected. Re-run failed t
|
|
|
8310
8860
|
executionErrorCount: summary.executionErrorCount,
|
|
8311
8861
|
outputPath,
|
|
8312
8862
|
testFiles: activeTestFiles,
|
|
8313
|
-
|
|
8863
|
+
provider: options.provider,
|
|
8314
8864
|
thresholdFailed,
|
|
8315
8865
|
allExecutionErrors,
|
|
8316
8866
|
budgetExceeded: runBudgetExceeded || void 0
|
|
@@ -8331,7 +8881,7 @@ async function resolveEvaluationRunner() {
|
|
|
8331
8881
|
if (!overridePath) {
|
|
8332
8882
|
return runEvaluation;
|
|
8333
8883
|
}
|
|
8334
|
-
const resolved =
|
|
8884
|
+
const resolved = path13.isAbsolute(overridePath) ? overridePath : path13.resolve(process.cwd(), overridePath);
|
|
8335
8885
|
const moduleUrl = pathToFileURL(resolved).href;
|
|
8336
8886
|
const mod = await import(moduleUrl);
|
|
8337
8887
|
const candidate = mod.runEvaluation;
|
|
@@ -8365,20 +8915,21 @@ export {
|
|
|
8365
8915
|
normalizeTagMap,
|
|
8366
8916
|
loadLightweightResults,
|
|
8367
8917
|
Mutex,
|
|
8368
|
-
|
|
8918
|
+
PROVIDER_FILE_CANDIDATES,
|
|
8369
8919
|
fileExists,
|
|
8370
|
-
|
|
8920
|
+
discoverProvidersFile,
|
|
8371
8921
|
loadEnvFromHierarchy,
|
|
8372
8922
|
detectFileType,
|
|
8373
8923
|
validateEvalFile,
|
|
8924
|
+
validateTypeScriptEvalConfigFile,
|
|
8374
8925
|
validateCasesFile,
|
|
8375
8926
|
validateTargetsFile,
|
|
8376
8927
|
validateConfigFile,
|
|
8377
8928
|
validateFileReferences,
|
|
8378
8929
|
validateWorkspacePaths,
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
|
|
8930
|
+
readTestSuiteProvider,
|
|
8931
|
+
selectProvider,
|
|
8932
|
+
selectMultipleProviders,
|
|
8382
8933
|
enforceRequiredVersion,
|
|
8383
8934
|
c,
|
|
8384
8935
|
padRight,
|
|
@@ -8409,4 +8960,4 @@ export {
|
|
|
8409
8960
|
filterByCategory,
|
|
8410
8961
|
runEvalCommand
|
|
8411
8962
|
};
|
|
8412
|
-
//# sourceMappingURL=chunk-
|
|
8963
|
+
//# sourceMappingURL=chunk-QSK3PC44.js.map
|