agentv 5.2.0-next.1 → 5.3.1-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 +22 -20
- package/dist/{artifact-writer-SN6UNL5G.js → artifact-writer-7NBCOAYC.js} +4 -4
- package/dist/{chunk-3X357HS4.js → chunk-ASIGJIOJ.js} +107 -31
- package/dist/chunk-ASIGJIOJ.js.map +1 -0
- package/dist/{chunk-3S6A2RKR.js → chunk-ELCJ23K4.js} +18879 -17538
- package/dist/chunk-ELCJ23K4.js.map +1 -0
- package/dist/{chunk-T4AD3H3Y.js → chunk-LKGARI3W.js} +399 -32
- package/dist/chunk-LKGARI3W.js.map +1 -0
- package/dist/{chunk-ALVZQUZP.js → chunk-LXBI3SPX.js} +142 -14
- package/dist/chunk-LXBI3SPX.js.map +1 -0
- package/dist/{chunk-46K2OET3.js → chunk-RKE7SSET.js} +2 -2
- package/dist/cli.js +5 -5
- package/dist/dashboard/assets/{index-DNgf3qJ2.js → index-CbEMiJSb.js} +1 -1
- package/dist/dashboard/assets/{index-r_jSJmlw.js → index-DTA6-l7q.js} +3 -3
- package/dist/dashboard/index.html +1 -1
- package/dist/{dist-DEPJOMCA.js → dist-NMXMI5SK.js} +25 -5
- package/dist/index.js +5 -5
- package/dist/{interactive-36ZNMQB2.js → interactive-BN527UV3.js} +5 -5
- package/dist/skills/agentv-bench/SKILL.md +15 -14
- package/dist/skills/agentv-bench/agents/analyzer.md +2 -2
- package/dist/skills/agentv-bench/agents/comparator.md +3 -3
- package/dist/skills/agentv-bench/agents/executor.md +1 -1
- package/dist/skills/agentv-bench/agents/grader.md +4 -2
- package/dist/skills/agentv-bench/references/autoresearch.md +9 -9
- package/dist/skills/agentv-bench/references/description-optimization.md +5 -6
- package/dist/skills/agentv-bench/references/environment-adaptation.md +6 -6
- package/dist/skills/agentv-bench/references/eval-yaml-spec.md +50 -56
- 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 +138 -22
- package/dist/skills/agentv-eval-writer/SKILL.md +103 -63
- package/dist/skills/agentv-eval-writer/references/custom-evaluators.md +10 -5
- package/dist/skills/agentv-eval-writer/references/eval.schema.json +749 -2158
- package/dist/skills/agentv-eval-writer/references/rubric-evaluator.md +1 -1
- package/dist/{ts-eval-loader-OMG2JBHP-OP5RR7A3.js → ts-eval-loader-2RFVZHCT-7CZ3DCDD.js} +8 -4
- package/package.json +1 -1
- package/dist/chunk-3S6A2RKR.js.map +0 -1
- package/dist/chunk-3X357HS4.js.map +0 -1
- package/dist/chunk-ALVZQUZP.js.map +0 -1
- package/dist/chunk-T4AD3H3Y.js.map +0 -1
- /package/dist/{artifact-writer-SN6UNL5G.js.map → artifact-writer-7NBCOAYC.js.map} +0 -0
- /package/dist/{chunk-46K2OET3.js.map → chunk-RKE7SSET.js.map} +0 -0
- /package/dist/{dist-DEPJOMCA.js.map → dist-NMXMI5SK.js.map} +0 -0
- /package/dist/{interactive-36ZNMQB2.js.map → interactive-BN527UV3.js.map} +0 -0
- /package/dist/{ts-eval-loader-OMG2JBHP-OP5RR7A3.js.map → ts-eval-loader-2RFVZHCT-7CZ3DCDD.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-RKE7SSET.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-LXBI3SPX.js";
|
|
22
22
|
import {
|
|
23
23
|
AGENTV_LOCAL_CONFIG_FILE_NAME,
|
|
24
24
|
AGENTV_LOCAL_CONFIG_YML_FILE_NAME,
|
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
interpolateEnv,
|
|
52
52
|
isAgentVConfigFileName,
|
|
53
53
|
isGraderKind,
|
|
54
|
+
isTypeScriptEvalConfigFileName,
|
|
54
55
|
listTargetNames,
|
|
55
56
|
loadCasesFromDirectory,
|
|
56
57
|
loadCasesFromFile,
|
|
@@ -59,6 +60,7 @@ import {
|
|
|
59
60
|
loadTestSuite,
|
|
60
61
|
loadTestSuiteFromYamlObject,
|
|
61
62
|
normalizeComposableConfigGraph,
|
|
63
|
+
normalizeMetricsArtifactWire,
|
|
62
64
|
normalizeResultRow,
|
|
63
65
|
normalizeTargetDefinition,
|
|
64
66
|
parseJsonlResults,
|
|
@@ -82,8 +84,9 @@ import {
|
|
|
82
84
|
toSnakeCaseDeep,
|
|
83
85
|
traceEnvelopeToTraceSummary,
|
|
84
86
|
traceEnvelopeToTranscriptMessages,
|
|
87
|
+
typeScriptEvalConfigGlob,
|
|
85
88
|
writeInitialRunSummaryArtifact
|
|
86
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-ELCJ23K4.js";
|
|
87
90
|
|
|
88
91
|
// src/commands/eval/shared.ts
|
|
89
92
|
import { constants } from "node:fs";
|
|
@@ -214,7 +217,7 @@ function agentSkillsToAgentVYamlObject(suite) {
|
|
|
214
217
|
|
|
215
218
|
// src/commands/eval/shared.ts
|
|
216
219
|
function isNativeEvalFile(filePath) {
|
|
217
|
-
return /\.(ya?ml|jsonl
|
|
220
|
+
return /\.(ya?ml|jsonl)$/i.test(filePath) || isTypeScriptEvalConfigFileName(filePath);
|
|
218
221
|
}
|
|
219
222
|
function shouldInspectJsonPath(filePath) {
|
|
220
223
|
const base = path.basename(filePath).toLowerCase();
|
|
@@ -264,7 +267,7 @@ async function resolveEvalPaths(evalPaths, cwd, options = {}) {
|
|
|
264
267
|
continue;
|
|
265
268
|
}
|
|
266
269
|
if (candidateStats.isDirectory()) {
|
|
267
|
-
const filePattern = options.allowReadAdapters ?
|
|
270
|
+
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()}}`;
|
|
268
271
|
const dirGlob = path.posix.join(candidatePath.replace(/\\/g, "/"), `**/${filePattern}`);
|
|
269
272
|
const dirMatches = await fg(dirGlob, {
|
|
270
273
|
absolute: true,
|
|
@@ -346,7 +349,7 @@ async function findRepoRoot(start) {
|
|
|
346
349
|
// package.json
|
|
347
350
|
var package_default = {
|
|
348
351
|
name: "agentv",
|
|
349
|
-
version: "5.
|
|
352
|
+
version: "5.3.1-next.1",
|
|
350
353
|
description: "CLI entry point for AgentV",
|
|
351
354
|
type: "module",
|
|
352
355
|
repository: {
|
|
@@ -1053,7 +1056,9 @@ function hydrateTrace(baseDir, record, options) {
|
|
|
1053
1056
|
}
|
|
1054
1057
|
function hydrateManifestRecord(baseDir, record, options) {
|
|
1055
1058
|
const grading = readOptionalJson(baseDir, record.grading_path);
|
|
1056
|
-
const metrics =
|
|
1059
|
+
const metrics = normalizeMetricsArtifactWire(
|
|
1060
|
+
readOptionalJson(baseDir, record.metrics_path)
|
|
1061
|
+
);
|
|
1057
1062
|
const timing = metrics ?? readOptionalJson(baseDir, record.timing_path);
|
|
1058
1063
|
const testId = record.test_id ?? "unknown";
|
|
1059
1064
|
const gradingAssertions = grading ? collectComponentAssertions(grading.component_results) : void 0;
|
|
@@ -2853,18 +2858,63 @@ var UNSUPPORTED_PROMPTFOO_ASSERTION_TYPES = /* @__PURE__ */ new Set([
|
|
|
2853
2858
|
"human",
|
|
2854
2859
|
"max-score",
|
|
2855
2860
|
"tool-call-f1",
|
|
2856
|
-
"skill-used",
|
|
2857
|
-
"trajectory:goal-success",
|
|
2858
|
-
"trajectory:tool-args-match",
|
|
2859
|
-
"trajectory:step-count",
|
|
2860
|
-
"trajectory:tool-sequence",
|
|
2861
|
-
"trajectory:tool-used",
|
|
2862
2861
|
"trace-error-spans",
|
|
2863
2862
|
"trace-span-count",
|
|
2864
2863
|
"trace-span-duration",
|
|
2865
2864
|
"search-rubric",
|
|
2866
2865
|
"word-count"
|
|
2867
2866
|
]);
|
|
2867
|
+
function formatJsonValue(value) {
|
|
2868
|
+
if (typeof value === "string") return value;
|
|
2869
|
+
try {
|
|
2870
|
+
return JSON.stringify(value);
|
|
2871
|
+
} catch {
|
|
2872
|
+
return String(value);
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
function hasToolTrajectoryLatencyCheck(value) {
|
|
2876
|
+
const expected = value.expected;
|
|
2877
|
+
return Array.isArray(expected) && expected.some(
|
|
2878
|
+
(item) => isObject(item) && (item.max_duration_ms !== void 0 || item.maxDurationMs !== void 0)
|
|
2879
|
+
);
|
|
2880
|
+
}
|
|
2881
|
+
function staleSkillTriggerMessage(value) {
|
|
2882
|
+
const skill = typeof value.skill === "string" && value.skill.trim() ? value.skill.trim() : "";
|
|
2883
|
+
const shouldTrigger = value.should_trigger !== false;
|
|
2884
|
+
if (!skill) {
|
|
2885
|
+
return "Authored assertion type 'skill-trigger' has been removed. Use 'skill-used' with value: <skill> for expected skill use, or 'not-skill-used' with value: <skill> when the skill must not be used.";
|
|
2886
|
+
}
|
|
2887
|
+
const replacementType = shouldTrigger ? "skill-used" : "not-skill-used";
|
|
2888
|
+
return `Authored assertion type 'skill-trigger' has been removed. Replace skill: ${skill} with type: ${replacementType}, value: ${skill}.`;
|
|
2889
|
+
}
|
|
2890
|
+
function staleToolTrajectoryMessage(value) {
|
|
2891
|
+
const mode = typeof value.mode === "string" ? value.mode : void 0;
|
|
2892
|
+
if (hasToolTrajectoryLatencyCheck(value)) {
|
|
2893
|
+
return "Authored assertion type 'tool-trajectory' has been removed. Per-tool latency checks such as max_duration_ms have no Promptfoo trajectory:* equivalent in AgentV yet; use a custom script assertion or track this as unsupported future scope.";
|
|
2894
|
+
}
|
|
2895
|
+
if (mode === "any_order" && isObject(value.minimums)) {
|
|
2896
|
+
const [toolName, min] = Object.entries(value.minimums)[0] ?? [];
|
|
2897
|
+
const example = typeof toolName === "string" ? ` For example: type: trajectory:tool-used, value: { name: ${toolName}, min: ${formatJsonValue(min)} }.` : "";
|
|
2898
|
+
return `Authored assertion type 'tool-trajectory' has been removed. Replace mode: any_order minimums with one Promptfoo trajectory:tool-used assertion per tool.${example}`;
|
|
2899
|
+
}
|
|
2900
|
+
if ((mode === "in_order" || mode === "exact") && Array.isArray(value.expected)) {
|
|
2901
|
+
const steps = value.expected.filter(isObject).map((item) => item.tool).filter((tool) => typeof tool === "string");
|
|
2902
|
+
const hasArgs = value.expected.some(
|
|
2903
|
+
(item) => isObject(item) && item.args !== void 0 && item.args !== "any"
|
|
2904
|
+
);
|
|
2905
|
+
const sequenceHint = steps.length > 0 ? ` Use type: trajectory:tool-sequence, value: { mode: ${mode}, steps: ${formatJsonValue(steps)} }.` : " Use type: trajectory:tool-sequence with value: { mode, steps }.";
|
|
2906
|
+
const argsHint = hasArgs ? " Move expected args checks to trajectory:tool-args-match with Promptfoo mode: partial or exact." : "";
|
|
2907
|
+
return `Authored assertion type 'tool-trajectory' has been removed.${sequenceHint}${argsHint}`;
|
|
2908
|
+
}
|
|
2909
|
+
return "Authored assertion type 'tool-trajectory' has been removed. Use Promptfoo trajectory:* assertions: trajectory:tool-used for tool presence/counts, trajectory:tool-sequence for in_order/exact steps, and trajectory:tool-args-match for argument checks. AgentV-specific latency checks are unsupported future scope.";
|
|
2910
|
+
}
|
|
2911
|
+
function staleAuthoredAssertionMessage(value) {
|
|
2912
|
+
if (typeof value.type !== "string") return void 0;
|
|
2913
|
+
const type = value.type.replace(/_/g, "-");
|
|
2914
|
+
if (type === "skill-trigger") return staleSkillTriggerMessage(value);
|
|
2915
|
+
if (type === "tool-trajectory") return staleToolTrajectoryMessage(value);
|
|
2916
|
+
return void 0;
|
|
2917
|
+
}
|
|
2868
2918
|
var VALID_TEST_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
2869
2919
|
".csv",
|
|
2870
2920
|
".cjs",
|
|
@@ -2984,6 +3034,14 @@ var REMOVED_TOP_LEVEL_FIELDS = /* @__PURE__ */ new Map([
|
|
|
2984
3034
|
"providers",
|
|
2985
3035
|
"Top-level 'providers' is not a runtime alias in AgentV eval YAML. Use 'targets' for systems under test; provider names backend kind inside each target."
|
|
2986
3036
|
],
|
|
3037
|
+
[
|
|
3038
|
+
"eval_cases",
|
|
3039
|
+
"Top-level 'eval_cases' has been removed from authored eval YAML. Use 'tests' instead."
|
|
3040
|
+
],
|
|
3041
|
+
[
|
|
3042
|
+
"evalcases",
|
|
3043
|
+
"Top-level 'evalcases' has been removed from authored eval YAML. Use 'tests' instead."
|
|
3044
|
+
],
|
|
2987
3045
|
["repeat", "Top-level 'repeat' has been removed. Use evaluate_options.repeat instead."],
|
|
2988
3046
|
["runs", "Top-level 'runs' has been removed. Use evaluate_options.repeat.count instead."],
|
|
2989
3047
|
[
|
|
@@ -2998,11 +3056,11 @@ var REMOVED_TOP_LEVEL_FIELDS = /* @__PURE__ */ new Map([
|
|
|
2998
3056
|
[
|
|
2999
3057
|
"preprocessors",
|
|
3000
3058
|
"Top-level 'preprocessors' has been removed from authored eval YAML. Use default_test.options.transform or assertion-level transform instead."
|
|
3001
|
-
]
|
|
3059
|
+
],
|
|
3060
|
+
["providerPromptMap", "Top-level 'providerPromptMap' is not supported. Use 'targets'."],
|
|
3061
|
+
["provider_prompt_map", "Top-level 'provider_prompt_map' is not supported. Use 'targets'."]
|
|
3002
3062
|
]);
|
|
3003
3063
|
var DEPRECATED_TOP_LEVEL_FIELDS = /* @__PURE__ */ new Map([
|
|
3004
|
-
["eval_cases", "'eval_cases' is deprecated. Use 'tests' instead."],
|
|
3005
|
-
["evalcases", "'evalcases' is deprecated. Use 'tests' instead."],
|
|
3006
3064
|
["evaluator", "'evaluator' is deprecated. Use 'assert' instead."]
|
|
3007
3065
|
]);
|
|
3008
3066
|
var KNOWN_TEST_FIELDS = /* @__PURE__ */ new Set([
|
|
@@ -3035,6 +3093,7 @@ var KNOWN_TEST_FIELDS = /* @__PURE__ */ new Set([
|
|
|
3035
3093
|
"on_turn_failure",
|
|
3036
3094
|
"window_size"
|
|
3037
3095
|
]);
|
|
3096
|
+
var KNOWN_SCENARIO_FIELDS = /* @__PURE__ */ new Set(["description", "config", "tests"]);
|
|
3038
3097
|
var SUPPORTED_WORKSPACE_REPO_FIELDS = /* @__PURE__ */ new Set(["path", "repo", "commit", "ancestor", "sparse"]);
|
|
3039
3098
|
var KNOWN_REMOVED_WORKSPACE_FIELDS = /* @__PURE__ */ new Set([
|
|
3040
3099
|
"template",
|
|
@@ -3052,6 +3111,22 @@ REMOVED_TEST_FIELDS.set(
|
|
|
3052
3111
|
"input",
|
|
3053
3112
|
"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."
|
|
3054
3113
|
);
|
|
3114
|
+
REMOVED_TEST_FIELDS.set(
|
|
3115
|
+
"preprocessors",
|
|
3116
|
+
"tests[].preprocessors has been removed from authored eval YAML. Use tests[].options.transform or assertion-level transform instead."
|
|
3117
|
+
);
|
|
3118
|
+
REMOVED_TEST_FIELDS.set(
|
|
3119
|
+
"postprocess",
|
|
3120
|
+
"tests[].postprocess has been removed from authored eval YAML. Use tests[].options.transform instead."
|
|
3121
|
+
);
|
|
3122
|
+
REMOVED_TEST_FIELDS.set(
|
|
3123
|
+
"eval_cases",
|
|
3124
|
+
"tests[].eval_cases has been removed from authored eval YAML. Use 'tests' rows directly."
|
|
3125
|
+
);
|
|
3126
|
+
REMOVED_TEST_FIELDS.set(
|
|
3127
|
+
"evalcases",
|
|
3128
|
+
"tests[].evalcases has been removed from authored eval YAML. Use 'tests' rows directly."
|
|
3129
|
+
);
|
|
3055
3130
|
var DEPRECATED_TEST_FIELDS = /* @__PURE__ */ new Map([
|
|
3056
3131
|
["evaluator", "'evaluator' is deprecated. Use 'assert' instead."],
|
|
3057
3132
|
["expected_outcome", "'expected_outcome' is deprecated. Use 'assert' instead."]
|
|
@@ -3185,6 +3260,7 @@ async function validateEvalFile(filePath) {
|
|
|
3185
3260
|
validateEvaluateOptions(parsed.evaluate_options, "evaluate_options", absolutePath, errors);
|
|
3186
3261
|
validateAssertArray(parsed.assert, "assert", absolutePath, errors, customAssertionTypes);
|
|
3187
3262
|
validateDefaultTest(parsed.default_test, absolutePath, errors, customAssertionTypes);
|
|
3263
|
+
await validateScenarios(parsed.scenarios, parsed, absolutePath, errors, customAssertionTypes);
|
|
3188
3264
|
const cases = parsed.tests;
|
|
3189
3265
|
const hasImports = collectImportEntries(parsed).length > 0;
|
|
3190
3266
|
const hasScenarios = Array.isArray(parsed.scenarios);
|
|
@@ -3357,6 +3433,32 @@ async function validateEvalFile(filePath) {
|
|
|
3357
3433
|
errors
|
|
3358
3434
|
};
|
|
3359
3435
|
}
|
|
3436
|
+
async function validateTypeScriptEvalConfigFile(filePath) {
|
|
3437
|
+
const absolutePath = path22.resolve(filePath);
|
|
3438
|
+
try {
|
|
3439
|
+
const { loadTsEvalSuite } = await import("./ts-eval-loader-2RFVZHCT-7CZ3DCDD.js");
|
|
3440
|
+
await loadTsEvalSuite(absolutePath, process.cwd());
|
|
3441
|
+
return {
|
|
3442
|
+
valid: true,
|
|
3443
|
+
filePath: absolutePath,
|
|
3444
|
+
fileType: "eval",
|
|
3445
|
+
errors: []
|
|
3446
|
+
};
|
|
3447
|
+
} catch (error) {
|
|
3448
|
+
return {
|
|
3449
|
+
valid: false,
|
|
3450
|
+
filePath: absolutePath,
|
|
3451
|
+
fileType: "eval",
|
|
3452
|
+
errors: [
|
|
3453
|
+
{
|
|
3454
|
+
severity: "error",
|
|
3455
|
+
filePath: absolutePath,
|
|
3456
|
+
message: error.message
|
|
3457
|
+
}
|
|
3458
|
+
]
|
|
3459
|
+
};
|
|
3460
|
+
}
|
|
3461
|
+
}
|
|
3360
3462
|
async function validateSuiteWorkspaceConfigs(parsed, absolutePath, errors) {
|
|
3361
3463
|
await validateWorkspaceConfig(parsed.workspace, absolutePath, errors, "workspace");
|
|
3362
3464
|
if (isObject(parsed.execution)) {
|
|
@@ -3843,6 +3945,182 @@ function validateDefaultTest(defaultTest, filePath, errors, customAssertionTypes
|
|
|
3843
3945
|
});
|
|
3844
3946
|
}
|
|
3845
3947
|
}
|
|
3948
|
+
async function validateScenarios(scenarios, parsed, filePath, errors, customAssertionTypes) {
|
|
3949
|
+
if (scenarios === void 0) {
|
|
3950
|
+
return;
|
|
3951
|
+
}
|
|
3952
|
+
if (!Array.isArray(scenarios)) {
|
|
3953
|
+
errors.push({
|
|
3954
|
+
severity: "error",
|
|
3955
|
+
filePath,
|
|
3956
|
+
location: "scenarios",
|
|
3957
|
+
message: "Invalid 'scenarios' field (must be an array)"
|
|
3958
|
+
});
|
|
3959
|
+
return;
|
|
3960
|
+
}
|
|
3961
|
+
for (let scenarioIndex = 0; scenarioIndex < scenarios.length; scenarioIndex++) {
|
|
3962
|
+
const scenario = scenarios[scenarioIndex];
|
|
3963
|
+
const scenarioLocation = `scenarios[${scenarioIndex}]`;
|
|
3964
|
+
if (!isObject(scenario)) {
|
|
3965
|
+
errors.push({
|
|
3966
|
+
severity: "error",
|
|
3967
|
+
filePath,
|
|
3968
|
+
location: scenarioLocation,
|
|
3969
|
+
message: "Scenario must be an object"
|
|
3970
|
+
});
|
|
3971
|
+
continue;
|
|
3972
|
+
}
|
|
3973
|
+
for (const key of Object.keys(scenario)) {
|
|
3974
|
+
if (!KNOWN_SCENARIO_FIELDS.has(key)) {
|
|
3975
|
+
errors.push({
|
|
3976
|
+
severity: "error",
|
|
3977
|
+
filePath,
|
|
3978
|
+
location: `${scenarioLocation}.${key}`,
|
|
3979
|
+
message: `Unknown scenario field '${key}'.`
|
|
3980
|
+
});
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3983
|
+
if (!Array.isArray(scenario.config)) {
|
|
3984
|
+
errors.push({
|
|
3985
|
+
severity: "error",
|
|
3986
|
+
filePath,
|
|
3987
|
+
location: `${scenarioLocation}.config`,
|
|
3988
|
+
message: "Invalid 'config' field (must be an array)"
|
|
3989
|
+
});
|
|
3990
|
+
} else {
|
|
3991
|
+
for (let configIndex = 0; configIndex < scenario.config.length; configIndex++) {
|
|
3992
|
+
await validateScenarioTestLikeRow(
|
|
3993
|
+
scenario.config[configIndex],
|
|
3994
|
+
`${scenarioLocation}.config[${configIndex}]`,
|
|
3995
|
+
filePath,
|
|
3996
|
+
errors,
|
|
3997
|
+
customAssertionTypes,
|
|
3998
|
+
{ requireInput: false }
|
|
3999
|
+
);
|
|
4000
|
+
}
|
|
4001
|
+
}
|
|
4002
|
+
const scenarioConfigs = Array.isArray(scenario.config) ? scenario.config : [];
|
|
4003
|
+
if (!Array.isArray(scenario.tests)) {
|
|
4004
|
+
errors.push({
|
|
4005
|
+
severity: "error",
|
|
4006
|
+
filePath,
|
|
4007
|
+
location: `${scenarioLocation}.tests`,
|
|
4008
|
+
message: "Invalid 'tests' field (must be an array)"
|
|
4009
|
+
});
|
|
4010
|
+
continue;
|
|
4011
|
+
}
|
|
4012
|
+
for (let testIndex = 0; testIndex < scenario.tests.length; testIndex++) {
|
|
4013
|
+
const test = scenario.tests[testIndex];
|
|
4014
|
+
const everyConfigProvidesInput = scenarioConfigs.length > 0 && scenarioConfigs.every(
|
|
4015
|
+
(config) => isObject(config) && (config.prompts !== void 0 || config.provider_output !== void 0)
|
|
4016
|
+
);
|
|
4017
|
+
const requireInput = isObject(test) && parsed.prompts === void 0 && test.prompts === void 0 && test.provider_output === void 0 && !everyConfigProvidesInput;
|
|
4018
|
+
await validateScenarioTestLikeRow(
|
|
4019
|
+
test,
|
|
4020
|
+
`${scenarioLocation}.tests[${testIndex}]`,
|
|
4021
|
+
filePath,
|
|
4022
|
+
errors,
|
|
4023
|
+
customAssertionTypes,
|
|
4024
|
+
{ requireInput }
|
|
4025
|
+
);
|
|
4026
|
+
}
|
|
4027
|
+
}
|
|
4028
|
+
}
|
|
4029
|
+
async function validateScenarioTestLikeRow(row, location, filePath, errors, customAssertionTypes, options) {
|
|
4030
|
+
if (!isObject(row)) {
|
|
4031
|
+
errors.push({
|
|
4032
|
+
severity: "error",
|
|
4033
|
+
filePath,
|
|
4034
|
+
location,
|
|
4035
|
+
message: "Scenario row must be an object"
|
|
4036
|
+
});
|
|
4037
|
+
return;
|
|
4038
|
+
}
|
|
4039
|
+
for (const key of Object.keys(row)) {
|
|
4040
|
+
const removedMessage = REMOVED_TEST_FIELDS.get(key);
|
|
4041
|
+
if (removedMessage) {
|
|
4042
|
+
errors.push({
|
|
4043
|
+
severity: "error",
|
|
4044
|
+
filePath,
|
|
4045
|
+
location: `${location}.${key}`,
|
|
4046
|
+
message: removedMessage.replaceAll("tests[]", location)
|
|
4047
|
+
});
|
|
4048
|
+
continue;
|
|
4049
|
+
}
|
|
4050
|
+
const deprecationMessage = DEPRECATED_TEST_FIELDS.get(key);
|
|
4051
|
+
if (deprecationMessage) {
|
|
4052
|
+
errors.push({
|
|
4053
|
+
severity: "warning",
|
|
4054
|
+
filePath,
|
|
4055
|
+
location: `${location}.${key}`,
|
|
4056
|
+
message: deprecationMessage
|
|
4057
|
+
});
|
|
4058
|
+
} else if (!KNOWN_TEST_FIELDS.has(key)) {
|
|
4059
|
+
errors.push({
|
|
4060
|
+
severity: "error",
|
|
4061
|
+
filePath,
|
|
4062
|
+
location: `${location}.${key}`,
|
|
4063
|
+
message: `Unknown test field '${key}'.`
|
|
4064
|
+
});
|
|
4065
|
+
}
|
|
4066
|
+
}
|
|
4067
|
+
const id = row.id;
|
|
4068
|
+
if (id !== void 0 && (typeof id !== "string" || id.trim().length === 0)) {
|
|
4069
|
+
errors.push({
|
|
4070
|
+
severity: "error",
|
|
4071
|
+
filePath,
|
|
4072
|
+
location: `${location}.id`,
|
|
4073
|
+
message: "Invalid 'id' field (must be a non-empty string when provided)"
|
|
4074
|
+
});
|
|
4075
|
+
}
|
|
4076
|
+
const criteria = row.criteria;
|
|
4077
|
+
if (criteria !== void 0 && (typeof criteria !== "string" || criteria.trim().length === 0)) {
|
|
4078
|
+
errors.push({
|
|
4079
|
+
severity: "error",
|
|
4080
|
+
filePath,
|
|
4081
|
+
location: `${location}.criteria`,
|
|
4082
|
+
message: "Invalid 'criteria' field (must be a non-empty string if provided)"
|
|
4083
|
+
});
|
|
4084
|
+
} else if (criteria !== void 0 && row.assert !== void 0) {
|
|
4085
|
+
errors.push({
|
|
4086
|
+
severity: "error",
|
|
4087
|
+
filePath,
|
|
4088
|
+
location: `${location}.criteria`,
|
|
4089
|
+
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: ... }."
|
|
4090
|
+
});
|
|
4091
|
+
}
|
|
4092
|
+
validateInputField(row.input, `${location}.input`, filePath, errors, {
|
|
4093
|
+
required: options.requireInput
|
|
4094
|
+
});
|
|
4095
|
+
if (row.expected_output !== void 0) {
|
|
4096
|
+
errors.push({
|
|
4097
|
+
severity: "error",
|
|
4098
|
+
filePath,
|
|
4099
|
+
location: `${location}.expected_output`,
|
|
4100
|
+
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 }}' }."
|
|
4101
|
+
});
|
|
4102
|
+
}
|
|
4103
|
+
validateAssertArray(row.assert, `${location}.assert`, filePath, errors, customAssertionTypes);
|
|
4104
|
+
validateRunOverride(row.run, `${location}.run`, filePath, errors);
|
|
4105
|
+
validateTestOptions(row.options, `${location}.options`, filePath, errors);
|
|
4106
|
+
await validateEnvironmentConfig(row.environment, filePath, errors, `${location}.environment`);
|
|
4107
|
+
validateConversationMode(row, location, filePath, errors);
|
|
4108
|
+
await validateWorkspaceConfig(row.workspace, filePath, errors, `${location}.workspace`);
|
|
4109
|
+
const caseExecution = isObject(row.execution) ? row.execution : void 0;
|
|
4110
|
+
if (caseExecution) {
|
|
4111
|
+
validateTestExecutionFields(caseExecution, filePath, errors, location);
|
|
4112
|
+
rejectRuntimeWorkspaceConfig(
|
|
4113
|
+
caseExecution.workspace,
|
|
4114
|
+
filePath,
|
|
4115
|
+
errors,
|
|
4116
|
+
`${location}.execution.workspace`
|
|
4117
|
+
);
|
|
4118
|
+
}
|
|
4119
|
+
const targets = row.providers !== void 0 ? row.providers : row.provider;
|
|
4120
|
+
if (targets !== void 0) {
|
|
4121
|
+
validateTargetTestbedFields(targets, `${location}.providers`, filePath, errors);
|
|
4122
|
+
}
|
|
4123
|
+
}
|
|
3846
4124
|
function validateEvaluateOptions(evaluateOptions, location, filePath, errors) {
|
|
3847
4125
|
if (evaluateOptions === void 0) {
|
|
3848
4126
|
return;
|
|
@@ -4611,6 +4889,16 @@ function validateAssertArray(assertField, location, filePath, errors, customAsse
|
|
|
4611
4889
|
continue;
|
|
4612
4890
|
}
|
|
4613
4891
|
const typeValue = rawTypeValue.replace(/_/g, "-");
|
|
4892
|
+
const staleMessage = staleAuthoredAssertionMessage(item);
|
|
4893
|
+
if (staleMessage) {
|
|
4894
|
+
errors.push({
|
|
4895
|
+
severity: "error",
|
|
4896
|
+
filePath,
|
|
4897
|
+
location: `${itemLocation}.type`,
|
|
4898
|
+
message: staleMessage
|
|
4899
|
+
});
|
|
4900
|
+
continue;
|
|
4901
|
+
}
|
|
4614
4902
|
const replacement = REMOVED_ASSERTION_TYPE_REPLACEMENTS.get(typeValue);
|
|
4615
4903
|
if (replacement) {
|
|
4616
4904
|
errors.push({
|
|
@@ -4631,7 +4919,7 @@ function validateAssertArray(assertField, location, filePath, errors, customAsse
|
|
|
4631
4919
|
});
|
|
4632
4920
|
continue;
|
|
4633
4921
|
}
|
|
4634
|
-
if (!isGraderKind(typeValue) && !PROMPTFOO_ASSERTION_TYPES.has(typeValue) && !customAssertionTypes.has(typeValue)) {
|
|
4922
|
+
if (!isGraderKind(typeValue) && !isGraderKind(baseTypeValue) && !PROMPTFOO_ASSERTION_TYPES.has(typeValue) && !customAssertionTypes.has(typeValue)) {
|
|
4635
4923
|
errors.push({
|
|
4636
4924
|
severity: "warning",
|
|
4637
4925
|
filePath,
|
|
@@ -5154,6 +5442,7 @@ function validateUnknownSettings(target, provider, absolutePath, location, error
|
|
|
5154
5442
|
"env",
|
|
5155
5443
|
"grader_target",
|
|
5156
5444
|
"judge_target",
|
|
5445
|
+
"use_target",
|
|
5157
5446
|
"workers",
|
|
5158
5447
|
"$schema",
|
|
5159
5448
|
"targets"
|
|
@@ -5436,15 +5725,22 @@ async function validateTargetsFile(filePath) {
|
|
|
5436
5725
|
const provider = effectiveTarget.provider;
|
|
5437
5726
|
const rawTarget = rawTargets[i];
|
|
5438
5727
|
const rawUseTarget = isObject3(rawTarget) ? rawTarget.use_target : void 0;
|
|
5439
|
-
|
|
5728
|
+
if (effectiveTarget.use_target !== void 0 || rawUseTarget !== void 0) {
|
|
5729
|
+
errors.push({
|
|
5730
|
+
severity: "error",
|
|
5731
|
+
filePath: absolutePath,
|
|
5732
|
+
location: `${location}.use_target`,
|
|
5733
|
+
message: "The 'use_target' field has been removed from authored targets.yaml target definitions. Define a concrete target with 'provider' instead."
|
|
5734
|
+
});
|
|
5735
|
+
}
|
|
5440
5736
|
const providerValue = typeof provider === "string" ? provider.trim().toLowerCase() : void 0;
|
|
5441
5737
|
const isTemplated = isEnvTemplated(provider);
|
|
5442
|
-
if (
|
|
5738
|
+
if (typeof provider !== "string" || provider.trim().length === 0) {
|
|
5443
5739
|
errors.push({
|
|
5444
5740
|
severity: "error",
|
|
5445
5741
|
filePath: absolutePath,
|
|
5446
5742
|
location: `${location}.provider`,
|
|
5447
|
-
message: "Missing or invalid 'provider' field (must be a non-empty string
|
|
5743
|
+
message: "Missing or invalid 'provider' field (must be a non-empty string)"
|
|
5448
5744
|
});
|
|
5449
5745
|
} else if (!isTemplated && (providerValue === "claude" || providerValue === "copilot")) {
|
|
5450
5746
|
errors.push({
|
|
@@ -5579,6 +5875,9 @@ async function validateConfigFile(filePath, options = {}) {
|
|
|
5579
5875
|
validateRefsConfig(errors, filePath, config.refs);
|
|
5580
5876
|
validateComposableGraph(errors, filePath, config);
|
|
5581
5877
|
validateDashboardConfig(errors, filePath, config.dashboard);
|
|
5878
|
+
validateHooksConfig(errors, filePath, config.hooks);
|
|
5879
|
+
validateEnvPathConfig(errors, filePath, config.env_path);
|
|
5880
|
+
validateEnvFromConfig(errors, filePath, config.env_from);
|
|
5582
5881
|
const projects = config.projects;
|
|
5583
5882
|
if (projects !== void 0) {
|
|
5584
5883
|
if (scope === "project") {
|
|
@@ -5613,7 +5912,10 @@ async function validateConfigFile(filePath, options = {}) {
|
|
|
5613
5912
|
"defaults",
|
|
5614
5913
|
"projects",
|
|
5615
5914
|
"dashboard",
|
|
5616
|
-
"studio"
|
|
5915
|
+
"studio",
|
|
5916
|
+
"hooks",
|
|
5917
|
+
"env_path",
|
|
5918
|
+
"env_from"
|
|
5617
5919
|
]);
|
|
5618
5920
|
const unexpectedFields = Object.keys(config).filter((key) => !allowedFields.has(key));
|
|
5619
5921
|
if (unexpectedFields.length > 0) {
|
|
@@ -5662,6 +5964,76 @@ function validateDashboardConfig(errors, filePath, rawDashboard) {
|
|
|
5662
5964
|
);
|
|
5663
5965
|
}
|
|
5664
5966
|
}
|
|
5967
|
+
var ENV_FROM_FORMATS = /* @__PURE__ */ new Set(["shell_exports", "json"]);
|
|
5968
|
+
function validateHooksConfig(errors, filePath, rawHooks) {
|
|
5969
|
+
if (rawHooks === void 0 || rawHooks === null) {
|
|
5970
|
+
return;
|
|
5971
|
+
}
|
|
5972
|
+
if (!isPlainObject(rawHooks)) {
|
|
5973
|
+
addError(errors, filePath, "hooks", "Field 'hooks' must be an object");
|
|
5974
|
+
return;
|
|
5975
|
+
}
|
|
5976
|
+
if (rawHooks.before_session !== void 0) {
|
|
5977
|
+
validateOptionalString(errors, filePath, rawHooks.before_session, "hooks.before_session");
|
|
5978
|
+
errors.push({
|
|
5979
|
+
severity: "warning",
|
|
5980
|
+
filePath,
|
|
5981
|
+
location: "hooks.before_session",
|
|
5982
|
+
message: "'hooks.before_session' is deprecated; use 'env_path' and/or 'env_from' to load environment variables before validation and eval."
|
|
5983
|
+
});
|
|
5984
|
+
}
|
|
5985
|
+
}
|
|
5986
|
+
function validateEnvPathConfig(errors, filePath, rawEnvPath) {
|
|
5987
|
+
if (rawEnvPath === void 0 || rawEnvPath === null) {
|
|
5988
|
+
return;
|
|
5989
|
+
}
|
|
5990
|
+
const isList = Array.isArray(rawEnvPath);
|
|
5991
|
+
const entries = isList ? rawEnvPath : [rawEnvPath];
|
|
5992
|
+
entries.forEach((entry, index) => {
|
|
5993
|
+
const location = isList ? `env_path[${index}]` : "env_path";
|
|
5994
|
+
if (typeof entry !== "string" || entry.trim().length === 0) {
|
|
5995
|
+
addError(errors, filePath, location, `Field '${location}' must be a non-empty string`);
|
|
5996
|
+
}
|
|
5997
|
+
});
|
|
5998
|
+
}
|
|
5999
|
+
function validateEnvFromConfig(errors, filePath, rawEnvFrom) {
|
|
6000
|
+
if (rawEnvFrom === void 0 || rawEnvFrom === null) {
|
|
6001
|
+
return;
|
|
6002
|
+
}
|
|
6003
|
+
const isList = Array.isArray(rawEnvFrom);
|
|
6004
|
+
const entries = isList ? rawEnvFrom : [rawEnvFrom];
|
|
6005
|
+
entries.forEach((entry, index) => {
|
|
6006
|
+
const location = isList ? `env_from[${index}]` : "env_from";
|
|
6007
|
+
if (!isPlainObject(entry)) {
|
|
6008
|
+
addError(errors, filePath, location, `Field '${location}' must be an object`);
|
|
6009
|
+
return;
|
|
6010
|
+
}
|
|
6011
|
+
const command = entry.command;
|
|
6012
|
+
if (typeof command === "string") {
|
|
6013
|
+
addError(
|
|
6014
|
+
errors,
|
|
6015
|
+
filePath,
|
|
6016
|
+
`${location}.command`,
|
|
6017
|
+
`Field '${location}.command' must be an argv array of strings, not a shell command string. Use e.g. ["bun", "scripts/load-secrets.ts"].`
|
|
6018
|
+
);
|
|
6019
|
+
} else if (!Array.isArray(command) || command.length === 0 || !command.every((part) => typeof part === "string" && part.length > 0)) {
|
|
6020
|
+
addError(
|
|
6021
|
+
errors,
|
|
6022
|
+
filePath,
|
|
6023
|
+
`${location}.command`,
|
|
6024
|
+
`Field '${location}.command' must be a non-empty array of strings`
|
|
6025
|
+
);
|
|
6026
|
+
}
|
|
6027
|
+
if (entry.format !== void 0 && !ENV_FROM_FORMATS.has(entry.format)) {
|
|
6028
|
+
addError(
|
|
6029
|
+
errors,
|
|
6030
|
+
filePath,
|
|
6031
|
+
`${location}.format`,
|
|
6032
|
+
`Field '${location}.format' must be "shell_exports" or "json"`
|
|
6033
|
+
);
|
|
6034
|
+
}
|
|
6035
|
+
});
|
|
6036
|
+
}
|
|
5665
6037
|
function validateRefsConfig(errors, filePath, rawRefs) {
|
|
5666
6038
|
if (rawRefs === void 0) {
|
|
5667
6039
|
return;
|
|
@@ -5874,13 +6246,7 @@ async function validateFileReferences(evalFilePath) {
|
|
|
5874
6246
|
if (!isObject4(parsed)) {
|
|
5875
6247
|
return errors;
|
|
5876
6248
|
}
|
|
5877
|
-
|
|
5878
|
-
if (cases === void 0 && "eval_cases" in parsed) {
|
|
5879
|
-
cases = parsed.eval_cases;
|
|
5880
|
-
}
|
|
5881
|
-
if (cases === void 0 && "evalcases" in parsed) {
|
|
5882
|
-
cases = parsed.evalcases;
|
|
5883
|
-
}
|
|
6249
|
+
const cases = parsed.tests;
|
|
5884
6250
|
if (!Array.isArray(cases)) {
|
|
5885
6251
|
return errors;
|
|
5886
6252
|
}
|
|
@@ -7527,7 +7893,7 @@ async function runEvalCommand(input) {
|
|
|
7527
7893
|
const resolvedExperiment = resolveExperimentForRun(options.experiment);
|
|
7528
7894
|
const evalPathInputs = input.testFiles.length > 0 ? [...input.testFiles] : [];
|
|
7529
7895
|
if (evalPathInputs.length === 0 && process.stdin.isTTY) {
|
|
7530
|
-
const { launchInteractiveWizard } = await import("./interactive-
|
|
7896
|
+
const { launchInteractiveWizard } = await import("./interactive-BN527UV3.js");
|
|
7531
7897
|
await launchInteractiveWizard();
|
|
7532
7898
|
return void 0;
|
|
7533
7899
|
}
|
|
@@ -7867,7 +8233,7 @@ async function runEvalCommand(input) {
|
|
|
7867
8233
|
});
|
|
7868
8234
|
let transcriptProviderFactory;
|
|
7869
8235
|
if (options.transcript) {
|
|
7870
|
-
const { TranscriptProvider } = await import("./dist-
|
|
8236
|
+
const { TranscriptProvider } = await import("./dist-NMXMI5SK.js");
|
|
7871
8237
|
const transcriptProvider = await TranscriptProvider.fromFile(options.transcript);
|
|
7872
8238
|
const totalTests = [...fileMetadata.values()].reduce(
|
|
7873
8239
|
(sum, meta) => sum + meta.testCases.length,
|
|
@@ -8133,7 +8499,7 @@ ${formatRequiredVersionFailureNote(requiredVersionCheck)}`);
|
|
|
8133
8499
|
const sourceTests = activeSourceTests;
|
|
8134
8500
|
const taskBundleTargets = buildTaskBundleTargetSelections(activeTestFiles, fileMetadata);
|
|
8135
8501
|
if (isResumeAppend) {
|
|
8136
|
-
const { writePerTestArtifacts } = await import("./artifact-writer-
|
|
8502
|
+
const { writePerTestArtifacts } = await import("./artifact-writer-7NBCOAYC.js");
|
|
8137
8503
|
await writePerTestArtifacts(allResults, runDir, {
|
|
8138
8504
|
experiment: normalizeExperimentName(options.experiment),
|
|
8139
8505
|
runId: path12.basename(runDir),
|
|
@@ -8313,6 +8679,7 @@ export {
|
|
|
8313
8679
|
loadEnvFromHierarchy,
|
|
8314
8680
|
detectFileType,
|
|
8315
8681
|
validateEvalFile,
|
|
8682
|
+
validateTypeScriptEvalConfigFile,
|
|
8316
8683
|
validateCasesFile,
|
|
8317
8684
|
validateTargetsFile,
|
|
8318
8685
|
validateConfigFile,
|
|
@@ -8351,4 +8718,4 @@ export {
|
|
|
8351
8718
|
filterByCategory,
|
|
8352
8719
|
runEvalCommand
|
|
8353
8720
|
};
|
|
8354
|
-
//# sourceMappingURL=chunk-
|
|
8721
|
+
//# sourceMappingURL=chunk-LKGARI3W.js.map
|