agentv 5.0.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 +239 -53
- package/dist/{agentv-provider-AYXH7WLW-NJRC6UQX.js → agentv-provider-AYXH7WLW-6YZKZ7PS.js} +2 -2
- package/dist/{artifact-writer-QD52FC56.js → artifact-writer-SN6UNL5G.js} +15 -8
- package/dist/{chunk-GZJMODLW.js → chunk-3S6A2RKR.js} +45880 -30542
- package/dist/chunk-3S6A2RKR.js.map +1 -0
- package/dist/{chunk-6Q56CEXV.js → chunk-3X357HS4.js} +7900 -8985
- package/dist/chunk-3X357HS4.js.map +1 -0
- package/dist/{chunk-6JVM4GJI.js → chunk-46K2OET3.js} +187 -80
- package/dist/chunk-46K2OET3.js.map +1 -0
- package/dist/{chunk-IJEZFZJR.js → chunk-7BGERE6L.js} +2 -2
- package/dist/chunk-7BGERE6L.js.map +1 -0
- package/dist/{chunk-UG4JHZYM.js → chunk-ALVZQUZP.js} +670 -1427
- package/dist/chunk-ALVZQUZP.js.map +1 -0
- package/dist/{chunk-RCIEHFQ2.js → chunk-PEUTJS7B.js} +3 -3
- package/dist/{chunk-5H446C7X.js → chunk-QMRVH5ZP.js} +2 -8
- package/dist/{chunk-IBI7A5RP.js → chunk-T4AD3H3Y.js} +3444 -2251
- package/dist/chunk-T4AD3H3Y.js.map +1 -0
- package/dist/cli.js +8 -9
- package/dist/cli.js.map +1 -1
- package/dist/dashboard/assets/{index-D5_8DE_B.js → index-DNgf3qJ2.js} +1 -1
- package/dist/dashboard/assets/index-D_bokML8.css +1 -0
- package/dist/dashboard/assets/index-r_jSJmlw.js +121 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/{dist-KJ6PELQY.js → dist-DEPJOMCA.js} +74 -60
- package/dist/{docker-workspace-ZJ2ESVBI-6UDETQII.js → docker-workspace-NNK4Z6FR-QRTIG6TM.js} +3 -3
- package/dist/{exec-MYPAJJP7-C5HD5WG5.js → exec-4HFFRQ3B-AXDMJNLJ.js} +3 -3
- package/dist/index.js +8 -9
- package/dist/{interactive-2WMVAASS.js → interactive-36ZNMQB2.js} +13 -29
- package/dist/interactive-36ZNMQB2.js.map +1 -0
- package/dist/skills/agentv-bench/SKILL.md +38 -34
- package/dist/skills/agentv-bench/agents/analyzer.md +6 -6
- package/dist/skills/agentv-bench/agents/comparator.md +4 -5
- package/dist/skills/agentv-bench/agents/grader.md +4 -4
- package/dist/skills/agentv-bench/references/autoresearch.md +3 -3
- package/dist/skills/agentv-bench/references/description-optimization.md +2 -2
- package/dist/skills/agentv-bench/references/environment-adaptation.md +10 -10
- package/dist/skills/agentv-bench/references/eval-yaml-spec.md +51 -30
- package/dist/skills/agentv-bench/references/migrating-from-skill-creator.md +4 -4
- package/dist/skills/agentv-bench/references/subagent-pipeline.md +13 -12
- package/dist/skills/agentv-eval-migrations/SKILL.md +33 -0
- package/dist/skills/agentv-eval-migrations/references/breaking-changes.md +1012 -0
- package/dist/skills/agentv-eval-review/SKILL.md +6 -3
- package/dist/skills/agentv-eval-review/scripts/lint_eval.py +1 -1
- package/dist/skills/agentv-eval-writer/SKILL.md +380 -246
- package/dist/skills/agentv-eval-writer/references/{config-schema.json → config.schema.json} +6 -5
- package/dist/skills/agentv-eval-writer/references/custom-evaluators.md +23 -18
- package/dist/skills/agentv-eval-writer/references/eval.schema.json +9852 -0
- package/dist/skills/agentv-eval-writer/references/python-helpers.md +8 -8
- package/dist/skills/agentv-eval-writer/references/rubric-evaluator.md +21 -22
- package/dist/skills/agentv-trace-analyst/SKILL.md +4 -4
- package/dist/templates/.agentv/targets.yaml +41 -40
- package/dist/{ts-eval-loader-RE43OAGX-AMRCUKBZ.js → ts-eval-loader-OMG2JBHP-OP5RR7A3.js} +5 -4
- package/package.json +19 -4
- package/dist/chunk-6JVM4GJI.js.map +0 -1
- package/dist/chunk-6Q56CEXV.js.map +0 -1
- package/dist/chunk-76FOHROU.js +0 -96
- package/dist/chunk-76FOHROU.js.map +0 -1
- package/dist/chunk-GZJMODLW.js.map +0 -1
- package/dist/chunk-HSHTTN6C.js +0 -565
- package/dist/chunk-HSHTTN6C.js.map +0 -1
- package/dist/chunk-IBI7A5RP.js.map +0 -1
- package/dist/chunk-IJEZFZJR.js.map +0 -1
- package/dist/chunk-LRULMAAA.js +0 -1711
- package/dist/chunk-LRULMAAA.js.map +0 -1
- package/dist/chunk-R3CXYNTN.js +0 -1238
- package/dist/chunk-R3CXYNTN.js.map +0 -1
- package/dist/chunk-UG4JHZYM.js.map +0 -1
- package/dist/chunk-VQ2ZO7XJ.js +0 -2098
- package/dist/chunk-VQ2ZO7XJ.js.map +0 -1
- package/dist/chunk-XALGXSKB.js +0 -21
- package/dist/chunk-XALGXSKB.js.map +0 -1
- package/dist/dashboard/assets/index-BVMrdN8a.js +0 -119
- package/dist/dashboard/assets/index-DZWXfWsv.css +0 -1
- package/dist/esm-NNMQYIKT.js +0 -32
- package/dist/esm-R77SNOF5.js +0 -65
- package/dist/esm-RVQPUGWH.js +0 -1207
- package/dist/esm-RVQPUGWH.js.map +0 -1
- package/dist/esm-TTEMJEVV.js +0 -933
- package/dist/esm-TTEMJEVV.js.map +0 -1
- package/dist/esm-ZADQ4XQH-QUFGGZL4.js +0 -924
- package/dist/esm-ZADQ4XQH-QUFGGZL4.js.map +0 -1
- package/dist/exec-MYPAJJP7-C5HD5WG5.js.map +0 -1
- package/dist/getMachineId-bsd-HSK5LZMG.js +0 -41
- package/dist/getMachineId-bsd-HSK5LZMG.js.map +0 -1
- package/dist/getMachineId-darwin-4DP6CCJV.js +0 -41
- package/dist/getMachineId-darwin-4DP6CCJV.js.map +0 -1
- package/dist/getMachineId-linux-44LJ5UJB.js +0 -33
- package/dist/getMachineId-linux-44LJ5UJB.js.map +0 -1
- package/dist/getMachineId-unsupported-NVK6IATM.js +0 -24
- package/dist/getMachineId-unsupported-NVK6IATM.js.map +0 -1
- package/dist/getMachineId-win-YZ36S7VA.js +0 -43
- package/dist/getMachineId-win-YZ36S7VA.js.map +0 -1
- package/dist/interactive-2WMVAASS.js.map +0 -1
- package/dist/otlp-json-file-exporter-RY63S3IG-PZBQPVYY.js +0 -9
- package/dist/otlp-json-file-exporter-RY63S3IG-PZBQPVYY.js.map +0 -1
- package/dist/skills/agentv-eval-writer/references/eval-schema.json +0 -17295
- package/dist/skills/agentv-eval-writer/references/experiment-schema.json +0 -278
- package/dist/src-76ISS3LH.js +0 -1733
- package/dist/src-76ISS3LH.js.map +0 -1
- package/dist/ts-eval-loader-RE43OAGX-AMRCUKBZ.js.map +0 -1
- /package/dist/{agentv-provider-AYXH7WLW-NJRC6UQX.js.map → agentv-provider-AYXH7WLW-6YZKZ7PS.js.map} +0 -0
- /package/dist/{artifact-writer-QD52FC56.js.map → artifact-writer-SN6UNL5G.js.map} +0 -0
- /package/dist/{chunk-RCIEHFQ2.js.map → chunk-PEUTJS7B.js.map} +0 -0
- /package/dist/{chunk-5H446C7X.js.map → chunk-QMRVH5ZP.js.map} +0 -0
- /package/dist/{dist-KJ6PELQY.js.map → dist-DEPJOMCA.js.map} +0 -0
- /package/dist/{docker-workspace-ZJ2ESVBI-6UDETQII.js.map → docker-workspace-NNK4Z6FR-QRTIG6TM.js.map} +0 -0
- /package/dist/{esm-NNMQYIKT.js.map → exec-4HFFRQ3B-AXDMJNLJ.js.map} +0 -0
- /package/dist/{esm-R77SNOF5.js.map → ts-eval-loader-OMG2JBHP-OP5RR7A3.js.map} +0 -0
|
@@ -6,20 +6,20 @@ import {
|
|
|
6
6
|
filterByCategory,
|
|
7
7
|
findRepoRoot,
|
|
8
8
|
getCategories,
|
|
9
|
+
resolveExistingRunPrimaryPath,
|
|
9
10
|
runEvalCommand
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-76FOHROU.js";
|
|
14
|
-
import "./chunk-RCIEHFQ2.js";
|
|
11
|
+
} from "./chunk-T4AD3H3Y.js";
|
|
12
|
+
import "./chunk-46K2OET3.js";
|
|
13
|
+
import "./chunk-ALVZQUZP.js";
|
|
15
14
|
import {
|
|
16
15
|
getAgentvConfigDir,
|
|
17
16
|
listTargetNames,
|
|
18
17
|
readTargetDefinitions
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
18
|
+
} from "./chunk-3S6A2RKR.js";
|
|
19
|
+
import "./chunk-7BGERE6L.js";
|
|
20
|
+
import "./chunk-PEUTJS7B.js";
|
|
21
21
|
import "./chunk-M7BUKBAF.js";
|
|
22
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-QMRVH5ZP.js";
|
|
23
23
|
|
|
24
24
|
// src/commands/eval/interactive.ts
|
|
25
25
|
import { existsSync } from "node:fs";
|
|
@@ -70,7 +70,6 @@ ${ANSI_DIM}Resuming run at ${relativeDir}...${ANSI_RESET}
|
|
|
70
70
|
evalPaths: lastConfig.evalPaths,
|
|
71
71
|
target: lastConfig.target,
|
|
72
72
|
workers: lastConfig.workers,
|
|
73
|
-
dryRun: lastConfig.dryRun,
|
|
74
73
|
cache: lastConfig.cache
|
|
75
74
|
},
|
|
76
75
|
{ resumeOutputDir: lastConfig.outputDir }
|
|
@@ -85,7 +84,6 @@ ${ANSI_DIM}Rerunning last configuration...${ANSI_RESET}
|
|
|
85
84
|
evalPaths: lastConfig.evalPaths,
|
|
86
85
|
target: lastConfig.target,
|
|
87
86
|
workers: lastConfig.workers,
|
|
88
|
-
dryRun: lastConfig.dryRun,
|
|
89
87
|
cache: lastConfig.cache
|
|
90
88
|
});
|
|
91
89
|
return;
|
|
@@ -103,8 +101,8 @@ ${ANSI_DIM}Rerunning last configuration...${ANSI_RESET}
|
|
|
103
101
|
async function promptMainMenu(lastConfig) {
|
|
104
102
|
const choices = [];
|
|
105
103
|
if (lastConfig?.outputDir) {
|
|
106
|
-
const indexPath =
|
|
107
|
-
if (existsSync(indexPath)) {
|
|
104
|
+
const indexPath = resolveExistingRunPrimaryPath(lastConfig.outputDir);
|
|
105
|
+
if (indexPath && existsSync(indexPath)) {
|
|
108
106
|
const dirLabel = path2.basename(lastConfig.outputDir);
|
|
109
107
|
choices.push({
|
|
110
108
|
name: "\u23EF Resume last run",
|
|
@@ -245,7 +243,7 @@ async function promptAdvancedOptions() {
|
|
|
245
243
|
default: false
|
|
246
244
|
});
|
|
247
245
|
if (!customize) {
|
|
248
|
-
return { workers: 3,
|
|
246
|
+
return { workers: 3, cache: false };
|
|
249
247
|
}
|
|
250
248
|
const workers = await number({
|
|
251
249
|
message: "Number of parallel workers (1-50)",
|
|
@@ -253,15 +251,11 @@ async function promptAdvancedOptions() {
|
|
|
253
251
|
min: 1,
|
|
254
252
|
max: 50
|
|
255
253
|
}) ?? 3;
|
|
256
|
-
const dryRun = await confirm({
|
|
257
|
-
message: "Enable dry-run mode (mock responses)?",
|
|
258
|
-
default: false
|
|
259
|
-
});
|
|
260
254
|
const cache = await confirm({
|
|
261
255
|
message: "Enable response cache?",
|
|
262
256
|
default: false
|
|
263
257
|
});
|
|
264
|
-
return { workers,
|
|
258
|
+
return { workers, cache };
|
|
265
259
|
}
|
|
266
260
|
async function promptReviewAndConfirm(config, cwd) {
|
|
267
261
|
const evalDisplay = config.evalPaths.map((p) => {
|
|
@@ -275,7 +269,6 @@ ${ANSI_BOLD}Review Configuration${ANSI_RESET}`);
|
|
|
275
269
|
${evalDisplay}`);
|
|
276
270
|
console.log(`${ANSI_GREEN}Target:${ANSI_RESET} ${config.target}`);
|
|
277
271
|
console.log(`${ANSI_GREEN}Workers:${ANSI_RESET} ${config.workers}`);
|
|
278
|
-
console.log(`${ANSI_GREEN}Dry run:${ANSI_RESET} ${config.dryRun ? "yes" : "no"}`);
|
|
279
272
|
console.log(`${ANSI_GREEN}Cache:${ANSI_RESET} ${config.cache ? "yes" : "no"}`);
|
|
280
273
|
console.log(`${ANSI_DIM}${"\u2500".repeat(40)}${ANSI_RESET}`);
|
|
281
274
|
return confirm({
|
|
@@ -288,12 +281,8 @@ async function executeConfig(config, opts) {
|
|
|
288
281
|
const rawOptions = {
|
|
289
282
|
target: config.target,
|
|
290
283
|
workers: config.workers,
|
|
291
|
-
dryRun: config.dryRun,
|
|
292
284
|
cache: config.cache,
|
|
293
285
|
...opts?.resumeOutputDir ? { output: opts.resumeOutputDir, resume: true } : {},
|
|
294
|
-
dryRunDelay: 0,
|
|
295
|
-
dryRunDelayMin: 0,
|
|
296
|
-
dryRunDelayMax: 0,
|
|
297
286
|
agentTimeout: 120,
|
|
298
287
|
maxRetries: 2,
|
|
299
288
|
verbose: false,
|
|
@@ -312,7 +301,6 @@ async function executeConfig(config, opts) {
|
|
|
312
301
|
evalPaths: config.evalPaths,
|
|
313
302
|
target: config.target,
|
|
314
303
|
workers: config.workers,
|
|
315
|
-
dryRun: config.dryRun,
|
|
316
304
|
cache: config.cache,
|
|
317
305
|
outputDir: path2.dirname(result.outputPath)
|
|
318
306
|
});
|
|
@@ -335,13 +323,9 @@ ${ANSI_DIM}Retrying execution errors...${ANSI_RESET}
|
|
|
335
323
|
const rawOptions = {
|
|
336
324
|
target: config.target,
|
|
337
325
|
workers: config.workers,
|
|
338
|
-
dryRun: config.dryRun,
|
|
339
326
|
cache: config.cache,
|
|
340
327
|
retryErrors: outputPath,
|
|
341
328
|
out: outputPath,
|
|
342
|
-
dryRunDelay: 0,
|
|
343
|
-
dryRunDelayMin: 0,
|
|
344
|
-
dryRunDelayMax: 0,
|
|
345
329
|
agentTimeout: 120,
|
|
346
330
|
maxRetries: 2,
|
|
347
331
|
verbose: false,
|
|
@@ -360,4 +344,4 @@ ${ANSI_DIM}Retrying execution errors...${ANSI_RESET}
|
|
|
360
344
|
export {
|
|
361
345
|
launchInteractiveWizard
|
|
362
346
|
};
|
|
363
|
-
//# sourceMappingURL=interactive-
|
|
347
|
+
//# sourceMappingURL=interactive-36ZNMQB2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/eval/interactive.ts","../src/commands/eval/last-config.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { listTargetNames, readTargetDefinitions } from '@agentv/core';\nimport { checkbox, confirm, number, search, select } from '@inquirer/prompts';\n\nimport { TARGET_FILE_CANDIDATES, fileExists } from '../../utils/targets.js';\nimport {\n type DiscoveredEvalFile,\n discoverEvalFiles,\n filterByCategory,\n getCategories,\n} from './discover.js';\nimport { type LastConfig, loadLastConfig, saveLastConfig } from './last-config.js';\nimport { resolveExistingRunPrimaryPath } from './result-layout.js';\nimport { runEvalCommand } from './run-eval.js';\nimport { findRepoRoot } from './shared.js';\n\nconst ANSI_BOLD = '\\x1b[1m';\nconst ANSI_DIM = '\\x1b[2m';\nconst ANSI_CYAN = '\\x1b[36m';\nconst ANSI_GREEN = '\\x1b[32m';\nconst ANSI_RESET = '\\x1b[0m';\n\nexport interface InteractiveConfig {\n readonly evalPaths: readonly string[];\n readonly target: string;\n readonly workers: number;\n readonly cache: boolean;\n}\n\n/**\n * Launch the interactive wizard when `agentv eval` is called with no arguments.\n */\nexport async function launchInteractiveWizard(): Promise<void> {\n const cwd = process.cwd();\n\n console.log(`\\n${ANSI_BOLD}${ANSI_CYAN}AgentV Interactive Mode${ANSI_RESET}\\n`);\n\n const lastConfig = await loadLastConfig();\n const action = await promptMainMenu(lastConfig);\n\n if (action === 'exit') {\n return;\n }\n\n if (action === 'resume' && lastConfig?.outputDir) {\n const relativeDir = path.relative(cwd, lastConfig.outputDir) || lastConfig.outputDir;\n console.log(`\\n${ANSI_DIM}Resuming run at ${relativeDir}...${ANSI_RESET}\\n`);\n await executeConfig(\n {\n evalPaths: lastConfig.evalPaths,\n target: lastConfig.target,\n workers: lastConfig.workers,\n cache: lastConfig.cache,\n },\n { resumeOutputDir: lastConfig.outputDir },\n );\n return;\n }\n\n if (action === 'rerun' && lastConfig) {\n console.log(`\\n${ANSI_DIM}Rerunning last configuration...${ANSI_RESET}\\n`);\n await executeConfig({\n evalPaths: lastConfig.evalPaths,\n target: lastConfig.target,\n workers: lastConfig.workers,\n cache: lastConfig.cache,\n });\n return;\n }\n\n // Run new evaluation flow\n const config = await promptNewEvaluation(cwd);\n if (!config) {\n return;\n }\n\n // Review & confirm\n const confirmed = await promptReviewAndConfirm(config, cwd);\n if (!confirmed) {\n return;\n }\n\n await executeConfig(config);\n}\n\nasync function promptMainMenu(\n lastConfig: LastConfig | undefined,\n): Promise<'new' | 'rerun' | 'resume' | 'exit'> {\n type MenuChoice = 'new' | 'rerun' | 'resume' | 'exit';\n const choices: Array<{ name: string; value: MenuChoice; description?: string }> = [];\n\n // Resume entry: only when the prior run has a known artifact dir with a manifest.\n if (lastConfig?.outputDir) {\n const indexPath = resolveExistingRunPrimaryPath(lastConfig.outputDir);\n if (indexPath && existsSync(indexPath)) {\n const dirLabel = path.basename(lastConfig.outputDir);\n choices.push({\n name: '⏯ Resume last run',\n value: 'resume',\n description: `${dirLabel} (target: ${lastConfig.target})`,\n });\n }\n }\n\n if (lastConfig) {\n const evalCount = lastConfig.evalPaths.length;\n choices.push({\n name: '🔄 Rerun last config',\n value: 'rerun',\n description: `${evalCount} eval file(s), target: ${lastConfig.target}`,\n });\n }\n\n choices.push({ name: '🚀 Run new evaluation', value: 'new' }, { name: '✕ Exit', value: 'exit' });\n\n return select<MenuChoice>({\n message: 'What would you like to do?',\n choices,\n });\n}\n\nasync function promptNewEvaluation(cwd: string): Promise<InteractiveConfig | undefined> {\n // Step 1: Discover eval files\n console.log(`\\n${ANSI_DIM}Scanning for eval files...${ANSI_RESET}`);\n const allFiles = await discoverEvalFiles(cwd);\n\n if (allFiles.length === 0) {\n console.log(\n '\\n⚠ No eval files found in the current directory.\\n' +\n ' Place .yaml or .jsonl eval files in your project, or use:\\n' +\n ' agentv eval <path-to-eval.yaml>\\n',\n );\n return undefined;\n }\n\n console.log(`${ANSI_DIM}Found ${allFiles.length} eval file(s)${ANSI_RESET}\\n`);\n\n // Step 2: Select eval files (optionally filter by category first)\n const selectedFiles = await promptEvalSelection(allFiles);\n if (selectedFiles.length === 0) {\n console.log('\\nNo eval files selected.');\n return undefined;\n }\n\n // Step 3: Select target\n const target = await promptTargetSelection(cwd, selectedFiles[0].path);\n\n // Step 4: Advanced options\n const advanced = await promptAdvancedOptions();\n\n return {\n evalPaths: selectedFiles.map((f) => f.path),\n target,\n ...advanced,\n };\n}\n\nasync function promptEvalSelection(\n allFiles: readonly DiscoveredEvalFile[],\n): Promise<DiscoveredEvalFile[]> {\n const categories = getCategories(allFiles);\n\n // If only one category or few files, skip category selection\n let filesToSelect: readonly DiscoveredEvalFile[];\n\n if (categories.length > 1) {\n const selectedCategory = await search<string>({\n message: 'Select a category (type to search)',\n source: async (term) => {\n const filtered = term\n ? categories.filter((c) => c.toLowerCase().includes(term.toLowerCase()))\n : categories;\n return [\n { name: '(all categories)', value: '__all__' },\n ...filtered.map((c) => {\n const count = filterByCategory(allFiles, c).length;\n return { name: `${c} (${count} file${count > 1 ? 's' : ''})`, value: c };\n }),\n ];\n },\n });\n\n filesToSelect =\n selectedCategory === '__all__' ? allFiles : filterByCategory(allFiles, selectedCategory);\n } else {\n filesToSelect = allFiles;\n }\n\n return checkbox<DiscoveredEvalFile>({\n message: 'Select eval files to run (space to toggle, enter to confirm)',\n choices: filesToSelect.map((f) => ({\n name: f.relativePath,\n value: f,\n checked: filesToSelect.length <= 5, // auto-select if few files\n })),\n required: true,\n });\n}\n\nasync function promptTargetSelection(cwd: string, firstEvalPath: string): Promise<string> {\n const repoRoot = await findRepoRoot(cwd);\n\n // Try to find targets.yaml — search near the eval file first, then cwd/repoRoot\n const targetsPath = await findTargetsFile(cwd, repoRoot, firstEvalPath);\n\n if (!targetsPath) {\n console.log(`${ANSI_DIM}No targets.yaml found. Using default target.${ANSI_RESET}`);\n return 'default';\n }\n\n const definitions = await readTargetDefinitions(targetsPath);\n const targetNames = listTargetNames(definitions);\n\n if (targetNames.length === 0) {\n return 'default';\n }\n\n if (targetNames.length === 1) {\n console.log(`${ANSI_DIM}Using target: ${targetNames[0]}${ANSI_RESET}`);\n return targetNames[0];\n }\n\n return search<string>({\n message: 'Select a target (type to search)',\n source: async (term) => {\n const filtered = term\n ? targetNames.filter((t) => t.toLowerCase().includes(term.toLowerCase()))\n : targetNames;\n return filtered.map((t) => {\n const def = definitions.find((d) => d.name === t);\n return {\n name: t,\n value: t,\n description: def ? `provider: ${def.provider}` : undefined,\n };\n });\n },\n });\n}\n\nasync function findTargetsFile(\n cwd: string,\n repoRoot: string,\n evalFilePath?: string,\n): Promise<string | undefined> {\n // Build directory chain: eval file dir → cwd → repoRoot (mirrors discoverTargetsFile)\n const dirsToSearch: string[] = [];\n\n if (evalFilePath) {\n const evalDir = path.dirname(evalFilePath);\n if (!dirsToSearch.includes(evalDir)) {\n dirsToSearch.push(evalDir);\n }\n }\n\n if (!dirsToSearch.includes(cwd)) {\n dirsToSearch.push(cwd);\n }\n\n if (repoRoot !== cwd && !dirsToSearch.includes(repoRoot)) {\n dirsToSearch.push(repoRoot);\n }\n\n for (const dir of dirsToSearch) {\n for (const candidate of TARGET_FILE_CANDIDATES) {\n const fullPath = `${dir}/${candidate}`;\n if (await fileExists(fullPath)) {\n return fullPath;\n }\n }\n }\n\n return undefined;\n}\n\nasync function promptAdvancedOptions(): Promise<{\n workers: number;\n cache: boolean;\n}> {\n const customize = await confirm({\n message: 'Configure advanced options?',\n default: false,\n });\n\n if (!customize) {\n return { workers: 3, cache: false };\n }\n\n const workers =\n (await number({\n message: 'Number of parallel workers (1-50)',\n default: 3,\n min: 1,\n max: 50,\n })) ?? 3;\n\n const cache = await confirm({\n message: 'Enable response cache?',\n default: false,\n });\n\n return { workers, cache };\n}\n\nasync function promptReviewAndConfirm(config: InteractiveConfig, cwd: string): Promise<boolean> {\n const evalDisplay = config.evalPaths\n .map((p) => {\n const rel = p.startsWith(cwd) ? p.slice(cwd.length + 1) : p;\n return ` ${rel}`;\n })\n .join('\\n');\n\n console.log(`\\n${ANSI_BOLD}Review Configuration${ANSI_RESET}`);\n console.log(`${ANSI_DIM}${'─'.repeat(40)}${ANSI_RESET}`);\n console.log(`${ANSI_GREEN}Eval files:${ANSI_RESET}\\n${evalDisplay}`);\n console.log(`${ANSI_GREEN}Target:${ANSI_RESET} ${config.target}`);\n console.log(`${ANSI_GREEN}Workers:${ANSI_RESET} ${config.workers}`);\n console.log(`${ANSI_GREEN}Cache:${ANSI_RESET} ${config.cache ? 'yes' : 'no'}`);\n console.log(`${ANSI_DIM}${'─'.repeat(40)}${ANSI_RESET}`);\n\n return confirm({\n message: 'Run evaluation with this configuration?',\n default: true,\n });\n}\n\nasync function executeConfig(\n config: InteractiveConfig,\n opts?: { resumeOutputDir?: string },\n): Promise<void> {\n const cwd = process.cwd();\n const rawOptions: Record<string, unknown> = {\n target: config.target,\n workers: config.workers,\n cache: config.cache,\n ...(opts?.resumeOutputDir ? { output: opts.resumeOutputDir, resume: true } : {}),\n agentTimeout: 120,\n maxRetries: 2,\n verbose: false,\n keepWorkspaces: false,\n cleanupWorkspaces: false,\n trace: false,\n };\n\n const result = await runEvalCommand({\n testFiles: [...config.evalPaths],\n rawOptions,\n });\n\n // Persist config with the resolved artifact dir so the wizard can offer\n // \"Resume last run\" on the next invocation. Done after a successful run so\n // the saved outputDir always points at a real run manifest.\n if (result) {\n await saveLastConfig({\n timestamp: new Date().toISOString(),\n cwd,\n evalPaths: config.evalPaths,\n target: config.target,\n workers: config.workers,\n cache: config.cache,\n outputDir: path.dirname(result.outputPath),\n });\n }\n\n // Prompt to retry errors when execution errors were detected in a TTY\n if (result && result.executionErrorCount > 0 && process.stdin.isTTY) {\n await promptRetryErrors(config, result.outputPath);\n }\n}\n\nasync function promptRetryErrors(config: InteractiveConfig, outputPath: string): Promise<void> {\n const shouldRetry = await confirm({\n message: `Retry ${ANSI_BOLD}execution errors${ANSI_RESET} from this run?`,\n default: true,\n });\n\n if (!shouldRetry) {\n return;\n }\n\n console.log(`\\n${ANSI_DIM}Retrying execution errors...${ANSI_RESET}\\n`);\n\n const rawOptions: Record<string, unknown> = {\n target: config.target,\n workers: config.workers,\n cache: config.cache,\n retryErrors: outputPath,\n out: outputPath,\n agentTimeout: 120,\n maxRetries: 2,\n verbose: false,\n keepWorkspaces: false,\n cleanupWorkspaces: false,\n trace: false,\n };\n\n const retryResult = await runEvalCommand({\n testFiles: [...config.evalPaths],\n rawOptions,\n });\n\n // Allow chained retries if there are still errors\n if (retryResult && retryResult.executionErrorCount > 0 && process.stdin.isTTY) {\n await promptRetryErrors(config, retryResult.outputPath);\n }\n}\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { getAgentvConfigDir } from '@agentv/core';\n\nconst CONFIG_DIR = getAgentvConfigDir();\nconst LAST_CONFIG_PATH = path.join(CONFIG_DIR, 'last-config.json');\n\nexport interface LastConfig {\n readonly timestamp: string;\n readonly cwd: string;\n readonly evalPaths: readonly string[];\n readonly target: string;\n readonly workers: number;\n readonly cache: boolean;\n /**\n * Resolved artifact directory of the last completed wizard run. Used to\n * power the wizard's \"Resume last run\" entry. Optional for backward\n * compatibility with configs saved before this field existed.\n */\n readonly outputDir?: string;\n}\n\nexport async function loadLastConfig(): Promise<LastConfig | undefined> {\n try {\n const content = await readFile(LAST_CONFIG_PATH, 'utf-8');\n return JSON.parse(content) as LastConfig;\n } catch {\n return undefined;\n }\n}\n\nexport async function saveLastConfig(config: LastConfig): Promise<void> {\n await mkdir(CONFIG_DIR, { recursive: true });\n await writeFile(LAST_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf-8');\n}\n"],"mappings":"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","names":["path","path"]}
|
|
@@ -65,24 +65,28 @@ Before running or optimizing, understand what you're working with.
|
|
|
65
65
|
|
|
66
66
|
AgentV supports two evaluation formats:
|
|
67
67
|
|
|
68
|
-
**EVAL.yaml** (native, full features) — supports
|
|
68
|
+
**EVAL.yaml** (native, full features) — supports environment recipes, script graders, multi-turn conversations, tool trajectory scoring, workspace file tracking, and multi-provider targets. Use this for agent evaluation.
|
|
69
69
|
|
|
70
70
|
```yaml
|
|
71
71
|
# example.eval.yaml
|
|
72
|
+
prompts:
|
|
73
|
+
- "{{ task }}"
|
|
74
|
+
|
|
75
|
+
environment:
|
|
76
|
+
type: host
|
|
77
|
+
workdir: ./workspace-template
|
|
78
|
+
setup:
|
|
79
|
+
command: ["bash", "-lc", "bun install && bun run build"]
|
|
80
|
+
cwd: "."
|
|
81
|
+
|
|
72
82
|
tests:
|
|
73
83
|
- id: basic-code-review
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
84
|
+
vars:
|
|
85
|
+
task: "Review this TypeScript file for bugs and suggest improvements"
|
|
86
|
+
assert:
|
|
77
87
|
- type: contains
|
|
78
88
|
value: "null"
|
|
79
89
|
- Review identifies the null pointer bug and suggests a concrete fix
|
|
80
|
-
|
|
81
|
-
workspace:
|
|
82
|
-
template: ./workspace-template
|
|
83
|
-
hooks:
|
|
84
|
-
before_each:
|
|
85
|
-
reset: fast
|
|
86
90
|
```
|
|
87
91
|
|
|
88
92
|
Multi-skill evaluation is handled naturally via input messages — describe the task in the test input, and the agent uses whatever skills it needs.
|
|
@@ -113,9 +117,9 @@ Start with 2-3 realistic test cases — the kind of thing a real user would actu
|
|
|
113
117
|
|
|
114
118
|
Good assertions are objectively verifiable and have descriptive names. Subjective quality ("the output is good") is better evaluated qualitatively — don't force assertions onto things that need human judgment.
|
|
115
119
|
|
|
116
|
-
**Grader types** (cheapest to most expensive): `exact`, `contains`, `regex`, `is-json`, `field-accuracy`, `
|
|
120
|
+
**Grader types** (cheapest to most expensive): `exact`, `contains`, `regex`, `is-json`, `field-accuracy`, `assert-set`, `script`, `tool-trajectory`, `llm-rubric`. See `references/eval-yaml-spec.md` for full config and grading recipes for each type.
|
|
117
121
|
|
|
118
|
-
Prefer deterministic graders over LLM graders whenever possible. If an assertion can be checked with `contains` or `regex`, don't use `llm-
|
|
122
|
+
Prefer deterministic graders over LLM graders whenever possible. If an assertion can be checked with `contains` or `regex`, don't use `llm-rubric`.
|
|
119
123
|
|
|
120
124
|
---
|
|
121
125
|
|
|
@@ -129,24 +133,24 @@ Each run produces a new `.agentv/results/default/<timestamp>/` directory automat
|
|
|
129
133
|
|
|
130
134
|
**User instruction takes priority.** If the user says "run in subagent mode", "use subagent mode", or "use CLI mode", use that mode directly.
|
|
131
135
|
|
|
132
|
-
If the user has not specified a mode, default to
|
|
136
|
+
If the user has not specified a mode, default to AgentV CLI mode.
|
|
133
137
|
|
|
134
|
-
|
|
|
135
|
-
|
|
136
|
-
|
|
|
137
|
-
|
|
|
138
|
+
| Mode | When to use | How |
|
|
139
|
+
|------|-------------|-----|
|
|
140
|
+
| **AgentV CLI** (default) | Normal eval runs, multi-provider benchmarking, CI, artifact generation, and Dashboard-compatible results. | `agentv eval <path>` |
|
|
141
|
+
| **Subagent mode** | Explicit user request, no usable CLI/runtime, or rare provider/request-cost constraints. | Read `references/subagent-pipeline.md` first. |
|
|
138
142
|
|
|
139
|
-
|
|
143
|
+
Do not read `AGENT_EVAL_MODE` or another environment variable to decide the default mode. **User instruction always overrides the default.**
|
|
140
144
|
|
|
141
|
-
|
|
145
|
+
**Subagent mode** — Parses eval.yaml directly, spawns executor subagents to run each test case in the current workspace, then spawns grader subagents to evaluate assertion types natively. This is an opt-in fallback. Read `references/subagent-pipeline.md` for the detailed procedure before using it.
|
|
142
146
|
|
|
143
|
-
|
|
147
|
+
**AgentV CLI mode** — AgentV CLI handles execution, grading, and artifact generation end-to-end. Works with all providers. Use this unless the user explicitly asks for subagent mode or the CLI path is unavailable.
|
|
144
148
|
|
|
145
149
|
### Running evaluations
|
|
146
150
|
|
|
147
|
-
**AgentV CLI mode** (end-to-end, EVAL.yaml):
|
|
151
|
+
**AgentV CLI mode** (default, end-to-end, EVAL.yaml):
|
|
148
152
|
```bash
|
|
149
|
-
agentv eval <eval-path>
|
|
153
|
+
agentv eval <eval-path>
|
|
150
154
|
```
|
|
151
155
|
|
|
152
156
|
**Subagent mode** — read `references/subagent-pipeline.md` for the detailed procedure. In brief: use `pipeline input` to extract inputs, dispatch one `executor` subagent per test case (all in parallel), then proceed to grading below.
|
|
@@ -196,19 +200,19 @@ grading until all responses are present.
|
|
|
196
200
|
|
|
197
201
|
**In subagent mode**, grading has three phases. **All three are required — do not stop after phase 1.**
|
|
198
202
|
|
|
199
|
-
**Phase 1:
|
|
203
|
+
**Phase 1: script graders** (deterministic, zero-cost)
|
|
200
204
|
|
|
201
205
|
```bash
|
|
202
206
|
agentv pipeline grade <run-dir>
|
|
203
207
|
```
|
|
204
208
|
|
|
205
209
|
This evaluates all deterministic assertions against `response.md` files. Two types are handled:
|
|
206
|
-
- **`
|
|
210
|
+
- **`script-grader` scripts** — external scripts executed against the response (arbitrary logic, any language)
|
|
207
211
|
- **Built-in assertion types** — evaluated in-process: `contains`, `contains-any`, `contains-all`, `icontains`, `regex`, `equals`, `starts-with`, `ends-with`, `is-json`, and variants
|
|
208
212
|
|
|
209
|
-
Both types are configured by `pipeline input` into `
|
|
213
|
+
Both types are configured by `pipeline input` into `script_graders/<name>.json` and graded by `pipeline grade`. Results are written to `<test-id>/script_grader_results/<name>.json`. Alternatively, pass `--grader-type code` to `pipeline run` to run these inline.
|
|
210
214
|
|
|
211
|
-
**Do not dispatch LLM grader subagents for tests that only have `contains`, `regex`, or other built-in assertions** — `pipeline grade` handles them entirely, at zero cost. To detect which tests need Phase 2, check whether `<test-id>/llm_graders/` contains any `.json` config files — `pipeline input` only writes there for `llm-
|
|
215
|
+
**Do not dispatch LLM grader subagents for tests that only have `contains`, `regex`, or other built-in assertions** — `pipeline grade` handles them entirely, at zero cost. To detect which tests need Phase 2, check whether `<test-id>/llm_graders/` contains any `.json` config files — `pipeline input` only writes there for `llm-rubric` assertions. Tests with an empty (or missing) `llm_graders/` directory are done after Phase 1.
|
|
212
216
|
|
|
213
217
|
**Phase 2: LLM grading** (semantic — do NOT skip this phase)
|
|
214
218
|
|
|
@@ -242,7 +246,7 @@ agentv pipeline bench <run-dir>
|
|
|
242
246
|
agentv results validate <run-dir>
|
|
243
247
|
```
|
|
244
248
|
|
|
245
|
-
`pipeline bench` reads LLM grader results from `llm_grader_results/<name>.json` per test automatically, merges with
|
|
249
|
+
`pipeline bench` reads LLM grader results from `llm_grader_results/<name>.json` per test automatically, merges with script-grader scores, computes weighted pass_rate, and writes `grading.json` + `index.jsonl` + `summary.json`.
|
|
246
250
|
|
|
247
251
|
> **Diagnosing `pass_rate=0`:** If `pipeline bench` reports `pass_rate=0` across the board, do **not** assume the tests genuinely failed. First verify the grading pipeline ran correctly: check that `<test-id>/llm_grader_results/<name>.json` exists and is non-empty for each test. If these files are absent or empty, the grader subagents failed to produce output (most common cause: `agents/grader.md` was not embedded in the subagent prompts — see Phase 2). Treat `pass_rate=0` as a real signal only after confirming grader results exist.
|
|
248
252
|
|
|
@@ -255,11 +259,11 @@ All artifacts use established schemas — see `references/schemas.md` for the fu
|
|
|
255
259
|
|
|
256
260
|
Write artifacts to `.agentv/artifacts/` or the iteration directory.
|
|
257
261
|
|
|
258
|
-
###
|
|
262
|
+
### Environment features (EVAL.yaml only)
|
|
259
263
|
|
|
260
|
-
- **
|
|
261
|
-
- **
|
|
262
|
-
- **Multi-repo** —
|
|
264
|
+
- **Environment recipes** — prepare host or Docker testbeds with `type`, `workdir`, and argv-only `setup.command`
|
|
265
|
+
- **Static local override** — use `--workspace-path` only when an existing local directory should be reused as-is
|
|
266
|
+
- **Multi-repo** — materialize repos from setup scripts when a task needs several checkouts
|
|
263
267
|
- **File change tracking** — grade by diffing workspace files before/after agent execution
|
|
264
268
|
|
|
265
269
|
---
|
|
@@ -276,7 +280,7 @@ Read the JSONL results and look for:
|
|
|
276
280
|
- **Always-fail tests** — task impossible, eval broken, or assertion misconfigured. Don't optimize against broken evals.
|
|
277
281
|
- **Flaky tests** — non-deterministic results across runs. Investigate before treating failures as real.
|
|
278
282
|
- **Systematic failures** — same failure pattern across multiple tests. This usually points to a missing instruction or wrong approach.
|
|
279
|
-
- **Deterministic upgrade candidates** — `llm-
|
|
283
|
+
- **Deterministic upgrade candidates** — `llm-rubric` assertions that could be replaced with `contains`, `regex`, or `is-json` (cheaper, faster, more reliable).
|
|
280
284
|
|
|
281
285
|
### Dispatch subagents
|
|
282
286
|
|
|
@@ -289,7 +293,7 @@ Read the JSONL results and look for:
|
|
|
289
293
|
Use CLI tools for deeper investigation:
|
|
290
294
|
```bash
|
|
291
295
|
agentv inspect <results-file> # Detailed execution trace inspection
|
|
292
|
-
agentv compare <file-a> <file-b> # Structured diff between runs
|
|
296
|
+
agentv results compare <file-a> <file-b> # Structured diff between runs
|
|
293
297
|
```
|
|
294
298
|
|
|
295
299
|
Look for: tool call patterns, error recovery behavior, conversation flow, wasted steps.
|
|
@@ -360,7 +364,7 @@ After improving:
|
|
|
360
364
|
|
|
361
365
|
### Automated keep/discard
|
|
362
366
|
|
|
363
|
-
For autonomous iteration, use `agentv compare --json` to automatically decide whether to keep or discard each change based on wins/losses/ties. Read `references/autoresearch.md` for the full decision rules, logging format, and integration with the iteration loop.
|
|
367
|
+
For autonomous iteration, use `agentv results compare --json` to automatically decide whether to keep or discard each change based on wins/losses/ties. Read `references/autoresearch.md` for the full decision rules, logging format, and integration with the iteration loop.
|
|
364
368
|
|
|
365
369
|
---
|
|
366
370
|
|
|
@@ -28,7 +28,7 @@ If `eval-path` is provided, also read the EVAL.yaml to understand grader configu
|
|
|
28
28
|
|
|
29
29
|
### Step 2: Deterministic-Upgrade Analysis
|
|
30
30
|
|
|
31
|
-
For each grader entry in `scores` where `type` is `"llm-
|
|
31
|
+
For each grader entry in `scores` where `type` is `"llm-rubric"` or `"rubrics"`, inspect the `reasoning` and `assertions` fields for patterns that indicate a deterministic assertion would suffice:
|
|
32
32
|
|
|
33
33
|
| Signal | Detection | Suggested Upgrade |
|
|
34
34
|
|--------|-----------|-------------------|
|
|
@@ -48,7 +48,7 @@ For each grader entry in `scores` where `type` is `"llm-grader"` or `"rubrics"`,
|
|
|
48
48
|
|
|
49
49
|
### Step 3: Weak Assertion Detection
|
|
50
50
|
|
|
51
|
-
Scan the EVAL.yaml `
|
|
51
|
+
Scan the EVAL.yaml `assert` entries (if `eval-path` provided) and the `reasoning` fields in results for weak assertions:
|
|
52
52
|
|
|
53
53
|
| Weakness | Detection | Improvement |
|
|
54
54
|
|----------|-----------|-------------|
|
|
@@ -56,7 +56,7 @@ Scan the EVAL.yaml `assertions` entries (if `eval-path` provided) and the `reaso
|
|
|
56
56
|
| Tautological | Contains "is correct", "is good", "works properly", "is valid" without specifying what correct/good means | Define explicit pass/fail conditions |
|
|
57
57
|
| Compound criteria | Single assertion checks multiple independent things (uses "and", "also", "additionally" joining distinct checks) | Split into separate assertions, one per concern |
|
|
58
58
|
| Missing expected value | `type: equals` or `type: contains` without a `value` field | Add the expected value |
|
|
59
|
-
| Overly broad LLM-grader | LLM-grader with no rubric items, just a single vague `prompt` string | Convert to `type:
|
|
59
|
+
| Overly broad LLM-grader | LLM-grader with no rubric items, just a single vague `prompt` string | Convert to `type: llm-rubric` with enumerated criteria, or use deterministic checks |
|
|
60
60
|
|
|
61
61
|
### Step 4: Cost/Quality Signals
|
|
62
62
|
|
|
@@ -94,7 +94,7 @@ Produce a structured report in this exact format:
|
|
|
94
94
|
|
|
95
95
|
| # | Test ID | Grader | Current Type | Evidence | Suggested Type | Suggested Config |
|
|
96
96
|
|---|---------|-----------|-------------|----------|----------------|-----------------|
|
|
97
|
-
| 1 | <test_id> | <grader name> | llm-
|
|
97
|
+
| 1 | <test_id> | <grader name> | llm-rubric | <brief evidence> | contains | `value: "exact string"` |
|
|
98
98
|
|
|
99
99
|
### Weak Assertions
|
|
100
100
|
|
|
@@ -122,8 +122,8 @@ If a section has no findings, include the header with "None found." underneath.
|
|
|
122
122
|
|
|
123
123
|
- **Be specific:** Every suggestion must include the test case ID, grader name, evidence from the results, and a concrete replacement config.
|
|
124
124
|
- **Be conservative:** Only suggest deterministic upgrades when the pattern is clear and consistent. Partial or ambiguous evidence should be noted but not acted on.
|
|
125
|
-
- **Prioritize by impact:** Order suggestions by estimated cost savings (`llm-
|
|
126
|
-
- **Handle all grader types:** Process `
|
|
125
|
+
- **Prioritize by impact:** Order suggestions by estimated cost savings (`llm-rubric` → deterministic saves the most).
|
|
126
|
+
- **Handle all grader types:** Process `script`, `tool-trajectory`, `llm-rubric`, `rubrics`, `assert-set`, and all deterministic types. Only LLM-based types are candidates for deterministic upgrades.
|
|
127
127
|
- **Multi-provider awareness:** When results span multiple targets, note if a suggestion applies to all targets or is target-specific.
|
|
128
128
|
- **No false positives:** It is better to miss a suggestion than to recommend an incorrect upgrade. If unsure, add the finding to a "Needs Review" subsection with your reasoning.
|
|
129
129
|
|
|
@@ -24,8 +24,7 @@ You are the Blind Comparator for AgentV's evaluation workflow. Your job is to co
|
|
|
24
24
|
You will receive:
|
|
25
25
|
- `outputs`: Array of evaluation outputs to compare. Each contains:
|
|
26
26
|
- `target_id`: The provider/configuration identifier (DO NOT read this during scoring)
|
|
27
|
-
- `
|
|
28
|
-
- `evaluator_results`: Array of grader scores and details (code-grader, tool-trajectory, llm-grader, deterministic)
|
|
27
|
+
- `evaluator_results`: Array of grader scores and details (script, tool-trajectory, llm-rubric, deterministic)
|
|
29
28
|
- `workspace_changes`: File changes made during workspace evaluation (if applicable)
|
|
30
29
|
- `tool_calls`: Tool invocations and results from multi-turn conversations (if applicable)
|
|
31
30
|
- `conversation`: Full multi-turn conversation history (if applicable)
|
|
@@ -91,9 +90,9 @@ For each content criterion, define:
|
|
|
91
90
|
|
|
92
91
|
**Grader-Specific Scoring** — when grader results are present:
|
|
93
92
|
|
|
94
|
-
- **
|
|
93
|
+
- **script-grader**: Factor in pass/fail results, test coverage, assertion hit rates
|
|
95
94
|
- **tool-trajectory**: Factor in tool call accuracy, sequence correctness, unnecessary tool calls
|
|
96
|
-
- **llm-
|
|
95
|
+
- **llm-rubric**: Factor in existing LLM grader scores as a reference signal (not as ground truth)
|
|
97
96
|
- **deterministic**: Factor in exact match / keyword hit rates
|
|
98
97
|
|
|
99
98
|
### Phase 3: Scoring
|
|
@@ -236,7 +235,7 @@ Also produce a human-readable markdown summary:
|
|
|
236
235
|
- **Be evidence-based**: Every score must cite specific evidence from the output.
|
|
237
236
|
- **Evaluate substance over style**: Correct, complete answers with rough formatting score higher than polished but incorrect answers.
|
|
238
237
|
- **Handle missing data gracefully**: If an output lacks workspace changes or tool calls but others have them, score what is present — do not penalize for data the target wasn't expected to produce.
|
|
239
|
-
- **Respect grader signals**: When
|
|
238
|
+
- **Respect grader signals**: When script-grader or tool-trajectory results exist, they represent objective ground truth. Weight these heavily.
|
|
240
239
|
|
|
241
240
|
## Edge Cases
|
|
242
241
|
|
|
@@ -3,7 +3,7 @@ name: grader
|
|
|
3
3
|
description: >-
|
|
4
4
|
Grade a candidate response for an AgentV evaluation test case. Evaluates all
|
|
5
5
|
assertion types natively — deterministic checks via string operations, LLM grading
|
|
6
|
-
via Claude's own reasoning,
|
|
6
|
+
via Claude's own reasoning, script-grader via Bash script execution. Zero CLI dependency.
|
|
7
7
|
Dispatch this agent after a candidate completes a test case.
|
|
8
8
|
model: inherit
|
|
9
9
|
color: yellow
|
|
@@ -12,7 +12,7 @@ tools: ["Read", "Bash", "Glob", "Grep", "Write"]
|
|
|
12
12
|
|
|
13
13
|
You are the grader for an AgentV evaluation test case. You have two jobs: **grade the outputs** and **critique the evals themselves**. A passing grade on a weak assertion is worse than useless — it creates false confidence. When you notice an assertion that's trivially satisfied, or an important outcome that no assertion checks, say so.
|
|
14
14
|
|
|
15
|
-
**For deterministic assertions, write and run a script rather than eyeballing it.** Scripts are faster, more reliable, and can be reused. Use LLM reasoning only for assertions that genuinely require semantic understanding (`llm-
|
|
15
|
+
**For deterministic assertions, write and run a script rather than eyeballing it.** Scripts are faster, more reliable, and can be reused. Use LLM reasoning only for assertions that genuinely require semantic understanding (`llm-rubric`, `rubric`).
|
|
16
16
|
|
|
17
17
|
**You will receive these parameters:**
|
|
18
18
|
- `eval-path`: Path to the eval YAML file
|
|
@@ -63,7 +63,7 @@ For each assertion in the test's `assertions[]`, evaluate it natively based on i
|
|
|
63
63
|
|
|
64
64
|
| Type | How to evaluate |
|
|
65
65
|
|------|----------------|
|
|
66
|
-
| `llm-
|
|
66
|
+
| `llm-rubric` | Read `value` for free-form criteria, `rubrics` for itemized criteria, or `prompt_content`/`prompt` for a custom grading prompt. Evaluate the response against those criteria. Score 0.0-1.0 with evidence. |
|
|
67
67
|
| `rubric` / `rubrics` | Read rubric items/criteria. Score each item 0.0-1.0. Aggregate as weighted average. |
|
|
68
68
|
|
|
69
69
|
For LLM-graded types: be rigorous and fair. Score based on substance, not exact wording. If a `criteria` field exists on the test case, use it as additional context for your evaluation. If `expected_output` exists, use it as a reference answer (not as the only correct answer).
|
|
@@ -72,7 +72,7 @@ For LLM-graded types: be rigorous and fair. Score based on substance, not exact
|
|
|
72
72
|
|
|
73
73
|
| Type | How to evaluate |
|
|
74
74
|
|------|----------------|
|
|
75
|
-
| `
|
|
75
|
+
| `script-grader` | Run: `bun <script-path>` or `python <script-path>`. Pass response via file. Parse stdout JSON: `{"score": N, "reason": "..."}` |
|
|
76
76
|
|
|
77
77
|
**Composite assertions** — evaluate sub-assertions, then aggregate per the configured mode (weighted_average, min, max, all_pass).
|
|
78
78
|
|
|
@@ -11,7 +11,7 @@ After each iteration, you can automatically decide whether to keep or discard th
|
|
|
11
11
|
After re-running test cases, compare the new results against the previous iteration's baseline:
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
agentv compare <baseline>.jsonl <candidate>.jsonl --json
|
|
14
|
+
agentv results compare <baseline>.jsonl <candidate>.jsonl --json
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Where `<baseline>.jsonl` is the `index.jsonl` from the previous best iteration and `<candidate>.jsonl` is the `index.jsonl` from the run you just completed.
|
|
@@ -75,7 +75,7 @@ The automated keep/discard replaces the manual compare-and-present cycle (steps
|
|
|
75
75
|
|
|
76
76
|
1. Apply change to prompts/skills/config
|
|
77
77
|
2. Re-run all test cases
|
|
78
|
-
3. Run `agentv compare baseline.jsonl candidate.jsonl --json`
|
|
78
|
+
3. Run `agentv results compare baseline.jsonl candidate.jsonl --json`
|
|
79
79
|
4. Apply keep/discard rules → promote or revert
|
|
80
80
|
5. Log the decision
|
|
81
81
|
6. If this is iteration 3, 6, or 9 → present progress to the user (human checkpoint)
|
|
@@ -244,7 +244,7 @@ The trajectory chart fetches `iterations.jsonl` directly via HTTP on each auto-r
|
|
|
244
244
|
|
|
245
245
|
Apply the automated keep/discard rules from the section above:
|
|
246
246
|
|
|
247
|
-
1. Run `agentv compare <baseline>.jsonl <candidate>.jsonl --json` where `<baseline>` is the best iteration's `index.jsonl` (or the first run's `index.jsonl` for cycle 1) and `<candidate>` is this cycle's `index.jsonl`.
|
|
247
|
+
1. Run `agentv results compare <baseline>.jsonl <candidate>.jsonl --json` where `<baseline>` is the best iteration's `index.jsonl` (or the first run's `index.jsonl` for cycle 1) and `<candidate>` is this cycle's `index.jsonl`.
|
|
248
248
|
2. If `wins > losses` → **KEEP**.
|
|
249
249
|
3. If `wins <= losses` → **DISCARD**.
|
|
250
250
|
4. If `mean_delta == 0` and the artifact is simpler → **KEEP** (simpler is better at equal performance). Simplicity: for files, compare line count; for directories, compare total size via `du -sb`.
|
|
@@ -35,12 +35,12 @@ it's a natural utterance):
|
|
|
35
35
|
tests:
|
|
36
36
|
- id: should-trigger-casual-optimize
|
|
37
37
|
input: "ok so I have this agent that keeps failing on the code review tasks, can you help me figure out why and fix it"
|
|
38
|
-
|
|
38
|
+
assert:
|
|
39
39
|
- type: skill-trigger
|
|
40
40
|
skill: agentv-bench
|
|
41
41
|
- id: should-not-trigger-build-error
|
|
42
42
|
input: "my TypeScript build is failing with type errors in src/auth.ts"
|
|
43
|
-
|
|
43
|
+
assert:
|
|
44
44
|
- type: skill-trigger
|
|
45
45
|
skill: agentv-bench
|
|
46
46
|
should_trigger: false
|
|
@@ -29,28 +29,28 @@ to any platform with skill-discovery mechanisms. All listed providers support sk
|
|
|
29
29
|
## Unsupported Providers: Use a Code-Grader
|
|
30
30
|
|
|
31
31
|
The built-in `skill-trigger` grader covers Claude, Copilot, Pi, Codex and VS Code out
|
|
32
|
-
of the box. For providers with different tool-call formats, write a
|
|
32
|
+
of the box. For providers with different tool-call formats, write a script-grader that inspects
|
|
33
33
|
the agent's transcript messages or tool call trace.
|
|
34
34
|
|
|
35
|
-
A
|
|
35
|
+
A script-grader receives the full evaluation context including the final `output` string,
|
|
36
36
|
transcript `messages`, and structured `trace`. Inspect `messages` or `trace.events` for
|
|
37
37
|
tool calls; reserve `output` for final-answer text checks.
|
|
38
38
|
|
|
39
39
|
```yaml
|
|
40
|
-
# Example:
|
|
40
|
+
# Example: script-grader for Codex skill-trigger detection
|
|
41
41
|
tests:
|
|
42
42
|
- id: should-trigger-codex
|
|
43
43
|
input: "Analyze this CSV file"
|
|
44
|
-
|
|
45
|
-
- type:
|
|
44
|
+
assert:
|
|
45
|
+
- type: script
|
|
46
46
|
command: [bun, run, ./judges/codex-skill-trigger.ts]
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
```typescript
|
|
50
50
|
// judges/codex-skill-trigger.ts
|
|
51
|
-
import {
|
|
51
|
+
import { defineScriptGrader } from '@agentv/sdk';
|
|
52
52
|
|
|
53
|
-
export default
|
|
53
|
+
export default defineScriptGrader(({ messages }) => {
|
|
54
54
|
const skillName = 'csv-analyzer';
|
|
55
55
|
const toolCalls = messages.flatMap((msg) => msg.toolCalls ?? []);
|
|
56
56
|
const firstTool = toolCalls[0];
|
|
@@ -65,7 +65,7 @@ export default defineCodeGrader(({ messages }) => {
|
|
|
65
65
|
if (cmd.includes(skillName)) {
|
|
66
66
|
return {
|
|
67
67
|
score: 1,
|
|
68
|
-
|
|
68
|
+
assert: [
|
|
69
69
|
{ text: `Skill "${skillName}" triggered via command`, passed: true, evidence: cmd },
|
|
70
70
|
],
|
|
71
71
|
};
|
|
@@ -78,14 +78,14 @@ export default defineCodeGrader(({ messages }) => {
|
|
|
78
78
|
if (path.includes(skillName)) {
|
|
79
79
|
return {
|
|
80
80
|
score: 1,
|
|
81
|
-
|
|
81
|
+
assert: [{ text: 'Skill file accessed', passed: true, evidence: path }],
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
return {
|
|
87
87
|
score: 0,
|
|
88
|
-
|
|
88
|
+
assert: [
|
|
89
89
|
{
|
|
90
90
|
text: `First tool was not a skill invocation for "${skillName}"`,
|
|
91
91
|
passed: false,
|