agentv 5.1.0-next.1 → 5.2.0-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 +16 -12
- package/dist/{artifact-writer-IORG7CW5.js → artifact-writer-SN6UNL5G.js} +5 -5
- package/dist/{chunk-ZGPCX334.js → chunk-3S6A2RKR.js} +2803 -959
- package/dist/chunk-3S6A2RKR.js.map +1 -0
- package/dist/{chunk-GIRUNQGP.js → chunk-3X357HS4.js} +205 -153
- package/dist/chunk-3X357HS4.js.map +1 -0
- package/dist/{chunk-CBBBRTQ3.js → chunk-46K2OET3.js} +64 -3
- package/dist/chunk-46K2OET3.js.map +1 -0
- package/dist/{chunk-GJWPQXHN.js → chunk-ALVZQUZP.js} +104 -188
- package/dist/chunk-ALVZQUZP.js.map +1 -0
- package/dist/{chunk-AM2IPHKS.js → chunk-T4AD3H3Y.js} +236 -154
- package/dist/chunk-T4AD3H3Y.js.map +1 -0
- package/dist/cli.js +6 -6
- package/dist/dashboard/assets/{index-BSHoWrdr.js → index-DNgf3qJ2.js} +1 -1
- package/dist/dashboard/assets/{index-zvUKAkKn.css → index-D_bokML8.css} +1 -1
- package/dist/dashboard/assets/index-r_jSJmlw.js +121 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/{dist-2D2GBHZV.js → dist-DEPJOMCA.js} +6 -8
- package/dist/index.js +6 -6
- package/dist/{interactive-V4SEHLNY.js → interactive-36ZNMQB2.js} +6 -6
- package/dist/skills/agentv-bench/SKILL.md +16 -12
- package/dist/skills/agentv-bench/references/eval-yaml-spec.md +15 -10
- package/dist/skills/agentv-bench/references/migrating-from-skill-creator.md +1 -1
- package/dist/skills/agentv-eval-migrations/references/breaking-changes.md +26 -27
- package/dist/skills/agentv-eval-writer/SKILL.md +86 -71
- package/dist/skills/agentv-eval-writer/references/eval.schema.json +772 -1367
- package/dist/{ts-eval-loader-SSPJVEHD-AL2A3V5Z.js → ts-eval-loader-OMG2JBHP-OP5RR7A3.js} +3 -2
- package/package.json +8 -2
- package/dist/chunk-AM2IPHKS.js.map +0 -1
- package/dist/chunk-CBBBRTQ3.js.map +0 -1
- package/dist/chunk-GIRUNQGP.js.map +0 -1
- package/dist/chunk-GJWPQXHN.js.map +0 -1
- package/dist/chunk-ZGPCX334.js.map +0 -1
- package/dist/dashboard/assets/index-BaLLxmVO.js +0 -121
- /package/dist/{artifact-writer-IORG7CW5.js.map → artifact-writer-SN6UNL5G.js.map} +0 -0
- /package/dist/{dist-2D2GBHZV.js.map → dist-DEPJOMCA.js.map} +0 -0
- /package/dist/{interactive-V4SEHLNY.js.map → interactive-36ZNMQB2.js.map} +0 -0
- /package/dist/{ts-eval-loader-SSPJVEHD-AL2A3V5Z.js.map → ts-eval-loader-OMG2JBHP-OP5RR7A3.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-46K2OET3.js";
|
|
5
5
|
import {
|
|
6
6
|
RunBudgetTracker,
|
|
7
7
|
buildWipBranchName,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
resolveResultsRepoRunsDir,
|
|
19
19
|
setupWipWorktree,
|
|
20
20
|
syncResultsRepoForProject
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-ALVZQUZP.js";
|
|
22
22
|
import {
|
|
23
23
|
AGENTV_LOCAL_CONFIG_FILE_NAME,
|
|
24
24
|
AGENTV_LOCAL_CONFIG_YML_FILE_NAME,
|
|
@@ -66,6 +66,7 @@ import {
|
|
|
66
66
|
readTargetDefinitions,
|
|
67
67
|
readTestSuiteMetadata,
|
|
68
68
|
resolveConfigFieldReferences,
|
|
69
|
+
resolveEnvironmentRecipe,
|
|
69
70
|
resolveFileReference,
|
|
70
71
|
resolveResultsConfigForProject,
|
|
71
72
|
resolveTargetDefinition,
|
|
@@ -82,7 +83,7 @@ import {
|
|
|
82
83
|
traceEnvelopeToTraceSummary,
|
|
83
84
|
traceEnvelopeToTranscriptMessages,
|
|
84
85
|
writeInitialRunSummaryArtifact
|
|
85
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-3S6A2RKR.js";
|
|
86
87
|
|
|
87
88
|
// src/commands/eval/shared.ts
|
|
88
89
|
import { constants } from "node:fs";
|
|
@@ -345,7 +346,7 @@ async function findRepoRoot(start) {
|
|
|
345
346
|
// package.json
|
|
346
347
|
var package_default = {
|
|
347
348
|
name: "agentv",
|
|
348
|
-
version: "5.
|
|
349
|
+
version: "5.2.0-next.1",
|
|
349
350
|
description: "CLI entry point for AgentV",
|
|
350
351
|
type: "module",
|
|
351
352
|
repository: {
|
|
@@ -386,7 +387,7 @@ var package_default = {
|
|
|
386
387
|
yaml: "^2.8.3"
|
|
387
388
|
},
|
|
388
389
|
peerDependencies: {
|
|
389
|
-
"@anthropic-ai/claude-agent-sdk": "^0.2.
|
|
390
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.89",
|
|
390
391
|
"@github/copilot-sdk": "^1.0.3",
|
|
391
392
|
"@openai/codex-sdk": "^0.136.0",
|
|
392
393
|
"@earendil-works/pi-coding-agent": "^0.74.0"
|
|
@@ -405,6 +406,12 @@ var package_default = {
|
|
|
405
406
|
optional: true
|
|
406
407
|
}
|
|
407
408
|
},
|
|
409
|
+
optionalDependencies: {
|
|
410
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.89",
|
|
411
|
+
"@github/copilot-sdk": "^1.0.3",
|
|
412
|
+
"@openai/codex-sdk": "^0.136.0",
|
|
413
|
+
"@earendil-works/pi-coding-agent": "^0.74.0"
|
|
414
|
+
},
|
|
408
415
|
devDependencies: {
|
|
409
416
|
"@agentv/core": "workspace:*",
|
|
410
417
|
"@agentv/sdk": "workspace:*",
|
|
@@ -867,6 +874,9 @@ function readGradingAssertionResults(record) {
|
|
|
867
874
|
);
|
|
868
875
|
}
|
|
869
876
|
function readNestedGradingScores(record) {
|
|
877
|
+
if (Array.isArray(record.component_results)) {
|
|
878
|
+
return record.component_results;
|
|
879
|
+
}
|
|
870
880
|
if (Array.isArray(record.scores)) {
|
|
871
881
|
return record.scores;
|
|
872
882
|
}
|
|
@@ -878,14 +888,56 @@ function readNestedGradingScores(record) {
|
|
|
878
888
|
}
|
|
879
889
|
return void 0;
|
|
880
890
|
}
|
|
891
|
+
function componentLabel(component) {
|
|
892
|
+
const assertion = component.assertion;
|
|
893
|
+
if (assertion && typeof assertion === "object" && !Array.isArray(assertion)) {
|
|
894
|
+
const record = assertion;
|
|
895
|
+
for (const key of ["value", "name", "id", "type"]) {
|
|
896
|
+
const value = record[key];
|
|
897
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
898
|
+
return value;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
return typeof component.reason === "string" ? component.reason : "grading component";
|
|
903
|
+
}
|
|
904
|
+
function mapComponentAssertion(component) {
|
|
905
|
+
return {
|
|
906
|
+
text: componentLabel(component),
|
|
907
|
+
passed: component.pass === true,
|
|
908
|
+
evidence: typeof component.reason === "string" ? component.reason : void 0
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
function collectComponentAssertions(value) {
|
|
912
|
+
if (!Array.isArray(value)) {
|
|
913
|
+
return [];
|
|
914
|
+
}
|
|
915
|
+
return value.flatMap((component) => {
|
|
916
|
+
if (!component || typeof component !== "object" || Array.isArray(component)) {
|
|
917
|
+
return [];
|
|
918
|
+
}
|
|
919
|
+
const record = component;
|
|
920
|
+
const nested = collectComponentAssertions(record.component_results);
|
|
921
|
+
return nested.length > 0 ? nested : [mapComponentAssertion(record)];
|
|
922
|
+
});
|
|
923
|
+
}
|
|
881
924
|
function mapGradingEvaluator(evaluator) {
|
|
882
|
-
const
|
|
925
|
+
const pass = typeof evaluator.pass === "boolean" ? evaluator.pass : evaluator.verdict === "pass" || typeof evaluator.score === "number" && evaluator.score >= 0.8;
|
|
926
|
+
const verdict = pass ? "pass" : "fail";
|
|
883
927
|
const details = evaluator.details && typeof evaluator.details === "object" && !Array.isArray(evaluator.details) ? evaluator.details : void 0;
|
|
928
|
+
const assertion = evaluator.assertion && typeof evaluator.assertion === "object" && !Array.isArray(evaluator.assertion) ? evaluator.assertion : void 0;
|
|
884
929
|
return {
|
|
885
|
-
name: String(evaluator.name ??
|
|
886
|
-
type: String(evaluator.type ?? ""),
|
|
930
|
+
name: String(assertion?.name ?? assertion?.id ?? evaluator.name ?? componentLabel(evaluator)),
|
|
931
|
+
type: String(assertion?.type ?? evaluator.type ?? "llm-grader"),
|
|
887
932
|
score: typeof evaluator.score === "number" ? evaluator.score : 0,
|
|
888
|
-
|
|
933
|
+
reason: typeof evaluator.reason === "string" ? evaluator.reason : void 0,
|
|
934
|
+
assertions: (() => {
|
|
935
|
+
const nestedAssertions = collectComponentAssertions(evaluator.component_results);
|
|
936
|
+
if (nestedAssertions.length > 0) {
|
|
937
|
+
return nestedAssertions;
|
|
938
|
+
}
|
|
939
|
+
return readGradingAssertionResults(evaluator) ?? [mapComponentAssertion(evaluator)];
|
|
940
|
+
})(),
|
|
889
941
|
scores: mapGradingEvaluators(readNestedGradingScores(evaluator)),
|
|
890
942
|
weight: typeof evaluator.weight === "number" ? evaluator.weight : void 0,
|
|
891
943
|
verdict,
|
|
@@ -1004,9 +1056,10 @@ function hydrateManifestRecord(baseDir, record, options) {
|
|
|
1004
1056
|
const metrics = readOptionalJson(baseDir, record.metrics_path);
|
|
1005
1057
|
const timing = metrics ?? readOptionalJson(baseDir, record.timing_path);
|
|
1006
1058
|
const testId = record.test_id ?? "unknown";
|
|
1007
|
-
const gradingAssertions = grading ?
|
|
1059
|
+
const gradingAssertions = grading ? collectComponentAssertions(grading.component_results) : void 0;
|
|
1060
|
+
const gradingRecord = grading;
|
|
1008
1061
|
const gradingScores = mapGradingEvaluators(
|
|
1009
|
-
|
|
1062
|
+
gradingRecord?.component_results ?? gradingRecord?.graders ?? gradingRecord?.evaluators
|
|
1010
1063
|
);
|
|
1011
1064
|
return {
|
|
1012
1065
|
timestamp: record.timestamp,
|
|
@@ -2837,10 +2890,10 @@ var KNOWN_TOP_LEVEL_FIELDS = /* @__PURE__ */ new Set([
|
|
|
2837
2890
|
"input",
|
|
2838
2891
|
"input_files",
|
|
2839
2892
|
"prompts",
|
|
2840
|
-
"imports",
|
|
2841
2893
|
"tests",
|
|
2842
2894
|
"graders",
|
|
2843
2895
|
"defaults",
|
|
2896
|
+
"environment",
|
|
2844
2897
|
"target",
|
|
2845
2898
|
"targets",
|
|
2846
2899
|
"model",
|
|
@@ -2867,7 +2920,6 @@ var KNOWN_TOP_LEVEL_FIELDS = /* @__PURE__ */ new Set([
|
|
|
2867
2920
|
"governance"
|
|
2868
2921
|
]);
|
|
2869
2922
|
var KNOWN_INCLUDE_FIELDS = /* @__PURE__ */ new Set(["include", "type", "select", "run"]);
|
|
2870
|
-
var KNOWN_IMPORT_FIELDS = /* @__PURE__ */ new Set(["path", "select", "run"]);
|
|
2871
2923
|
var KNOWN_RUN_OVERRIDE_FIELDS = /* @__PURE__ */ new Set(["threshold", "repeat", "timeout_seconds", "budget_usd"]);
|
|
2872
2924
|
var KNOWN_DEFAULT_TEST_FIELDS = /* @__PURE__ */ new Set([
|
|
2873
2925
|
"vars",
|
|
@@ -2907,6 +2959,10 @@ var KNOWN_TEST_EXECUTION_FIELDS = /* @__PURE__ */ new Set([
|
|
|
2907
2959
|
"workspace"
|
|
2908
2960
|
]);
|
|
2909
2961
|
var REMOVED_TOP_LEVEL_FIELDS = /* @__PURE__ */ new Map([
|
|
2962
|
+
[
|
|
2963
|
+
"imports",
|
|
2964
|
+
"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."
|
|
2965
|
+
],
|
|
2910
2966
|
[
|
|
2911
2967
|
"expected_output",
|
|
2912
2968
|
"Top-level 'expected_output' has been removed from authored eval YAML. Put reference answers in default_test.vars.expected_output or tests[].vars.expected_output and consume them with an explicit assertion such as { type: 'llm-rubric', value: 'Matches the reference answer: {{ expected_output }}' }."
|
|
@@ -2966,6 +3022,7 @@ var KNOWN_TEST_FIELDS = /* @__PURE__ */ new Set([
|
|
|
2966
3022
|
"threshold",
|
|
2967
3023
|
"execution",
|
|
2968
3024
|
"run",
|
|
3025
|
+
"environment",
|
|
2969
3026
|
"workspace",
|
|
2970
3027
|
"metadata",
|
|
2971
3028
|
"conversation_id",
|
|
@@ -2979,6 +3036,17 @@ var KNOWN_TEST_FIELDS = /* @__PURE__ */ new Set([
|
|
|
2979
3036
|
"window_size"
|
|
2980
3037
|
]);
|
|
2981
3038
|
var SUPPORTED_WORKSPACE_REPO_FIELDS = /* @__PURE__ */ new Set(["path", "repo", "commit", "ancestor", "sparse"]);
|
|
3039
|
+
var KNOWN_REMOVED_WORKSPACE_FIELDS = /* @__PURE__ */ new Set([
|
|
3040
|
+
"template",
|
|
3041
|
+
"repos",
|
|
3042
|
+
"scope",
|
|
3043
|
+
"docker",
|
|
3044
|
+
"hooks",
|
|
3045
|
+
"env",
|
|
3046
|
+
"mode",
|
|
3047
|
+
"isolation",
|
|
3048
|
+
"path"
|
|
3049
|
+
]);
|
|
2982
3050
|
var REMOVED_TEST_FIELDS = /* @__PURE__ */ new Map([]);
|
|
2983
3051
|
REMOVED_TEST_FIELDS.set(
|
|
2984
3052
|
"input",
|
|
@@ -3108,13 +3176,15 @@ async function validateEvalFile(filePath) {
|
|
|
3108
3176
|
});
|
|
3109
3177
|
}
|
|
3110
3178
|
}
|
|
3179
|
+
await validateEnvironmentConfig(parsed.environment, absolutePath, errors, "environment");
|
|
3111
3180
|
await validateSuiteWorkspaceConfigs(parsed, absolutePath, errors);
|
|
3181
|
+
validateTargetTestbedFields(parsed.target, "target", absolutePath, errors);
|
|
3182
|
+
validateTargetsTestbedFields(parsed.targets, "targets", absolutePath, errors);
|
|
3112
3183
|
validateAuthoredWorkers(parsed, absolutePath, errors);
|
|
3113
3184
|
validateExecutionPolicy(parsed.execution, "execution", absolutePath, errors);
|
|
3114
3185
|
validateEvaluateOptions(parsed.evaluate_options, "evaluate_options", absolutePath, errors);
|
|
3115
3186
|
validateAssertArray(parsed.assert, "assert", absolutePath, errors, customAssertionTypes);
|
|
3116
3187
|
validateDefaultTest(parsed.default_test, absolutePath, errors, customAssertionTypes);
|
|
3117
|
-
await validateImportsField(parsed.imports, absolutePath, errors);
|
|
3118
3188
|
const cases = parsed.tests;
|
|
3119
3189
|
const hasImports = collectImportEntries(parsed).length > 0;
|
|
3120
3190
|
const hasScenarios = Array.isArray(parsed.scenarios);
|
|
@@ -3144,7 +3214,7 @@ async function validateEvalFile(filePath) {
|
|
|
3144
3214
|
severity: "error",
|
|
3145
3215
|
filePath: absolutePath,
|
|
3146
3216
|
location: "tests",
|
|
3147
|
-
message: "Missing or invalid 'tests' field (must be an array or a file path string, unless
|
|
3217
|
+
message: "Missing or invalid 'tests' field (must be an array or a file path string, unless scenarios are provided)"
|
|
3148
3218
|
});
|
|
3149
3219
|
return {
|
|
3150
3220
|
valid: errors.length === 0,
|
|
@@ -3264,6 +3334,12 @@ async function validateEvalFile(filePath) {
|
|
|
3264
3334
|
);
|
|
3265
3335
|
validateRunOverride(evalCase.run, `${location}.run`, absolutePath, errors);
|
|
3266
3336
|
validateTestOptions(evalCase.options, `${location}.options`, absolutePath, errors);
|
|
3337
|
+
await validateEnvironmentConfig(
|
|
3338
|
+
evalCase.environment,
|
|
3339
|
+
absolutePath,
|
|
3340
|
+
errors,
|
|
3341
|
+
`${location}.environment`
|
|
3342
|
+
);
|
|
3267
3343
|
validateConversationMode(evalCase, location, absolutePath, errors);
|
|
3268
3344
|
await validateWorkspaceConfig(
|
|
3269
3345
|
evalCase.workspace,
|
|
@@ -3292,6 +3368,43 @@ async function validateSuiteWorkspaceConfigs(parsed, absolutePath, errors) {
|
|
|
3292
3368
|
);
|
|
3293
3369
|
}
|
|
3294
3370
|
}
|
|
3371
|
+
async function validateEnvironmentConfig(environment, evalFilePath, errors, location) {
|
|
3372
|
+
if (environment === void 0) {
|
|
3373
|
+
return;
|
|
3374
|
+
}
|
|
3375
|
+
try {
|
|
3376
|
+
await resolveEnvironmentRecipe(environment, path22.dirname(evalFilePath), location);
|
|
3377
|
+
} catch (error) {
|
|
3378
|
+
errors.push({
|
|
3379
|
+
severity: "error",
|
|
3380
|
+
filePath: evalFilePath,
|
|
3381
|
+
location,
|
|
3382
|
+
message: error.message
|
|
3383
|
+
});
|
|
3384
|
+
}
|
|
3385
|
+
}
|
|
3386
|
+
function validateTargetTestbedFields(target, location, filePath, errors) {
|
|
3387
|
+
if (!isObject(target)) {
|
|
3388
|
+
return;
|
|
3389
|
+
}
|
|
3390
|
+
for (const field of ["environment", "container", "install"]) {
|
|
3391
|
+
if (target[field] === void 0) {
|
|
3392
|
+
continue;
|
|
3393
|
+
}
|
|
3394
|
+
errors.push({
|
|
3395
|
+
severity: "error",
|
|
3396
|
+
filePath,
|
|
3397
|
+
location: `${location}.${field}`,
|
|
3398
|
+
message: field === "environment" ? "Target definitions cannot include environment; author environment at suite/test/case scope." : `Target definitions cannot include ${field}; use an environment recipe for testbed setup.`
|
|
3399
|
+
});
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
function validateTargetsTestbedFields(targets, location, filePath, errors) {
|
|
3403
|
+
const entries = Array.isArray(targets) ? targets : targets === void 0 ? [] : [targets];
|
|
3404
|
+
entries.forEach((entry, index) => {
|
|
3405
|
+
validateTargetTestbedFields(entry, `${location}[${index}]`, filePath, errors);
|
|
3406
|
+
});
|
|
3407
|
+
}
|
|
3295
3408
|
function validateTestExecutionFields(caseExecution, filePath, errors, location) {
|
|
3296
3409
|
for (const key of Object.keys(caseExecution)) {
|
|
3297
3410
|
if (key === "workers") {
|
|
@@ -3413,87 +3526,11 @@ function rejectRuntimeWorkspaceConfig(workspace, filePath, errors, location) {
|
|
|
3413
3526
|
severity: "error",
|
|
3414
3527
|
filePath,
|
|
3415
3528
|
location,
|
|
3416
|
-
message: `${location} has been removed from eval YAML. Put machine-local workspace_path in .agentv/config.local.yaml under execution, or pass --workspace-path. Keep portable
|
|
3529
|
+
message: `${location} has been removed from eval YAML. Put machine-local workspace_path in .agentv/config.local.yaml under execution, or pass --workspace-path. Keep portable coding-agent testbed setup in environment.`
|
|
3417
3530
|
});
|
|
3418
3531
|
}
|
|
3419
|
-
function importEntryPath(value) {
|
|
3420
|
-
if (typeof value === "string" && value.trim().length > 0) {
|
|
3421
|
-
return value.trim();
|
|
3422
|
-
}
|
|
3423
|
-
if (!isObject(value)) {
|
|
3424
|
-
return void 0;
|
|
3425
|
-
}
|
|
3426
|
-
return typeof value.path === "string" && value.path.trim().length > 0 ? value.path.trim() : void 0;
|
|
3427
|
-
}
|
|
3428
|
-
async function validateImportsField(imports, filePath, errors) {
|
|
3429
|
-
if (imports === void 0) {
|
|
3430
|
-
return;
|
|
3431
|
-
}
|
|
3432
|
-
if (!isObject(imports)) {
|
|
3433
|
-
errors.push({
|
|
3434
|
-
severity: "error",
|
|
3435
|
-
filePath,
|
|
3436
|
-
location: "imports",
|
|
3437
|
-
message: "Invalid 'imports' field. Use imports.suites and/or imports.tests."
|
|
3438
|
-
});
|
|
3439
|
-
return;
|
|
3440
|
-
}
|
|
3441
|
-
for (const key of Object.keys(imports)) {
|
|
3442
|
-
if (key !== "suites" && key !== "tests") {
|
|
3443
|
-
errors.push({
|
|
3444
|
-
severity: "warning",
|
|
3445
|
-
filePath,
|
|
3446
|
-
location: `imports.${key}`,
|
|
3447
|
-
message: `Unknown imports field '${key}'. Use imports.suites or imports.tests.`
|
|
3448
|
-
});
|
|
3449
|
-
}
|
|
3450
|
-
}
|
|
3451
|
-
await validateImportGroup(imports.suites, "suite", "imports.suites", filePath, errors);
|
|
3452
|
-
await validateImportGroup(imports.tests, "tests", "imports.tests", filePath, errors);
|
|
3453
|
-
}
|
|
3454
|
-
async function validateImportGroup(group, type, location, filePath, errors) {
|
|
3455
|
-
if (group === void 0) {
|
|
3456
|
-
return;
|
|
3457
|
-
}
|
|
3458
|
-
const entries = Array.isArray(group) ? group : [group];
|
|
3459
|
-
for (let i = 0; i < entries.length; i++) {
|
|
3460
|
-
const entry = entries[i];
|
|
3461
|
-
const entryLocation = `${location}[${i}]`;
|
|
3462
|
-
const entryPath = importEntryPath(entry);
|
|
3463
|
-
if (!entryPath) {
|
|
3464
|
-
errors.push({
|
|
3465
|
-
severity: "error",
|
|
3466
|
-
filePath,
|
|
3467
|
-
location: entryLocation,
|
|
3468
|
-
message: "Invalid import entry. Use a path string or an object with a non-empty 'path'."
|
|
3469
|
-
});
|
|
3470
|
-
continue;
|
|
3471
|
-
}
|
|
3472
|
-
if (type === "tests" && !/\.eval\.ya?ml$/i.test(entryPath)) {
|
|
3473
|
-
await validateRawCaseImportPath(entryPath, filePath, `${entryLocation}.path`, errors);
|
|
3474
|
-
}
|
|
3475
|
-
if (isObject(entry)) {
|
|
3476
|
-
for (const key of Object.keys(entry)) {
|
|
3477
|
-
if (!KNOWN_IMPORT_FIELDS.has(key)) {
|
|
3478
|
-
errors.push({
|
|
3479
|
-
severity: "warning",
|
|
3480
|
-
filePath,
|
|
3481
|
-
location: `${entryLocation}.${key}`,
|
|
3482
|
-
message: `Unknown field '${key}'. This field will be ignored.`
|
|
3483
|
-
});
|
|
3484
|
-
}
|
|
3485
|
-
}
|
|
3486
|
-
validateIncludeSelect(entry.select, `${entryLocation}.select`, filePath, errors);
|
|
3487
|
-
validateRunOverride(entry.run, `${entryLocation}.run`, filePath, errors);
|
|
3488
|
-
}
|
|
3489
|
-
}
|
|
3490
|
-
}
|
|
3491
3532
|
function collectImportEntries(parsed) {
|
|
3492
3533
|
const entries = [];
|
|
3493
|
-
if (isObject(parsed.imports)) {
|
|
3494
|
-
entries.push(...collectImportGroup(parsed.imports.suites, "suite", "imports.suites"));
|
|
3495
|
-
entries.push(...collectImportGroup(parsed.imports.tests, "tests", "imports.tests"));
|
|
3496
|
-
}
|
|
3497
3534
|
const tests = parsed.tests;
|
|
3498
3535
|
if (Array.isArray(tests)) {
|
|
3499
3536
|
for (let i = 0; i < tests.length; i++) {
|
|
@@ -3516,42 +3553,24 @@ function collectImportEntries(parsed) {
|
|
|
3516
3553
|
}
|
|
3517
3554
|
return entries;
|
|
3518
3555
|
}
|
|
3519
|
-
function collectImportGroup(group, type, location) {
|
|
3520
|
-
if (group === void 0) {
|
|
3521
|
-
return [];
|
|
3522
|
-
}
|
|
3523
|
-
const entries = Array.isArray(group) ? group : [group];
|
|
3524
|
-
return entries.flatMap((entry, index) => {
|
|
3525
|
-
const pathValue = importEntryPath(entry);
|
|
3526
|
-
return pathValue ? [
|
|
3527
|
-
{
|
|
3528
|
-
path: pathValue,
|
|
3529
|
-
type,
|
|
3530
|
-
location: `${location}[${index}].path`,
|
|
3531
|
-
...isObject(entry) && entry.select !== void 0 ? { select: entry.select } : {},
|
|
3532
|
-
...isObject(entry) && entry.run !== void 0 ? { run: entry.run } : {}
|
|
3533
|
-
}
|
|
3534
|
-
] : [];
|
|
3535
|
-
});
|
|
3536
|
-
}
|
|
3537
3556
|
async function validateCompositionDiagnostics(filePath, parsed, errors) {
|
|
3538
|
-
const
|
|
3539
|
-
if (
|
|
3557
|
+
const includeEntries = collectImportEntries(parsed);
|
|
3558
|
+
if (includeEntries.length === 0) {
|
|
3540
3559
|
return;
|
|
3541
3560
|
}
|
|
3542
3561
|
const parentHasRuntime = hasWrapperRuntimeControls(parsed);
|
|
3543
|
-
const hasSuiteImport =
|
|
3562
|
+
const hasSuiteImport = includeEntries.some((entry) => entry.type === "suite");
|
|
3544
3563
|
if (hasSuiteImport) {
|
|
3545
3564
|
for (const location of parentWorkspaceLocations(parsed)) {
|
|
3546
3565
|
errors.push({
|
|
3547
3566
|
severity: "error",
|
|
3548
3567
|
filePath,
|
|
3549
3568
|
location,
|
|
3550
|
-
message: "Parent
|
|
3569
|
+
message: location === "environment" ? "Parent environment is not allowed with legacy tests[].include suite entries. Run eval files directly, or use tests: file://... for raw cases that should use the parent environment." : "Parent workspace is not allowed with legacy tests[].include suite entries. Run eval files directly, or use tests: file://... for raw cases that should use the parent workspace."
|
|
3551
3570
|
});
|
|
3552
3571
|
}
|
|
3553
3572
|
}
|
|
3554
|
-
for (const entry of
|
|
3573
|
+
for (const entry of includeEntries) {
|
|
3555
3574
|
const resolvedSuites = await resolveSuiteIncludePaths(entry.path, path22.dirname(filePath));
|
|
3556
3575
|
if (entry.type === "suite") {
|
|
3557
3576
|
for (const resolvedSuite of resolvedSuites) {
|
|
@@ -3567,7 +3586,7 @@ async function validateCompositionDiagnostics(filePath, parsed, errors) {
|
|
|
3567
3586
|
severity: "warning",
|
|
3568
3587
|
filePath,
|
|
3569
3588
|
location: entry.location,
|
|
3570
|
-
message: parentHasRuntime ? `Imported suite '${resolvedSuite.displayPath}' defines ${runtimeFields.join(", ")}, but child target and run controls are ignored
|
|
3589
|
+
message: parentHasRuntime ? `Imported suite '${resolvedSuite.displayPath}' defines ${runtimeFields.join(", ")}, but child target 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 target and run controls are ignored by legacy tests[].include suite imports. Prefer running eval files directly with CLI multi-file selection and tags.`
|
|
3571
3590
|
});
|
|
3572
3591
|
}
|
|
3573
3592
|
continue;
|
|
@@ -3581,7 +3600,7 @@ async function validateCompositionDiagnostics(filePath, parsed, errors) {
|
|
|
3581
3600
|
severity: "warning",
|
|
3582
3601
|
filePath,
|
|
3583
3602
|
location: entry.location,
|
|
3584
|
-
message: `
|
|
3603
|
+
message: `Legacy tests[].include with type: tests imports raw cases from eval suite '${resolvedSuite.displayPath}' and drops suite context, including child environment, workspace, input, assertions, metadata, target, and run controls. Prefer tests: file://... for raw case files.`
|
|
3585
3604
|
});
|
|
3586
3605
|
}
|
|
3587
3606
|
}
|
|
@@ -3620,6 +3639,9 @@ function parentWorkspaceLocations(parsed) {
|
|
|
3620
3639
|
if (parsed.workspace !== void 0) {
|
|
3621
3640
|
locations.push("workspace");
|
|
3622
3641
|
}
|
|
3642
|
+
if (parsed.environment !== void 0) {
|
|
3643
|
+
locations.push("environment");
|
|
3644
|
+
}
|
|
3623
3645
|
if (isObject(parsed.execution) && parsed.execution.workspace !== void 0) {
|
|
3624
3646
|
locations.push("execution.workspace");
|
|
3625
3647
|
}
|
|
@@ -3634,12 +3656,11 @@ async function readImportedSuite(filePath) {
|
|
|
3634
3656
|
}
|
|
3635
3657
|
}
|
|
3636
3658
|
function validateIncludeEntry(entry, location, filePath, errors) {
|
|
3637
|
-
const mode = entry.type === "suite" ? "suites" : entry.type === "tests" ? "tests" : void 0;
|
|
3638
3659
|
errors.push({
|
|
3639
3660
|
severity: "warning",
|
|
3640
3661
|
filePath,
|
|
3641
3662
|
location,
|
|
3642
|
-
message:
|
|
3663
|
+
message: entry.type === "suite" ? "tests[].include with type: suite is deprecated. Run eval files directly with CLI multi-file selection and tags instead." : "tests[].include is deprecated. Use tests: file://... or string entries inside tests: for raw case files."
|
|
3643
3664
|
});
|
|
3644
3665
|
for (const key of Object.keys(entry)) {
|
|
3645
3666
|
if (!KNOWN_INCLUDE_FIELDS.has(key)) {
|
|
@@ -4041,35 +4062,18 @@ async function validateWorkspaceConfig(workspace, evalFilePath, errors, location
|
|
|
4041
4062
|
if (workspace === void 0) {
|
|
4042
4063
|
return;
|
|
4043
4064
|
}
|
|
4044
|
-
if (
|
|
4045
|
-
validateWorkspaceRepoConfig(workspace, evalFilePath, errors, location);
|
|
4046
|
-
return;
|
|
4047
|
-
}
|
|
4048
|
-
if (typeof workspace !== "string") {
|
|
4049
|
-
return;
|
|
4050
|
-
}
|
|
4051
|
-
const workspacePath = path22.resolve(path22.dirname(evalFilePath), workspace);
|
|
4052
|
-
try {
|
|
4053
|
-
const workspaceContent = await readFile22(workspacePath, "utf8");
|
|
4054
|
-
const parsedWorkspace = interpolateEnv(parseYamlValue(workspaceContent), process.env);
|
|
4055
|
-
if (!isObject(parsedWorkspace)) {
|
|
4056
|
-
errors.push({
|
|
4057
|
-
severity: "error",
|
|
4058
|
-
filePath: evalFilePath,
|
|
4059
|
-
location,
|
|
4060
|
-
message: `External workspace file must contain a YAML object: ${workspace}`
|
|
4061
|
-
});
|
|
4062
|
-
return;
|
|
4063
|
-
}
|
|
4064
|
-
validateWorkspaceRepoConfig(parsedWorkspace, workspacePath, errors, location);
|
|
4065
|
-
} catch (error) {
|
|
4066
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
4065
|
+
if (typeof workspace === "string") {
|
|
4067
4066
|
errors.push({
|
|
4068
4067
|
severity: "error",
|
|
4069
4068
|
filePath: evalFilePath,
|
|
4070
4069
|
location,
|
|
4071
|
-
message:
|
|
4070
|
+
message: `${location} has been removed from public eval YAML. Use environment: file://... for reusable coding-agent testbed recipes.`
|
|
4072
4071
|
});
|
|
4072
|
+
return;
|
|
4073
|
+
}
|
|
4074
|
+
if (isObject(workspace)) {
|
|
4075
|
+
validateWorkspaceRepoConfig(workspace, evalFilePath, errors, location);
|
|
4076
|
+
return;
|
|
4073
4077
|
}
|
|
4074
4078
|
}
|
|
4075
4079
|
function validateWorkspaceRepoConfig(workspace, filePath, errors, location) {
|
|
@@ -4078,12 +4082,79 @@ function validateWorkspaceRepoConfig(workspace, filePath, errors, location) {
|
|
|
4078
4082
|
const afterEachHook = isObject(hooks) ? hooks.after_each : void 0;
|
|
4079
4083
|
const scope = workspace.scope;
|
|
4080
4084
|
const docker = workspace.docker;
|
|
4085
|
+
let hasRemovedTestbedField = false;
|
|
4086
|
+
if (Object.keys(workspace).length === 0) {
|
|
4087
|
+
errors.push({
|
|
4088
|
+
severity: "error",
|
|
4089
|
+
filePath,
|
|
4090
|
+
location,
|
|
4091
|
+
message: "workspace has been removed from public eval YAML. Use environment for coding-agent testbed setup."
|
|
4092
|
+
});
|
|
4093
|
+
return;
|
|
4094
|
+
}
|
|
4095
|
+
if ("template" in workspace) {
|
|
4096
|
+
hasRemovedTestbedField = true;
|
|
4097
|
+
errors.push({
|
|
4098
|
+
severity: "error",
|
|
4099
|
+
filePath,
|
|
4100
|
+
location: `${location}.template`,
|
|
4101
|
+
message: "workspace.template has been removed from public eval YAML. Use environment.workdir and environment.setup for authored testbed setup."
|
|
4102
|
+
});
|
|
4103
|
+
}
|
|
4104
|
+
if ("repos" in workspace) {
|
|
4105
|
+
hasRemovedTestbedField = true;
|
|
4106
|
+
errors.push({
|
|
4107
|
+
severity: "error",
|
|
4108
|
+
filePath,
|
|
4109
|
+
location: `${location}.repos`,
|
|
4110
|
+
message: "workspace.repos has been removed from public eval YAML. Use environment.setup.command argv to materialize repositories."
|
|
4111
|
+
});
|
|
4112
|
+
}
|
|
4113
|
+
if ("scope" in workspace) {
|
|
4114
|
+
hasRemovedTestbedField = true;
|
|
4115
|
+
errors.push({
|
|
4116
|
+
severity: "error",
|
|
4117
|
+
filePath,
|
|
4118
|
+
location: `${location}.scope`,
|
|
4119
|
+
message: "workspace.scope has been removed from public eval YAML. Use environment at suite/test scope and let runtime manage workspace lifetime."
|
|
4120
|
+
});
|
|
4121
|
+
}
|
|
4122
|
+
if ("docker" in workspace) {
|
|
4123
|
+
hasRemovedTestbedField = true;
|
|
4124
|
+
errors.push({
|
|
4125
|
+
severity: "error",
|
|
4126
|
+
filePath,
|
|
4127
|
+
location: `${location}.docker`,
|
|
4128
|
+
message: "workspace.docker has been removed from public eval YAML. Use environment.type: docker with image or context."
|
|
4129
|
+
});
|
|
4130
|
+
}
|
|
4131
|
+
if ("hooks" in workspace) {
|
|
4132
|
+
hasRemovedTestbedField = true;
|
|
4133
|
+
errors.push({
|
|
4134
|
+
severity: "error",
|
|
4135
|
+
filePath,
|
|
4136
|
+
location: `${location}.hooks`,
|
|
4137
|
+
message: "workspace.hooks has been removed from public eval YAML. Use environment.setup for testbed setup and extensions for lifecycle instrumentation."
|
|
4138
|
+
});
|
|
4139
|
+
}
|
|
4140
|
+
if ("env" in workspace) {
|
|
4141
|
+
hasRemovedTestbedField = true;
|
|
4142
|
+
errors.push({
|
|
4143
|
+
severity: "error",
|
|
4144
|
+
filePath,
|
|
4145
|
+
location: `${location}.env`,
|
|
4146
|
+
message: "workspace.env has been removed from public eval YAML. Use top-level env for provider/eval variables or environment.env for environment-scoped variables."
|
|
4147
|
+
});
|
|
4148
|
+
}
|
|
4149
|
+
if (hasRemovedTestbedField) {
|
|
4150
|
+
return;
|
|
4151
|
+
}
|
|
4081
4152
|
if ("mode" in workspace) {
|
|
4082
4153
|
errors.push({
|
|
4083
4154
|
severity: "error",
|
|
4084
4155
|
filePath,
|
|
4085
4156
|
location: `${location}.mode`,
|
|
4086
|
-
message: "workspace.mode has been removed from eval YAML. Use workspace.
|
|
4157
|
+
message: "workspace.mode has been removed from eval YAML. Use --workspace-path or execution.workspace_path for machine-local existing directories, and environment for portable testbed setup."
|
|
4087
4158
|
});
|
|
4088
4159
|
}
|
|
4089
4160
|
if ("isolation" in workspace) {
|
|
@@ -4091,7 +4162,7 @@ function validateWorkspaceRepoConfig(workspace, filePath, errors, location) {
|
|
|
4091
4162
|
severity: "error",
|
|
4092
4163
|
filePath,
|
|
4093
4164
|
location: `${location}.isolation`,
|
|
4094
|
-
message: "workspace.isolation has been removed. Use
|
|
4165
|
+
message: "workspace.isolation has been removed from eval YAML. Use environment at suite/test scope and let AgentV manage runtime isolation."
|
|
4095
4166
|
});
|
|
4096
4167
|
}
|
|
4097
4168
|
if ("path" in workspace) {
|
|
@@ -4099,7 +4170,18 @@ function validateWorkspaceRepoConfig(workspace, filePath, errors, location) {
|
|
|
4099
4170
|
severity: "error",
|
|
4100
4171
|
filePath,
|
|
4101
4172
|
location: `${location}.path`,
|
|
4102
|
-
message: "workspace.path has been removed from eval YAML.
|
|
4173
|
+
message: "workspace.path has been removed from eval YAML. Use environment.workdir for portable testbed cwd; put existing machine-local workspace paths in .agentv/config.local.yaml execution.workspace_path or pass --workspace-path."
|
|
4174
|
+
});
|
|
4175
|
+
}
|
|
4176
|
+
for (const key of Object.keys(workspace)) {
|
|
4177
|
+
if (KNOWN_REMOVED_WORKSPACE_FIELDS.has(key)) {
|
|
4178
|
+
continue;
|
|
4179
|
+
}
|
|
4180
|
+
errors.push({
|
|
4181
|
+
severity: "error",
|
|
4182
|
+
filePath,
|
|
4183
|
+
location: `${location}.${key}`,
|
|
4184
|
+
message: `${location}.${key} has been removed from public eval YAML. Use environment for portable coding-agent testbed setup.`
|
|
4103
4185
|
});
|
|
4104
4186
|
}
|
|
4105
4187
|
if (scope !== void 0 && scope !== "suite" && scope !== "attempt") {
|
|
@@ -4412,11 +4494,11 @@ async function validateSuiteImportCycles(filePath, parsed, errors) {
|
|
|
4412
4494
|
await validateSuiteImportCyclesFromParsed(filePath, parsed, [root], errors);
|
|
4413
4495
|
}
|
|
4414
4496
|
async function validateSuiteImportCyclesFromParsed(currentFilePath, parsed, stack, errors) {
|
|
4415
|
-
const
|
|
4416
|
-
if (
|
|
4497
|
+
const includeEntries = collectImportEntries(parsed);
|
|
4498
|
+
if (includeEntries.length === 0) {
|
|
4417
4499
|
return;
|
|
4418
4500
|
}
|
|
4419
|
-
for (const entry of
|
|
4501
|
+
for (const entry of includeEntries) {
|
|
4420
4502
|
if (entry.type !== "suite") {
|
|
4421
4503
|
continue;
|
|
4422
4504
|
}
|
|
@@ -5092,7 +5174,7 @@ function validateUnknownSettings(target, provider, absolutePath, location, error
|
|
|
5092
5174
|
severity: "warning",
|
|
5093
5175
|
filePath: absolutePath,
|
|
5094
5176
|
location: `${location}.${key}`,
|
|
5095
|
-
message: "workspace_template has been removed from targets. Use eval-level
|
|
5177
|
+
message: "workspace_template has been removed from targets. Use eval-level environment.workdir and environment.setup instead."
|
|
5096
5178
|
});
|
|
5097
5179
|
continue;
|
|
5098
5180
|
}
|
|
@@ -7445,7 +7527,7 @@ async function runEvalCommand(input) {
|
|
|
7445
7527
|
const resolvedExperiment = resolveExperimentForRun(options.experiment);
|
|
7446
7528
|
const evalPathInputs = input.testFiles.length > 0 ? [...input.testFiles] : [];
|
|
7447
7529
|
if (evalPathInputs.length === 0 && process.stdin.isTTY) {
|
|
7448
|
-
const { launchInteractiveWizard } = await import("./interactive-
|
|
7530
|
+
const { launchInteractiveWizard } = await import("./interactive-36ZNMQB2.js");
|
|
7449
7531
|
await launchInteractiveWizard();
|
|
7450
7532
|
return void 0;
|
|
7451
7533
|
}
|
|
@@ -7785,7 +7867,7 @@ async function runEvalCommand(input) {
|
|
|
7785
7867
|
});
|
|
7786
7868
|
let transcriptProviderFactory;
|
|
7787
7869
|
if (options.transcript) {
|
|
7788
|
-
const { TranscriptProvider } = await import("./dist-
|
|
7870
|
+
const { TranscriptProvider } = await import("./dist-DEPJOMCA.js");
|
|
7789
7871
|
const transcriptProvider = await TranscriptProvider.fromFile(options.transcript);
|
|
7790
7872
|
const totalTests = [...fileMetadata.values()].reduce(
|
|
7791
7873
|
(sum, meta) => sum + meta.testCases.length,
|
|
@@ -8051,7 +8133,7 @@ ${formatRequiredVersionFailureNote(requiredVersionCheck)}`);
|
|
|
8051
8133
|
const sourceTests = activeSourceTests;
|
|
8052
8134
|
const taskBundleTargets = buildTaskBundleTargetSelections(activeTestFiles, fileMetadata);
|
|
8053
8135
|
if (isResumeAppend) {
|
|
8054
|
-
const { writePerTestArtifacts } = await import("./artifact-writer-
|
|
8136
|
+
const { writePerTestArtifacts } = await import("./artifact-writer-SN6UNL5G.js");
|
|
8055
8137
|
await writePerTestArtifacts(allResults, runDir, {
|
|
8056
8138
|
experiment: normalizeExperimentName(options.experiment),
|
|
8057
8139
|
runId: path12.basename(runDir),
|
|
@@ -8269,4 +8351,4 @@ export {
|
|
|
8269
8351
|
filterByCategory,
|
|
8270
8352
|
runEvalCommand
|
|
8271
8353
|
};
|
|
8272
|
-
//# sourceMappingURL=chunk-
|
|
8354
|
+
//# sourceMappingURL=chunk-T4AD3H3Y.js.map
|