agentv 4.44.0-next.1 → 5.0.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 +2 -2
- package/dist/{artifact-writer-72MQQELS.js → artifact-writer-QD52FC56.js} +12 -10
- package/dist/{chunk-KAGZRUO6.js → chunk-6JVM4GJI.js} +3 -2
- package/dist/chunk-6JVM4GJI.js.map +1 -0
- package/dist/{chunk-2N3YSEMI.js → chunk-6Q56CEXV.js} +333 -99
- package/dist/chunk-6Q56CEXV.js.map +1 -0
- package/dist/{chunk-5DYGN547.js → chunk-GZJMODLW.js} +1008 -663
- package/dist/chunk-GZJMODLW.js.map +1 -0
- package/dist/{chunk-CXHYTYHU.js → chunk-IBI7A5RP.js} +621 -191
- package/dist/chunk-IBI7A5RP.js.map +1 -0
- package/dist/{chunk-NPVGBFF6.js → chunk-IJEZFZJR.js} +2 -43
- package/dist/chunk-IJEZFZJR.js.map +1 -0
- package/dist/{chunk-BPGJ4HBU.js → chunk-RCIEHFQ2.js} +3 -3
- package/dist/{chunk-NCNDA3F6.js → chunk-UG4JHZYM.js} +1176 -224
- package/dist/chunk-UG4JHZYM.js.map +1 -0
- package/dist/cli.js +7 -7
- package/dist/dashboard/assets/index-BVMrdN8a.js +119 -0
- package/dist/dashboard/assets/{index-DitffAxS.js → index-D5_8DE_B.js} +1 -1
- package/dist/dashboard/assets/index-DZWXfWsv.css +1 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/{dist-L4YCQOQ6.js → dist-KJ6PELQY.js} +45 -11
- package/dist/{docker-workspace-RPPXBT27-B4AQHVWA.js → docker-workspace-ZJ2ESVBI-6UDETQII.js} +2 -2
- package/dist/{exec-AR6JUUN5-6MBPURPR.js → exec-MYPAJJP7-C5HD5WG5.js} +2 -2
- package/dist/index.js +7 -7
- package/dist/{interactive-DRNRKLEQ.js → interactive-2WMVAASS.js} +7 -7
- package/dist/skills/agentv-bench/SKILL.md +3 -3
- package/dist/skills/agentv-bench/agents/analyzer.md +1 -1
- package/dist/skills/agentv-bench/references/autoresearch.md +1 -1
- package/dist/skills/agentv-bench/references/eval-yaml-spec.md +13 -3
- package/dist/skills/agentv-bench/references/migrating-from-skill-creator.md +2 -2
- package/dist/skills/agentv-bench/references/schemas.md +6 -6
- package/dist/skills/agentv-bench/references/subagent-pipeline.md +1 -1
- package/dist/skills/agentv-eval-writer/SKILL.md +10 -0
- package/dist/skills/agentv-eval-writer/references/eval-schema.json +3 -63
- package/dist/skills/agentv-eval-writer/references/experiment-schema.json +278 -0
- package/dist/{ts-eval-loader-S7ESROX2-6CB3HB6H.js → ts-eval-loader-RE43OAGX-AMRCUKBZ.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-2N3YSEMI.js.map +0 -1
- package/dist/chunk-5DYGN547.js.map +0 -1
- package/dist/chunk-CXHYTYHU.js.map +0 -1
- package/dist/chunk-KAGZRUO6.js.map +0 -1
- package/dist/chunk-NCNDA3F6.js.map +0 -1
- package/dist/chunk-NPVGBFF6.js.map +0 -1
- package/dist/dashboard/assets/index-1Hvy8sBy.js +0 -119
- package/dist/dashboard/assets/index-J5sPcQO3.css +0 -1
- /package/dist/{artifact-writer-72MQQELS.js.map → artifact-writer-QD52FC56.js.map} +0 -0
- /package/dist/{chunk-BPGJ4HBU.js.map → chunk-RCIEHFQ2.js.map} +0 -0
- /package/dist/{dist-L4YCQOQ6.js.map → dist-KJ6PELQY.js.map} +0 -0
- /package/dist/{docker-workspace-RPPXBT27-B4AQHVWA.js.map → docker-workspace-ZJ2ESVBI-6UDETQII.js.map} +0 -0
- /package/dist/{exec-AR6JUUN5-6MBPURPR.js.map → exec-MYPAJJP7-C5HD5WG5.js.map} +0 -0
- /package/dist/{interactive-DRNRKLEQ.js.map → interactive-2WMVAASS.js.map} +0 -0
- /package/dist/{ts-eval-loader-S7ESROX2-6CB3HB6H.js.map → ts-eval-loader-RE43OAGX-AMRCUKBZ.js.map} +0 -0
|
@@ -2,16 +2,21 @@ import { createRequire } from 'node:module'; const require = createRequire(impor
|
|
|
2
2
|
import {
|
|
3
3
|
toSnakeCaseDeep as toSnakeCaseDeep2,
|
|
4
4
|
writeArtifactsFromResults
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-6JVM4GJI.js";
|
|
6
6
|
import {
|
|
7
7
|
RunBudgetTracker,
|
|
8
|
+
buildExperimentArtifactMetadata,
|
|
8
9
|
buildWipBranchName,
|
|
10
|
+
confirmResultsMergeAndPull,
|
|
9
11
|
deleteWipBranch,
|
|
10
12
|
deriveCategory,
|
|
13
|
+
deriveExperimentNameFromPath,
|
|
11
14
|
directPushResultsWithDetails,
|
|
12
15
|
directorySizeBytes,
|
|
13
16
|
getResultsRepoSyncStatus,
|
|
17
|
+
isExperimentFileReference,
|
|
14
18
|
listGitRuns,
|
|
19
|
+
loadExperimentConfig,
|
|
15
20
|
loadTsConfig,
|
|
16
21
|
materializeGitRun,
|
|
17
22
|
normalizeResultsConfig,
|
|
@@ -19,8 +24,10 @@ import {
|
|
|
19
24
|
resolveResultsRepoRunsDir,
|
|
20
25
|
setupWipWorktree,
|
|
21
26
|
syncResultsRepoForProject
|
|
22
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-UG4JHZYM.js";
|
|
23
28
|
import {
|
|
29
|
+
AGENTV_LOCAL_CONFIG_FILE_NAME,
|
|
30
|
+
AGENTV_LOCAL_CONFIG_YML_FILE_NAME,
|
|
24
31
|
CLI_PLACEHOLDERS,
|
|
25
32
|
COMMON_TARGET_SETTINGS,
|
|
26
33
|
DEFAULT_EVAL_PATTERNS,
|
|
@@ -32,27 +39,33 @@ import {
|
|
|
32
39
|
aggregateRunDir,
|
|
33
40
|
buildDirectoryChain,
|
|
34
41
|
buildSearchRoots,
|
|
42
|
+
buildSearchRoots2,
|
|
35
43
|
buildTestTargetKey,
|
|
36
44
|
buildTraceFromMessages,
|
|
37
45
|
deduplicateByTestIdTarget,
|
|
38
46
|
ensureVSCodeSubagents,
|
|
47
|
+
external_exports,
|
|
39
48
|
findDeprecatedCamelCaseTargetWarnings,
|
|
40
49
|
findGitRoot,
|
|
41
50
|
getAgentvConfigDir,
|
|
51
|
+
getLocalConfigPath,
|
|
42
52
|
getProject,
|
|
43
53
|
getProjectForPath,
|
|
44
54
|
interpolateEnv,
|
|
55
|
+
isAgentVConfigFileName,
|
|
45
56
|
isGraderKind,
|
|
46
57
|
listTargetNames,
|
|
47
58
|
loadCasesFromDirectory,
|
|
48
59
|
loadCasesFromFile,
|
|
49
60
|
loadConfig,
|
|
61
|
+
loadPromptMdFallback,
|
|
50
62
|
loadTestSuite,
|
|
51
63
|
normalizeResultRow,
|
|
52
64
|
parseJsonlResults,
|
|
53
65
|
parseYamlValue,
|
|
54
66
|
readTargetDefinitions,
|
|
55
67
|
readTestSuiteMetadata,
|
|
68
|
+
resolveDefaultExperimentReference,
|
|
56
69
|
resolveFileReference,
|
|
57
70
|
resolveResultsConfigForProject,
|
|
58
71
|
resolveTargetDefinition,
|
|
@@ -66,8 +79,8 @@ import {
|
|
|
66
79
|
toCamelCaseDeep,
|
|
67
80
|
toSnakeCaseDeep,
|
|
68
81
|
traceFromTranscriptJsonLines,
|
|
69
|
-
|
|
70
|
-
} from "./chunk-
|
|
82
|
+
writeInitialRunSummaryArtifact
|
|
83
|
+
} from "./chunk-GZJMODLW.js";
|
|
71
84
|
|
|
72
85
|
// src/commands/eval/shared.ts
|
|
73
86
|
import { constants } from "node:fs";
|
|
@@ -183,7 +196,7 @@ async function findRepoRoot(start) {
|
|
|
183
196
|
// package.json
|
|
184
197
|
var package_default = {
|
|
185
198
|
name: "agentv",
|
|
186
|
-
version: "
|
|
199
|
+
version: "5.0.0-next.1",
|
|
187
200
|
description: "CLI entry point for AgentV",
|
|
188
201
|
type: "module",
|
|
189
202
|
repository: {
|
|
@@ -291,10 +304,49 @@ async function discoverTargetsFile(options) {
|
|
|
291
304
|
throw new Error("Unable to locate targets.yaml. Use --targets to specify the file explicitly.");
|
|
292
305
|
}
|
|
293
306
|
|
|
307
|
+
// src/commands/eval/discover.ts
|
|
308
|
+
import path3 from "node:path";
|
|
309
|
+
import fg2 from "fast-glob";
|
|
310
|
+
async function discoverEvalFiles(cwd) {
|
|
311
|
+
const repoRoot = await findRepoRoot(cwd);
|
|
312
|
+
const config = await loadConfig(path3.join(cwd, "_"), repoRoot);
|
|
313
|
+
const patterns = config?.eval_patterns && config.eval_patterns.length > 0 ? config.eval_patterns : DEFAULT_EVAL_PATTERNS;
|
|
314
|
+
const ignore = ["**/node_modules/**", "**/dist/**"];
|
|
315
|
+
const matches = await fg2(patterns, {
|
|
316
|
+
cwd,
|
|
317
|
+
absolute: true,
|
|
318
|
+
onlyFiles: true,
|
|
319
|
+
ignore,
|
|
320
|
+
followSymbolicLinks: true,
|
|
321
|
+
caseSensitiveMatch: false
|
|
322
|
+
});
|
|
323
|
+
const evalFiles = matches.map((absPath) => {
|
|
324
|
+
const relativePath = path3.relative(cwd, absPath);
|
|
325
|
+
const category = deriveCategory(relativePath);
|
|
326
|
+
return { path: absPath, relativePath, category };
|
|
327
|
+
});
|
|
328
|
+
evalFiles.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
329
|
+
return evalFiles;
|
|
330
|
+
}
|
|
331
|
+
function getCategories(files) {
|
|
332
|
+
const categories = /* @__PURE__ */ new Set();
|
|
333
|
+
for (const file of files) {
|
|
334
|
+
categories.add(file.category);
|
|
335
|
+
}
|
|
336
|
+
const sorted = Array.from(categories);
|
|
337
|
+
sorted.sort();
|
|
338
|
+
return sorted;
|
|
339
|
+
}
|
|
340
|
+
function filterByCategory(files, category) {
|
|
341
|
+
return files.filter((f) => f.category === category);
|
|
342
|
+
}
|
|
343
|
+
|
|
294
344
|
// src/commands/eval/run-eval.ts
|
|
345
|
+
import { spawn } from "node:child_process";
|
|
295
346
|
import { constants as constants4, existsSync as existsSync7, mkdirSync as mkdirSync2 } from "node:fs";
|
|
296
347
|
import { access as access6, readFile as readFile8 } from "node:fs/promises";
|
|
297
|
-
import
|
|
348
|
+
import { createRequire as createNodeRequire } from "node:module";
|
|
349
|
+
import path15 from "node:path";
|
|
298
350
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
299
351
|
|
|
300
352
|
// src/version-check.ts
|
|
@@ -350,11 +402,11 @@ function enforceRequiredVersion(requiredVersion, options) {
|
|
|
350
402
|
|
|
351
403
|
// src/commands/results/remote.ts
|
|
352
404
|
import { existsSync as existsSync5 } from "node:fs";
|
|
353
|
-
import
|
|
405
|
+
import path9 from "node:path";
|
|
354
406
|
|
|
355
407
|
// src/commands/eval/result-layout.ts
|
|
356
408
|
import { existsSync, statSync } from "node:fs";
|
|
357
|
-
import
|
|
409
|
+
import path4 from "node:path";
|
|
358
410
|
var RESULT_INDEX_FILENAME = "index.jsonl";
|
|
359
411
|
var RESULTS_DIRNAME = "results";
|
|
360
412
|
var DEFAULT_EXPERIMENT_NAME = "default";
|
|
@@ -385,19 +437,19 @@ function defaultRunPathSegments(experiment, runDirName) {
|
|
|
385
437
|
return [normalizedExperiment, runDirName];
|
|
386
438
|
}
|
|
387
439
|
function buildResultsRootDir(cwd) {
|
|
388
|
-
return
|
|
440
|
+
return path4.join(cwd, ".agentv", RESULTS_DIRNAME);
|
|
389
441
|
}
|
|
390
442
|
function buildDefaultRunDirFromName(cwd, experiment, runDirName) {
|
|
391
|
-
return
|
|
443
|
+
return path4.join(buildResultsRootDir(cwd), ...defaultRunPathSegments(experiment, runDirName));
|
|
392
444
|
}
|
|
393
445
|
function buildDefaultRunDir(cwd, experiment, timestamp = /* @__PURE__ */ new Date()) {
|
|
394
446
|
return buildDefaultRunDirFromName(cwd, experiment, createRunDirName(timestamp));
|
|
395
447
|
}
|
|
396
448
|
function resolveRunIndexPath(runDir) {
|
|
397
|
-
return
|
|
449
|
+
return path4.join(runDir, RESULT_INDEX_FILENAME);
|
|
398
450
|
}
|
|
399
451
|
function isRunManifestPath(filePath) {
|
|
400
|
-
return
|
|
452
|
+
return path4.basename(filePath) === RESULT_INDEX_FILENAME;
|
|
401
453
|
}
|
|
402
454
|
function resolveExistingRunPrimaryPath(runDir) {
|
|
403
455
|
const indexPath = resolveRunIndexPath(runDir);
|
|
@@ -435,24 +487,24 @@ function resolveRunManifestPath(filePath) {
|
|
|
435
487
|
return filePath;
|
|
436
488
|
}
|
|
437
489
|
function relativeRunPathFromCwd(cwd, runDir) {
|
|
438
|
-
const relative =
|
|
439
|
-
if (!relative || relative.startsWith("..") ||
|
|
490
|
+
const relative = path4.relative(path4.resolve(buildResultsRootDir(cwd)), path4.resolve(runDir));
|
|
491
|
+
if (!relative || relative.startsWith("..") || path4.isAbsolute(relative)) {
|
|
440
492
|
return void 0;
|
|
441
493
|
}
|
|
442
|
-
const parts = relative.split(
|
|
494
|
+
const parts = relative.split(path4.sep).filter(Boolean);
|
|
443
495
|
if (parts.length < 2 || isReservedResultsNamespace(parts[0])) {
|
|
444
496
|
return void 0;
|
|
445
497
|
}
|
|
446
|
-
return parts.join(
|
|
498
|
+
return parts.join(path4.posix.sep);
|
|
447
499
|
}
|
|
448
500
|
|
|
449
501
|
// src/commands/inspect/utils.ts
|
|
450
502
|
import { readFileSync as readFileSync2, readdirSync, statSync as statSync2 } from "node:fs";
|
|
451
|
-
import
|
|
503
|
+
import path6 from "node:path";
|
|
452
504
|
|
|
453
505
|
// src/commands/results/manifest.ts
|
|
454
506
|
import { existsSync as existsSync2, readFileSync } from "node:fs";
|
|
455
|
-
import
|
|
507
|
+
import path5 from "node:path";
|
|
456
508
|
function parseJsonlLines(content) {
|
|
457
509
|
return content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => JSON.parse(line));
|
|
458
510
|
}
|
|
@@ -479,7 +531,7 @@ function readOptionalText(baseDir, relativePath) {
|
|
|
479
531
|
if (!relativePath) {
|
|
480
532
|
return void 0;
|
|
481
533
|
}
|
|
482
|
-
const absolutePath =
|
|
534
|
+
const absolutePath = path5.join(baseDir, relativePath);
|
|
483
535
|
if (!existsSync2(absolutePath)) {
|
|
484
536
|
return void 0;
|
|
485
537
|
}
|
|
@@ -601,8 +653,8 @@ function parseResultManifest(content) {
|
|
|
601
653
|
return parseResultRows(content);
|
|
602
654
|
}
|
|
603
655
|
function resolveResultSourcePath(source, cwd) {
|
|
604
|
-
const resolved =
|
|
605
|
-
if (isDirectoryPath(resolved) ||
|
|
656
|
+
const resolved = path5.isAbsolute(source) ? source : path5.resolve(cwd ?? process.cwd(), source);
|
|
657
|
+
if (isDirectoryPath(resolved) || path5.basename(resolved) === RESULT_INDEX_FILENAME) {
|
|
606
658
|
return resolveRunManifestPath(resolved);
|
|
607
659
|
}
|
|
608
660
|
return resolved;
|
|
@@ -611,7 +663,7 @@ function loadManifestResults(sourceFile, options = {}) {
|
|
|
611
663
|
const resolvedSourceFile = resolveRunManifestPath(sourceFile);
|
|
612
664
|
const content = readFileSync(resolvedSourceFile, "utf8");
|
|
613
665
|
const records = parseResultRows(content, resolvedSourceFile);
|
|
614
|
-
const baseDir =
|
|
666
|
+
const baseDir = path5.dirname(resolvedSourceFile);
|
|
615
667
|
return records.map((record) => hydrateManifestRecord(baseDir, record, options));
|
|
616
668
|
}
|
|
617
669
|
function loadLightweightResults(sourceFile) {
|
|
@@ -659,10 +711,10 @@ function padLeft(str, len) {
|
|
|
659
711
|
}
|
|
660
712
|
function loadResultFile(filePath) {
|
|
661
713
|
const resolvedFilePath = resolveTraceResultPath(filePath);
|
|
662
|
-
if (
|
|
714
|
+
if (path6.extname(resolvedFilePath) === ".json") {
|
|
663
715
|
return loadOtlpTraceFile(resolvedFilePath);
|
|
664
716
|
}
|
|
665
|
-
if (
|
|
717
|
+
if (path6.basename(resolvedFilePath) === RESULT_INDEX_FILENAME) {
|
|
666
718
|
return loadManifestAsRawResults(resolvedFilePath);
|
|
667
719
|
}
|
|
668
720
|
return loadJsonlRecords(resolvedFilePath);
|
|
@@ -960,7 +1012,7 @@ function toTraceSummary(result) {
|
|
|
960
1012
|
return toCamelCaseDeep(rawTrace);
|
|
961
1013
|
}
|
|
962
1014
|
function buildRunId(relativeRunPath) {
|
|
963
|
-
const normalized = relativeRunPath.split(
|
|
1015
|
+
const normalized = relativeRunPath.split(path6.sep).join("/");
|
|
964
1016
|
const segments = normalized.split("/").filter(Boolean);
|
|
965
1017
|
if (segments.length >= 2) {
|
|
966
1018
|
const experiment = segments.slice(0, -1).join("/");
|
|
@@ -974,8 +1026,8 @@ function buildRunId(relativeRunPath) {
|
|
|
974
1026
|
}
|
|
975
1027
|
function readRunDisplayName(runDir) {
|
|
976
1028
|
try {
|
|
977
|
-
const
|
|
978
|
-
const displayName =
|
|
1029
|
+
const summary = JSON.parse(readFileSync2(path6.join(runDir, "summary.json"), "utf8"));
|
|
1030
|
+
const displayName = summary.metadata?.display_name;
|
|
979
1031
|
return typeof displayName === "string" && displayName.trim() ? displayName.trim() : void 0;
|
|
980
1032
|
} catch {
|
|
981
1033
|
return void 0;
|
|
@@ -984,8 +1036,8 @@ function readRunDisplayName(runDir) {
|
|
|
984
1036
|
function collectRunManifestPaths(runsDir, currentDir, files) {
|
|
985
1037
|
const primaryPath = resolveExistingRunPrimaryPath(currentDir);
|
|
986
1038
|
if (primaryPath) {
|
|
987
|
-
const relativeRunPath =
|
|
988
|
-
const sortName =
|
|
1039
|
+
const relativeRunPath = path6.relative(runsDir, currentDir);
|
|
1040
|
+
const sortName = path6.basename(currentDir);
|
|
989
1041
|
files.push({
|
|
990
1042
|
filePath: primaryPath,
|
|
991
1043
|
displayName: readRunDisplayName(currentDir) ?? sortName,
|
|
@@ -997,7 +1049,7 @@ function collectRunManifestPaths(runsDir, currentDir, files) {
|
|
|
997
1049
|
const entries = readdirSync(currentDir, { withFileTypes: true });
|
|
998
1050
|
for (const entry of entries) {
|
|
999
1051
|
if (entry.isDirectory()) {
|
|
1000
|
-
collectRunManifestPaths(runsDir,
|
|
1052
|
+
collectRunManifestPaths(runsDir, path6.join(currentDir, entry.name), files);
|
|
1001
1053
|
}
|
|
1002
1054
|
}
|
|
1003
1055
|
}
|
|
@@ -1010,7 +1062,7 @@ function listResultFilesFromRoot(runsDir, options) {
|
|
|
1010
1062
|
if (options?.skipTopLevelDirs?.has(entry.name) || isReservedResultsNamespace(entry.name)) {
|
|
1011
1063
|
continue;
|
|
1012
1064
|
}
|
|
1013
|
-
collectRunManifestPaths(runsDir,
|
|
1065
|
+
collectRunManifestPaths(runsDir, path6.join(runsDir, entry.name), files);
|
|
1014
1066
|
}
|
|
1015
1067
|
}
|
|
1016
1068
|
} catch {
|
|
@@ -1091,7 +1143,7 @@ function formatScore(score) {
|
|
|
1091
1143
|
// src/commands/results/remote-metadata.ts
|
|
1092
1144
|
import { execFileSync } from "node:child_process";
|
|
1093
1145
|
import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync4, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1094
|
-
import
|
|
1146
|
+
import path8 from "node:path";
|
|
1095
1147
|
|
|
1096
1148
|
// src/commands/results/run-state.ts
|
|
1097
1149
|
import { createHash } from "node:crypto";
|
|
@@ -1132,12 +1184,12 @@ function materializeRunState(input) {
|
|
|
1132
1184
|
|
|
1133
1185
|
// src/commands/results/run-tags.ts
|
|
1134
1186
|
import { existsSync as existsSync3, readFileSync as readFileSync3, unlinkSync, writeFileSync } from "node:fs";
|
|
1135
|
-
import
|
|
1187
|
+
import path7 from "node:path";
|
|
1136
1188
|
var RUN_TAGS_FILENAME = "tags.json";
|
|
1137
1189
|
var MAX_TAGS_PER_RUN = 20;
|
|
1138
1190
|
var MAX_TAG_LENGTH = 60;
|
|
1139
1191
|
function runTagsPath(manifestPath) {
|
|
1140
|
-
return
|
|
1192
|
+
return path7.join(path7.dirname(manifestPath), RUN_TAGS_FILENAME);
|
|
1141
1193
|
}
|
|
1142
1194
|
function readRunTags(manifestPath) {
|
|
1143
1195
|
const fp = runTagsPath(manifestPath);
|
|
@@ -1202,7 +1254,7 @@ function normalizeTags(tags) {
|
|
|
1202
1254
|
|
|
1203
1255
|
// src/commands/results/remote-metadata.ts
|
|
1204
1256
|
var RESULTS_RUNS_DIR = "runs";
|
|
1205
|
-
var REMOTE_METADATA_RUNS_DIR =
|
|
1257
|
+
var REMOTE_METADATA_RUNS_DIR = path8.join("metadata", "runs");
|
|
1206
1258
|
function cleanGitEnv() {
|
|
1207
1259
|
const env = {};
|
|
1208
1260
|
for (const [key, value] of Object.entries(process.env)) {
|
|
@@ -1228,7 +1280,7 @@ function tryRunGit(repoDir, args) {
|
|
|
1228
1280
|
}
|
|
1229
1281
|
}
|
|
1230
1282
|
function toGitPath(filePath) {
|
|
1231
|
-
return filePath.split(
|
|
1283
|
+
return filePath.split(path8.sep).join("/");
|
|
1232
1284
|
}
|
|
1233
1285
|
function readTagsFile(filePath) {
|
|
1234
1286
|
if (!existsSync4(filePath)) return void 0;
|
|
@@ -1282,27 +1334,27 @@ function resolveComparisonRef(repoDir) {
|
|
|
1282
1334
|
return tryRunGit(repoDir, ["rev-parse", "--verify", "HEAD"]) ? "HEAD" : void 0;
|
|
1283
1335
|
}
|
|
1284
1336
|
function resolveRemoteRunMetadataPaths(repoDir, manifestPath) {
|
|
1285
|
-
const runsRoot =
|
|
1286
|
-
const manifestDir =
|
|
1287
|
-
const runRelativePath =
|
|
1288
|
-
if (runRelativePath.length === 0 || runRelativePath.startsWith("..") ||
|
|
1337
|
+
const runsRoot = path8.resolve(repoDir, RESULTS_RUNS_DIR);
|
|
1338
|
+
const manifestDir = path8.resolve(path8.dirname(manifestPath));
|
|
1339
|
+
const runRelativePath = path8.relative(runsRoot, manifestDir);
|
|
1340
|
+
if (runRelativePath.length === 0 || runRelativePath.startsWith("..") || path8.isAbsolute(runRelativePath)) {
|
|
1289
1341
|
throw new Error(
|
|
1290
1342
|
`Remote run manifest is outside the results repo runs directory: ${manifestPath}`
|
|
1291
1343
|
);
|
|
1292
1344
|
}
|
|
1293
|
-
const overlayTagsPath =
|
|
1345
|
+
const overlayTagsPath = path8.join(
|
|
1294
1346
|
repoDir,
|
|
1295
1347
|
REMOTE_METADATA_RUNS_DIR,
|
|
1296
1348
|
runRelativePath,
|
|
1297
1349
|
RUN_TAGS_FILENAME
|
|
1298
1350
|
);
|
|
1299
|
-
const artifactTagsPath =
|
|
1351
|
+
const artifactTagsPath = path8.join(runsRoot, runRelativePath, RUN_TAGS_FILENAME);
|
|
1300
1352
|
return {
|
|
1301
1353
|
runRelativePath,
|
|
1302
1354
|
artifactTagsPath,
|
|
1303
|
-
artifactTagsGitPath: toGitPath(
|
|
1355
|
+
artifactTagsGitPath: toGitPath(path8.relative(repoDir, artifactTagsPath)),
|
|
1304
1356
|
overlayTagsPath,
|
|
1305
|
-
overlayTagsGitPath: toGitPath(
|
|
1357
|
+
overlayTagsGitPath: toGitPath(path8.relative(repoDir, overlayTagsPath))
|
|
1306
1358
|
};
|
|
1307
1359
|
}
|
|
1308
1360
|
function readRemoteRunTagsContext(repoDir, manifestPath, comparisonRef = resolveComparisonRef(repoDir)) {
|
|
@@ -1363,7 +1415,7 @@ function writeRemoteRunTags(repoDir, manifestPath, tags, comparisonRef, expected
|
|
|
1363
1415
|
updated_at: updatedAt,
|
|
1364
1416
|
tag_revision: createTagRevision(cleaned, updatedAt)
|
|
1365
1417
|
};
|
|
1366
|
-
mkdirSync(
|
|
1418
|
+
mkdirSync(path8.dirname(context.paths.overlayTagsPath), { recursive: true });
|
|
1367
1419
|
writeFileSync2(context.paths.overlayTagsPath, `${JSON.stringify(entry, null, 2)}
|
|
1368
1420
|
`, "utf8");
|
|
1369
1421
|
return readRemoteRunTags(repoDir, manifestPath, comparisonRef);
|
|
@@ -1407,7 +1459,7 @@ function invalidateGitRunsCache(repoDir) {
|
|
|
1407
1459
|
}
|
|
1408
1460
|
}
|
|
1409
1461
|
function relativeLocalRunPath(cwd, manifestPath) {
|
|
1410
|
-
const manifestDir =
|
|
1462
|
+
const manifestDir = path9.resolve(path9.dirname(manifestPath));
|
|
1411
1463
|
return relativeRunPathFromCwd(cwd, manifestDir);
|
|
1412
1464
|
}
|
|
1413
1465
|
function remoteMetadataManifestPath(cwd, config, meta) {
|
|
@@ -1421,7 +1473,7 @@ function remoteMetadataManifestPath(cwd, config, meta) {
|
|
|
1421
1473
|
if (!relativeRunPath) {
|
|
1422
1474
|
return void 0;
|
|
1423
1475
|
}
|
|
1424
|
-
return
|
|
1476
|
+
return path9.join(config.path, "runs", ...relativeRunPath.split("/"), "index.jsonl");
|
|
1425
1477
|
}
|
|
1426
1478
|
var REMOTE_RUN_PREFIX = "remote::";
|
|
1427
1479
|
var SIZE_WARNING_BYTES = 10 * 1024 * 1024;
|
|
@@ -1434,7 +1486,7 @@ function getRelativeRunPath(cwd, runDir) {
|
|
|
1434
1486
|
return relative;
|
|
1435
1487
|
}
|
|
1436
1488
|
throw new Error(
|
|
1437
|
-
`Run workspace must use .agentv/results/<experiment>/<timestamp>: ${
|
|
1489
|
+
`Run workspace must use .agentv/results/<experiment>/<timestamp>: ${path9.resolve(runDir)}`
|
|
1438
1490
|
);
|
|
1439
1491
|
}
|
|
1440
1492
|
function buildCommitTitle(payload) {
|
|
@@ -1453,7 +1505,7 @@ async function maybeWarnLargeArtifact(runDir) {
|
|
|
1453
1505
|
}
|
|
1454
1506
|
async function loadNormalizedResultsConfig(cwd, projectId, overrides) {
|
|
1455
1507
|
const repoRoot = await findRepoRoot(cwd) ?? cwd;
|
|
1456
|
-
const config = await loadConfig(
|
|
1508
|
+
const config = await loadConfig(path9.join(cwd, "_"), repoRoot);
|
|
1457
1509
|
const project = projectId !== void 0 ? getProject(projectId) : getProjectForPath(repoRoot) ?? getProjectForPath(cwd);
|
|
1458
1510
|
const projectResults = project?.results ? {
|
|
1459
1511
|
mode: "github",
|
|
@@ -1571,6 +1623,32 @@ async function syncRemoteResults(cwd, projectId) {
|
|
|
1571
1623
|
};
|
|
1572
1624
|
}
|
|
1573
1625
|
}
|
|
1626
|
+
async function confirmRemoteResultsMerge(cwd, projectId) {
|
|
1627
|
+
const config = await loadNormalizedResultsConfig(cwd, projectId);
|
|
1628
|
+
if (!config) {
|
|
1629
|
+
return {
|
|
1630
|
+
...await getResultsRepoSyncStatus(),
|
|
1631
|
+
run_count: 0
|
|
1632
|
+
};
|
|
1633
|
+
}
|
|
1634
|
+
try {
|
|
1635
|
+
const status = await confirmResultsMergeAndPull(config);
|
|
1636
|
+
invalidateGitRunsCache(config.path);
|
|
1637
|
+
return {
|
|
1638
|
+
...status,
|
|
1639
|
+
run_count: await getRemoteRunCount(config, status)
|
|
1640
|
+
};
|
|
1641
|
+
} catch (error) {
|
|
1642
|
+
const status = await getResultsRepoSyncStatus(config);
|
|
1643
|
+
return {
|
|
1644
|
+
...status,
|
|
1645
|
+
run_count: await getRemoteRunCount(config, status),
|
|
1646
|
+
last_error: getStatusMessage(error),
|
|
1647
|
+
blocked: true,
|
|
1648
|
+
block_reason: getStatusMessage(error)
|
|
1649
|
+
};
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1574
1652
|
function dedupeSyncedRunCopies(runs) {
|
|
1575
1653
|
const byRunId = /* @__PURE__ */ new Map();
|
|
1576
1654
|
for (const run of runs) {
|
|
@@ -1613,7 +1691,7 @@ async function listMergedResultFiles(cwd, limit, projectId) {
|
|
|
1613
1691
|
raw_filename: r.run_id,
|
|
1614
1692
|
source: "remote",
|
|
1615
1693
|
on_remote: true,
|
|
1616
|
-
path:
|
|
1694
|
+
path: path9.join(config.path, r.manifest_path),
|
|
1617
1695
|
displayName: r.display_name,
|
|
1618
1696
|
timestamp: r.timestamp,
|
|
1619
1697
|
testCount: r.test_count,
|
|
@@ -1668,11 +1746,11 @@ async function ensureRemoteRunAvailable(cwd, meta, projectId) {
|
|
|
1668
1746
|
if (!config) {
|
|
1669
1747
|
throw new Error("Remote results are not configured");
|
|
1670
1748
|
}
|
|
1671
|
-
const relativeManifestPath =
|
|
1749
|
+
const relativeManifestPath = path9.relative(config.path, meta.path).split(path9.sep).join("/");
|
|
1672
1750
|
if (relativeManifestPath.length === 0 || relativeManifestPath === meta.path || relativeManifestPath.startsWith("../")) {
|
|
1673
1751
|
throw new Error(`Remote manifest path is outside the results repo clone: ${meta.path}`);
|
|
1674
1752
|
}
|
|
1675
|
-
const relativeRunPath =
|
|
1753
|
+
const relativeRunPath = path9.posix.relative("runs", path9.posix.dirname(relativeManifestPath));
|
|
1676
1754
|
await materializeGitRun(config.path, relativeRunPath, getResultsStorageRef(config));
|
|
1677
1755
|
}
|
|
1678
1756
|
async function readRemoteRunTagState(cwd, meta, projectId) {
|
|
@@ -1781,13 +1859,13 @@ async function maybeAutoExportRunArtifacts(payload) {
|
|
|
1781
1859
|
// src/commands/eval/env.ts
|
|
1782
1860
|
import { constants as constants3 } from "node:fs";
|
|
1783
1861
|
import { access as access3 } from "node:fs/promises";
|
|
1784
|
-
import
|
|
1862
|
+
import path10 from "node:path";
|
|
1785
1863
|
import { config as loadDotenv } from "dotenv";
|
|
1786
1864
|
function uniqueDirs(directories) {
|
|
1787
1865
|
const seen = /* @__PURE__ */ new Set();
|
|
1788
1866
|
const result = [];
|
|
1789
1867
|
for (const dir of directories) {
|
|
1790
|
-
const absolute =
|
|
1868
|
+
const absolute = path10.resolve(dir);
|
|
1791
1869
|
if (seen.has(absolute)) {
|
|
1792
1870
|
continue;
|
|
1793
1871
|
}
|
|
@@ -1806,14 +1884,14 @@ async function fileExists2(filePath) {
|
|
|
1806
1884
|
}
|
|
1807
1885
|
function collectAncestorDirectories(start, boundary) {
|
|
1808
1886
|
const directories = [];
|
|
1809
|
-
const boundaryDir =
|
|
1810
|
-
let current =
|
|
1887
|
+
const boundaryDir = path10.resolve(boundary);
|
|
1888
|
+
let current = path10.resolve(start);
|
|
1811
1889
|
while (current !== void 0) {
|
|
1812
1890
|
directories.push(current);
|
|
1813
1891
|
if (current === boundaryDir) {
|
|
1814
1892
|
break;
|
|
1815
1893
|
}
|
|
1816
|
-
const parent =
|
|
1894
|
+
const parent = path10.dirname(current);
|
|
1817
1895
|
if (parent === current) {
|
|
1818
1896
|
break;
|
|
1819
1897
|
}
|
|
@@ -1823,12 +1901,12 @@ function collectAncestorDirectories(start, boundary) {
|
|
|
1823
1901
|
}
|
|
1824
1902
|
async function loadEnvFromHierarchy(options) {
|
|
1825
1903
|
const { testFilePath, repoRoot, verbose } = options;
|
|
1826
|
-
const testDir =
|
|
1904
|
+
const testDir = path10.dirname(path10.resolve(testFilePath));
|
|
1827
1905
|
const cwd = process.cwd();
|
|
1828
1906
|
const searchDirs = uniqueDirs([...collectAncestorDirectories(testDir, repoRoot), repoRoot, cwd]);
|
|
1829
1907
|
const envFiles = [];
|
|
1830
1908
|
for (const dir of searchDirs) {
|
|
1831
|
-
const candidate =
|
|
1909
|
+
const candidate = path10.join(dir, ".env");
|
|
1832
1910
|
if (await fileExists2(candidate)) {
|
|
1833
1911
|
envFiles.push(candidate);
|
|
1834
1912
|
}
|
|
@@ -1851,7 +1929,7 @@ async function loadEnvFromHierarchy(options) {
|
|
|
1851
1929
|
|
|
1852
1930
|
// src/commands/eval/otel-backends.ts
|
|
1853
1931
|
import { access as access4 } from "node:fs/promises";
|
|
1854
|
-
import
|
|
1932
|
+
import path11 from "node:path";
|
|
1855
1933
|
import { pathToFileURL } from "node:url";
|
|
1856
1934
|
var RESOLVER_EXTENSIONS = [".mjs", ".js"];
|
|
1857
1935
|
var builtinOtelBackendResolvers = [
|
|
@@ -1915,7 +1993,7 @@ async function findLocalOtelBackendResolver(name, cwd) {
|
|
|
1915
1993
|
}
|
|
1916
1994
|
for (const dir of getResolverSearchDirs(cwd)) {
|
|
1917
1995
|
for (const ext of RESOLVER_EXTENSIONS) {
|
|
1918
|
-
const candidate =
|
|
1996
|
+
const candidate = path11.join(dir, `${name}${ext}`);
|
|
1919
1997
|
try {
|
|
1920
1998
|
await access4(candidate);
|
|
1921
1999
|
return candidate;
|
|
@@ -1927,11 +2005,11 @@ async function findLocalOtelBackendResolver(name, cwd) {
|
|
|
1927
2005
|
}
|
|
1928
2006
|
function getResolverSearchDirs(cwd) {
|
|
1929
2007
|
const dirs = [];
|
|
1930
|
-
let current =
|
|
1931
|
-
const root =
|
|
2008
|
+
let current = path11.resolve(cwd);
|
|
2009
|
+
const root = path11.parse(current).root;
|
|
1932
2010
|
while (current !== root) {
|
|
1933
|
-
dirs.push(
|
|
1934
|
-
current =
|
|
2011
|
+
dirs.push(path11.join(current, ".agentv", "otel-backends"));
|
|
2012
|
+
current = path11.dirname(current);
|
|
1935
2013
|
}
|
|
1936
2014
|
return dirs;
|
|
1937
2015
|
}
|
|
@@ -1960,7 +2038,7 @@ function trimTrailingSlash(value) {
|
|
|
1960
2038
|
// src/commands/eval/jsonl-writer.ts
|
|
1961
2039
|
import { createWriteStream } from "node:fs";
|
|
1962
2040
|
import { mkdir } from "node:fs/promises";
|
|
1963
|
-
import
|
|
2041
|
+
import path12 from "node:path";
|
|
1964
2042
|
import { finished } from "node:stream/promises";
|
|
1965
2043
|
|
|
1966
2044
|
// ../../node_modules/.bun/async-mutex@0.5.0/node_modules/async-mutex/index.mjs
|
|
@@ -2178,7 +2256,7 @@ var JsonlWriter = class _JsonlWriter {
|
|
|
2178
2256
|
this.stream = stream;
|
|
2179
2257
|
}
|
|
2180
2258
|
static async open(filePath, options) {
|
|
2181
|
-
await mkdir(
|
|
2259
|
+
await mkdir(path12.dirname(filePath), { recursive: true });
|
|
2182
2260
|
const flags = options?.append ? "a" : "w";
|
|
2183
2261
|
const stream = createWriteStream(filePath, { flags, encoding: "utf8" });
|
|
2184
2262
|
return new _JsonlWriter(stream);
|
|
@@ -2363,7 +2441,7 @@ async function loadNonErrorResults(jsonlPath) {
|
|
|
2363
2441
|
// src/commands/eval/run-cache.ts
|
|
2364
2442
|
import { existsSync as existsSync6 } from "node:fs";
|
|
2365
2443
|
import { mkdir as mkdir2, readFile, writeFile } from "node:fs/promises";
|
|
2366
|
-
import
|
|
2444
|
+
import path13 from "node:path";
|
|
2367
2445
|
var CACHE_FILENAME = "cache.json";
|
|
2368
2446
|
function resolveRunCacheFile(cache) {
|
|
2369
2447
|
if (cache.lastRunDir) {
|
|
@@ -2372,7 +2450,7 @@ function resolveRunCacheFile(cache) {
|
|
|
2372
2450
|
return "";
|
|
2373
2451
|
}
|
|
2374
2452
|
function cachePath(cwd) {
|
|
2375
|
-
return
|
|
2453
|
+
return path13.join(cwd, ".agentv", CACHE_FILENAME);
|
|
2376
2454
|
}
|
|
2377
2455
|
async function loadRunCache(cwd) {
|
|
2378
2456
|
try {
|
|
@@ -2389,13 +2467,13 @@ async function resolveCachedRunDir(cwd) {
|
|
|
2389
2467
|
return cache.lastRunDir;
|
|
2390
2468
|
}
|
|
2391
2469
|
async function saveRunCache(cwd, resultPath) {
|
|
2392
|
-
if (
|
|
2470
|
+
if (path13.basename(resultPath) !== RESULT_INDEX_FILENAME) {
|
|
2393
2471
|
return;
|
|
2394
2472
|
}
|
|
2395
|
-
const dir =
|
|
2473
|
+
const dir = path13.join(cwd, ".agentv");
|
|
2396
2474
|
await mkdir2(dir, { recursive: true });
|
|
2397
2475
|
const cache = {
|
|
2398
|
-
lastRunDir:
|
|
2476
|
+
lastRunDir: path13.dirname(resultPath),
|
|
2399
2477
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2400
2478
|
};
|
|
2401
2479
|
await writeFile(cachePath(cwd), `${JSON.stringify(cache, null, 2)}
|
|
@@ -2664,7 +2742,7 @@ function formatMatrixSummary(results) {
|
|
|
2664
2742
|
|
|
2665
2743
|
// ../../packages/core/dist/evaluation/validation/index.js
|
|
2666
2744
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
2667
|
-
import
|
|
2745
|
+
import path14 from "node:path";
|
|
2668
2746
|
import { readFile as readFile22, readdir, stat as stat2 } from "node:fs/promises";
|
|
2669
2747
|
import path22 from "node:path";
|
|
2670
2748
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
@@ -2710,10 +2788,13 @@ async function detectFileType(filePath) {
|
|
|
2710
2788
|
}
|
|
2711
2789
|
}
|
|
2712
2790
|
function inferFileTypeFromPath(filePath) {
|
|
2713
|
-
const normalized =
|
|
2714
|
-
const basename =
|
|
2791
|
+
const normalized = path14.normalize(filePath).replace(/\\/g, "/");
|
|
2792
|
+
const basename = path14.basename(filePath);
|
|
2793
|
+
if (basename === AGENTV_LOCAL_CONFIG_FILE_NAME || basename === AGENTV_LOCAL_CONFIG_YML_FILE_NAME) {
|
|
2794
|
+
return "config";
|
|
2795
|
+
}
|
|
2715
2796
|
if (normalized.includes("/.agentv/")) {
|
|
2716
|
-
if (basename
|
|
2797
|
+
if (isAgentVConfigFileName(basename)) {
|
|
2717
2798
|
return "config";
|
|
2718
2799
|
}
|
|
2719
2800
|
if (basename === "targets.yaml" || basename === "targets.yml") {
|
|
@@ -2726,6 +2807,62 @@ function inferFileTypeFromPath(filePath) {
|
|
|
2726
2807
|
}
|
|
2727
2808
|
return "unknown";
|
|
2728
2809
|
}
|
|
2810
|
+
var JsonObjectSchema = external_exports.object({}).catchall(external_exports.unknown());
|
|
2811
|
+
var StringOrStringArraySchema = external_exports.union([external_exports.string().min(1), external_exports.array(external_exports.string().min(1)).min(1)]);
|
|
2812
|
+
var ExperimentScriptSchema = external_exports.union([
|
|
2813
|
+
external_exports.string().min(1),
|
|
2814
|
+
external_exports.object({
|
|
2815
|
+
command: StringOrStringArraySchema.optional(),
|
|
2816
|
+
script: StringOrStringArraySchema.optional(),
|
|
2817
|
+
timeout_seconds: external_exports.number().gt(0).optional(),
|
|
2818
|
+
cwd: external_exports.string().min(1).optional(),
|
|
2819
|
+
env: external_exports.record(external_exports.string()).optional()
|
|
2820
|
+
}).strict().refine((value) => value.command !== void 0 || value.script !== void 0, {
|
|
2821
|
+
message: "Experiment step must define command or script."
|
|
2822
|
+
})
|
|
2823
|
+
]);
|
|
2824
|
+
var ExperimentRepeatSchema = external_exports.object({
|
|
2825
|
+
count: external_exports.number().int().min(1),
|
|
2826
|
+
strategy: external_exports.enum(["pass_at_k", "mean", "confidence_interval"]).optional(),
|
|
2827
|
+
cost_limit_usd: external_exports.number().min(0).optional(),
|
|
2828
|
+
costLimitUsd: external_exports.number().min(0).optional()
|
|
2829
|
+
}).strict();
|
|
2830
|
+
var ExperimentTargetRefSchema = external_exports.union([
|
|
2831
|
+
external_exports.string().min(1),
|
|
2832
|
+
external_exports.object({
|
|
2833
|
+
name: external_exports.string().min(1),
|
|
2834
|
+
use_target: external_exports.string().min(1).optional(),
|
|
2835
|
+
hooks: JsonObjectSchema.optional()
|
|
2836
|
+
}).strict()
|
|
2837
|
+
]);
|
|
2838
|
+
var ExperimentSuiteSelectSchema = external_exports.object({
|
|
2839
|
+
test_ids: external_exports.array(external_exports.string().min(1)).min(1)
|
|
2840
|
+
}).strict();
|
|
2841
|
+
var ExperimentSuiteRefSchema = external_exports.object({
|
|
2842
|
+
ref: external_exports.string().min(1),
|
|
2843
|
+
select: ExperimentSuiteSelectSchema.optional()
|
|
2844
|
+
}).strict();
|
|
2845
|
+
var ExperimentFileSchema = external_exports.object({
|
|
2846
|
+
name: external_exports.string().min(1).optional(),
|
|
2847
|
+
agent: external_exports.string().min(1).optional(),
|
|
2848
|
+
target: external_exports.string().min(1).optional(),
|
|
2849
|
+
targets: external_exports.array(ExperimentTargetRefSchema).min(1).optional(),
|
|
2850
|
+
model: external_exports.string().min(1).optional(),
|
|
2851
|
+
agent_options: JsonObjectSchema.optional(),
|
|
2852
|
+
suites: external_exports.array(ExperimentSuiteRefSchema).min(1).optional(),
|
|
2853
|
+
scripts: external_exports.array(ExperimentScriptSchema).optional(),
|
|
2854
|
+
repeat: ExperimentRepeatSchema.optional(),
|
|
2855
|
+
runs: external_exports.number().int().min(1).optional(),
|
|
2856
|
+
early_exit: external_exports.boolean().optional(),
|
|
2857
|
+
timeout_seconds: external_exports.number().gt(0).optional(),
|
|
2858
|
+
workers: external_exports.number().int().min(1).optional(),
|
|
2859
|
+
budget_usd: external_exports.number().gt(0).optional(),
|
|
2860
|
+
sandbox: external_exports.enum(["auto", "docker", "vercel"]).optional(),
|
|
2861
|
+
workspace: JsonObjectSchema.optional(),
|
|
2862
|
+
setup: external_exports.array(ExperimentScriptSchema).optional()
|
|
2863
|
+
}).strict().refine((value) => value.repeat === void 0 || value.runs === void 0, {
|
|
2864
|
+
message: "Use repeat or runs, not both."
|
|
2865
|
+
});
|
|
2729
2866
|
var ASSERTION_TYPES_WITH_STRING_VALUE = /* @__PURE__ */ new Set([
|
|
2730
2867
|
"contains",
|
|
2731
2868
|
"icontains",
|
|
@@ -3023,8 +3160,16 @@ async function validateEvalFile(filePath) {
|
|
|
3023
3160
|
message: "Invalid 'criteria' field (must be a non-empty string if provided)"
|
|
3024
3161
|
});
|
|
3025
3162
|
}
|
|
3163
|
+
const caseExecution = isObject(evalCase.execution) ? evalCase.execution : void 0;
|
|
3164
|
+
const skipDefaults = caseExecution?.skip_defaults === true;
|
|
3165
|
+
const hasPromptMdFallback = evalCase.input === void 0 ? await loadPromptMdFallback({
|
|
3166
|
+
evalFilePath: absolutePath,
|
|
3167
|
+
searchRoots: buildSearchRoots2(absolutePath, process.cwd()),
|
|
3168
|
+
testInputFiles: evalCase.input_files,
|
|
3169
|
+
suiteInputFiles: skipDefaults ? void 0 : parsed.input_files
|
|
3170
|
+
}) !== void 0 : false;
|
|
3026
3171
|
validateInputField(evalCase.input, `${location}.input`, absolutePath, errors, {
|
|
3027
|
-
required:
|
|
3172
|
+
required: !hasPromptMdFallback
|
|
3028
3173
|
});
|
|
3029
3174
|
const expectedOutputField = evalCase.expected_output;
|
|
3030
3175
|
if (expectedOutputField !== void 0) {
|
|
@@ -3247,7 +3392,7 @@ function validateInputField(inputField, location, filePath, errors, options = {}
|
|
|
3247
3392
|
severity: "error",
|
|
3248
3393
|
filePath,
|
|
3249
3394
|
location,
|
|
3250
|
-
message: "Missing 'input' field (
|
|
3395
|
+
message: "Missing 'input' field (provide a string, object, message array, or PROMPT.md next to EVAL.yaml / referenced in input_files)"
|
|
3251
3396
|
});
|
|
3252
3397
|
}
|
|
3253
3398
|
return;
|
|
@@ -4241,7 +4386,9 @@ async function validateConfigFile(filePath, options = {}) {
|
|
|
4241
4386
|
}
|
|
4242
4387
|
function inferConfigScope(filePath) {
|
|
4243
4388
|
const globalConfigPath = path52.resolve(getAgentvConfigDir(), "config.yaml");
|
|
4244
|
-
|
|
4389
|
+
const globalLocalConfigPath = path52.resolve(getLocalConfigPath(globalConfigPath));
|
|
4390
|
+
const resolvedPath = path52.resolve(filePath);
|
|
4391
|
+
if (resolvedPath === globalConfigPath || resolvedPath === globalLocalConfigPath) {
|
|
4245
4392
|
return "global";
|
|
4246
4393
|
}
|
|
4247
4394
|
return filePath.split(/[\\/]/).includes(".agentv") ? "project" : "global";
|
|
@@ -4474,12 +4621,19 @@ function validateResultsSyncAndBranchPrefix(errors, filePath, resultsRecord, loc
|
|
|
4474
4621
|
`Field '${location}.sync.require_push' must be a boolean`
|
|
4475
4622
|
);
|
|
4476
4623
|
}
|
|
4477
|
-
if (syncRecord.push_conflict_policy
|
|
4624
|
+
if (syncRecord.push_conflict_policy === "backup_and_force_push") {
|
|
4478
4625
|
addError(
|
|
4479
4626
|
errors,
|
|
4480
4627
|
filePath,
|
|
4481
4628
|
`${location}.sync.push_conflict_policy`,
|
|
4482
|
-
`Field '${location}.sync.push_conflict_policy'
|
|
4629
|
+
`Field '${location}.sync.push_conflict_policy' uses removed value 'backup_and_force_push'; remove it or set it to 'block'. AgentV never force-pushes result branches.`
|
|
4630
|
+
);
|
|
4631
|
+
} else if (syncRecord.push_conflict_policy !== void 0 && syncRecord.push_conflict_policy !== "block") {
|
|
4632
|
+
addError(
|
|
4633
|
+
errors,
|
|
4634
|
+
filePath,
|
|
4635
|
+
`${location}.sync.push_conflict_policy`,
|
|
4636
|
+
`Field '${location}.sync.push_conflict_policy' must be 'block'`
|
|
4483
4637
|
);
|
|
4484
4638
|
}
|
|
4485
4639
|
}
|
|
@@ -5226,6 +5380,8 @@ var WipCheckpointLoop = class {
|
|
|
5226
5380
|
|
|
5227
5381
|
// src/commands/eval/run-eval.ts
|
|
5228
5382
|
var DEFAULT_WORKERS = 3;
|
|
5383
|
+
var loadCjsModule = createNodeRequire(import.meta.url);
|
|
5384
|
+
var micromatch = loadCjsModule("micromatch");
|
|
5229
5385
|
function shouldSkipExistingResultForResume(result, rerunFailed) {
|
|
5230
5386
|
if (rerunFailed) {
|
|
5231
5387
|
return result.executionStatus === "ok";
|
|
@@ -5306,13 +5462,13 @@ function normalizeSourceMetadataByEvalFile(value) {
|
|
|
5306
5462
|
const entries = [...value.entries()].filter(
|
|
5307
5463
|
(entry) => typeof entry[0] === "string" && typeof entry[1] === "object" && entry[1] !== null && !Array.isArray(entry[1])
|
|
5308
5464
|
);
|
|
5309
|
-
return entries.length > 0 ? new Map(entries.map(([key, metadata]) => [
|
|
5465
|
+
return entries.length > 0 ? new Map(entries.map(([key, metadata]) => [path15.resolve(key), metadata])) : void 0;
|
|
5310
5466
|
}
|
|
5311
5467
|
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
5312
5468
|
const entries = Object.entries(value).filter(
|
|
5313
5469
|
(entry) => typeof entry[1] === "object" && entry[1] !== null && !Array.isArray(entry[1])
|
|
5314
5470
|
);
|
|
5315
|
-
return entries.length > 0 ? new Map(entries.map(([key, metadata]) => [
|
|
5471
|
+
return entries.length > 0 ? new Map(entries.map(([key, metadata]) => [path15.resolve(key), metadata])) : void 0;
|
|
5316
5472
|
}
|
|
5317
5473
|
return void 0;
|
|
5318
5474
|
}
|
|
@@ -5326,10 +5482,10 @@ var LEGACY_OUTPUT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
5326
5482
|
".htm"
|
|
5327
5483
|
]);
|
|
5328
5484
|
function looksLikeLegacyOutputFilePath(value) {
|
|
5329
|
-
return LEGACY_OUTPUT_FILE_EXTENSIONS.has(
|
|
5485
|
+
return LEGACY_OUTPUT_FILE_EXTENSIONS.has(path15.extname(value).toLowerCase());
|
|
5330
5486
|
}
|
|
5331
5487
|
function outputFileMigrationMessage(value) {
|
|
5332
|
-
const ext =
|
|
5488
|
+
const ext = path15.extname(value).toLowerCase();
|
|
5333
5489
|
const removalHint = ext === ".xml" ? "JUnit XML export from agentv eval has been removed." : "Flat result file export from agentv eval has been removed.";
|
|
5334
5490
|
return `--output expects a run directory, not a file path: ${value}
|
|
5335
5491
|
${removalHint} Set --output <dir> for the canonical run artifacts; AgentV always writes <dir>/index.jsonl.`;
|
|
@@ -5337,7 +5493,7 @@ ${removalHint} Set --output <dir> for the canonical run artifacts; AgentV always
|
|
|
5337
5493
|
function artifactsMigrationMessage(artifactsDir, outputDir) {
|
|
5338
5494
|
const lines = [`--artifacts was removed from agentv eval. Use --output ${artifactsDir} instead.`];
|
|
5339
5495
|
if (outputDir && looksLikeLegacyOutputFilePath(outputDir)) {
|
|
5340
|
-
const ext =
|
|
5496
|
+
const ext = path15.extname(outputDir).toLowerCase();
|
|
5341
5497
|
lines.push(
|
|
5342
5498
|
ext === ".xml" ? "JUnit XML export from agentv eval has been removed." : "Flat result file export from agentv eval has been removed."
|
|
5343
5499
|
);
|
|
@@ -5493,7 +5649,7 @@ function normalizeOptions(rawOptions, config, yamlExecution) {
|
|
|
5493
5649
|
};
|
|
5494
5650
|
}
|
|
5495
5651
|
function withSourceMetadata(result, testFilePath, options) {
|
|
5496
|
-
const sourceMetadata = options.sourceMetadataByEvalFile?.get(
|
|
5652
|
+
const sourceMetadata = options.sourceMetadataByEvalFile?.get(path15.resolve(testFilePath));
|
|
5497
5653
|
if (!sourceMetadata) {
|
|
5498
5654
|
return result;
|
|
5499
5655
|
}
|
|
@@ -5515,7 +5671,258 @@ async function ensureFileExists(filePath, description) {
|
|
|
5515
5671
|
function buildDefaultOutputPathForExperiment(cwd, experiment, runDirName) {
|
|
5516
5672
|
const runDir = buildDefaultRunDirFromName(cwd, experiment, runDirName);
|
|
5517
5673
|
mkdirSync2(runDir, { recursive: true });
|
|
5518
|
-
return
|
|
5674
|
+
return path15.join(runDir, "index.jsonl");
|
|
5675
|
+
}
|
|
5676
|
+
function normalizeTsDefaultExperiment(config) {
|
|
5677
|
+
return normalizeString(config?.experiments?.default) ?? normalizeString(config?.defaultExperiment);
|
|
5678
|
+
}
|
|
5679
|
+
async function resolveExperimentForRun(params) {
|
|
5680
|
+
const experimentRef = params.explicitExperiment ?? params.yamlDefaultExperiment ?? params.tsDefaultExperiment;
|
|
5681
|
+
if (!experimentRef) {
|
|
5682
|
+
return {};
|
|
5683
|
+
}
|
|
5684
|
+
const experimentPath = resolveExperimentFilePath(params.cwd, experimentRef);
|
|
5685
|
+
if (!experimentPath) {
|
|
5686
|
+
if (isExperimentFileReference(experimentRef)) {
|
|
5687
|
+
throw new Error(`Experiment file not found: ${experimentRef}`);
|
|
5688
|
+
}
|
|
5689
|
+
return { name: experimentRef };
|
|
5690
|
+
}
|
|
5691
|
+
const config = await loadExperimentConfig(experimentPath);
|
|
5692
|
+
return {
|
|
5693
|
+
name: config.name ?? deriveExperimentNameFromPath(experimentPath),
|
|
5694
|
+
config
|
|
5695
|
+
};
|
|
5696
|
+
}
|
|
5697
|
+
function resolveExperimentFilePath(cwd, experimentRef) {
|
|
5698
|
+
if (isExperimentFileReference(experimentRef)) {
|
|
5699
|
+
const experimentPath = path15.isAbsolute(experimentRef) ? experimentRef : path15.resolve(cwd, experimentRef);
|
|
5700
|
+
return existsSync7(experimentPath) ? experimentPath : void 0;
|
|
5701
|
+
}
|
|
5702
|
+
for (const ext of ["yaml", "yml", "ts", "js", "mts", "mjs"]) {
|
|
5703
|
+
const candidate = path15.resolve(cwd, "experiments", `${experimentRef}.${ext}`);
|
|
5704
|
+
if (existsSync7(candidate)) {
|
|
5705
|
+
return candidate;
|
|
5706
|
+
}
|
|
5707
|
+
}
|
|
5708
|
+
return void 0;
|
|
5709
|
+
}
|
|
5710
|
+
function applyExperimentOptions(options, experiment) {
|
|
5711
|
+
if (!experiment) {
|
|
5712
|
+
return options;
|
|
5713
|
+
}
|
|
5714
|
+
const experimentTargetRefs = buildExperimentTargetRefs(experiment);
|
|
5715
|
+
const experimentTargetNames = experimentTargetRefs?.map((target) => target.name) ?? [];
|
|
5716
|
+
const experimentTarget = experiment.target && experiment.target.trim().length > 0 ? experiment.target : void 0;
|
|
5717
|
+
const nextCliTargets = options.cliTargets.length > 0 ? options.cliTargets : experimentTargetNames.length > 0 ? experimentTargetNames : experimentTarget ? [experimentTarget] : options.cliTargets;
|
|
5718
|
+
const workspaceMode = options.workspaceMode ?? readExperimentWorkspaceMode(experiment.workspace?.mode);
|
|
5719
|
+
const workspacePath = options.workspacePath ?? readExperimentWorkspacePath(experiment.workspace);
|
|
5720
|
+
return {
|
|
5721
|
+
...options,
|
|
5722
|
+
target: options.target ?? (nextCliTargets.length === 1 ? nextCliTargets[0] : void 0),
|
|
5723
|
+
cliTargets: nextCliTargets,
|
|
5724
|
+
agentTimeoutSeconds: options.agentTimeoutSeconds ?? experiment.timeoutSeconds,
|
|
5725
|
+
workers: options.workers ?? experiment.workers,
|
|
5726
|
+
workspaceMode: workspacePath ? "static" : workspaceMode,
|
|
5727
|
+
workspacePath,
|
|
5728
|
+
budgetUsd: options.budgetUsd ?? experiment.budgetUsd,
|
|
5729
|
+
experimentConfig: experiment,
|
|
5730
|
+
experimentMetadata: buildExperimentArtifactMetadata(experiment),
|
|
5731
|
+
experimentTargetRefs: options.cliTargets.length === 0 ? experimentTargetRefs : void 0,
|
|
5732
|
+
experimentTrialsConfig: buildExperimentTrialsConfig(experiment)
|
|
5733
|
+
};
|
|
5734
|
+
}
|
|
5735
|
+
function buildExperimentTargetRefs(experiment) {
|
|
5736
|
+
if (!experiment.targets || experiment.targets.length === 0) {
|
|
5737
|
+
return void 0;
|
|
5738
|
+
}
|
|
5739
|
+
return experiment.targets.map((target) => {
|
|
5740
|
+
if (typeof target === "string") {
|
|
5741
|
+
return { name: target };
|
|
5742
|
+
}
|
|
5743
|
+
return {
|
|
5744
|
+
name: target.name,
|
|
5745
|
+
...target.useTarget !== void 0 && { use_target: target.useTarget },
|
|
5746
|
+
...target.hooks !== void 0 && {
|
|
5747
|
+
hooks: target.hooks
|
|
5748
|
+
}
|
|
5749
|
+
};
|
|
5750
|
+
});
|
|
5751
|
+
}
|
|
5752
|
+
function buildExperimentTrialsConfig(experiment) {
|
|
5753
|
+
if (experiment.repeat) {
|
|
5754
|
+
if (experiment.repeat.count <= 1) {
|
|
5755
|
+
return void 0;
|
|
5756
|
+
}
|
|
5757
|
+
return {
|
|
5758
|
+
count: experiment.repeat.count,
|
|
5759
|
+
strategy: experiment.repeat.strategy,
|
|
5760
|
+
...experiment.repeat.costLimitUsd !== void 0 && {
|
|
5761
|
+
costLimitUsd: experiment.repeat.costLimitUsd
|
|
5762
|
+
},
|
|
5763
|
+
...experiment.earlyExit !== void 0 && { earlyExit: experiment.earlyExit }
|
|
5764
|
+
};
|
|
5765
|
+
}
|
|
5766
|
+
if (!experiment.runs || experiment.runs <= 1) {
|
|
5767
|
+
return void 0;
|
|
5768
|
+
}
|
|
5769
|
+
return {
|
|
5770
|
+
count: experiment.runs,
|
|
5771
|
+
strategy: "pass_at_k",
|
|
5772
|
+
...experiment.earlyExit !== void 0 && { earlyExit: experiment.earlyExit }
|
|
5773
|
+
};
|
|
5774
|
+
}
|
|
5775
|
+
function readExperimentWorkspaceMode(value) {
|
|
5776
|
+
return value === "pooled" || value === "temp" || value === "static" ? value : void 0;
|
|
5777
|
+
}
|
|
5778
|
+
function readExperimentWorkspacePath(workspace) {
|
|
5779
|
+
const value = workspace?.path;
|
|
5780
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
5781
|
+
}
|
|
5782
|
+
function matchesTestFilter(id, filter) {
|
|
5783
|
+
return typeof filter === "string" ? micromatch.isMatch(id, filter) : filter.some((pattern) => micromatch.isMatch(id, pattern));
|
|
5784
|
+
}
|
|
5785
|
+
async function resolveExperimentSuiteSelection(suites, cwd) {
|
|
5786
|
+
if (!suites || suites.length === 0) {
|
|
5787
|
+
return void 0;
|
|
5788
|
+
}
|
|
5789
|
+
const testFiles = /* @__PURE__ */ new Set();
|
|
5790
|
+
const selectedTestIdsByEvalFile = /* @__PURE__ */ new Map();
|
|
5791
|
+
for (const suite of suites) {
|
|
5792
|
+
const resolvedSuiteFiles = await resolveEvalPaths([suite.ref], cwd);
|
|
5793
|
+
for (const testFilePath of resolvedSuiteFiles) {
|
|
5794
|
+
const resolvedPath = path15.resolve(testFilePath);
|
|
5795
|
+
testFiles.add(resolvedPath);
|
|
5796
|
+
if (suite.select?.testIds && suite.select.testIds.length > 0) {
|
|
5797
|
+
const existing = selectedTestIdsByEvalFile.get(resolvedPath) ?? [];
|
|
5798
|
+
selectedTestIdsByEvalFile.set(resolvedPath, [...existing, ...suite.select.testIds]);
|
|
5799
|
+
}
|
|
5800
|
+
}
|
|
5801
|
+
}
|
|
5802
|
+
const filtersByEvalFile = /* @__PURE__ */ new Map();
|
|
5803
|
+
for (const [testFilePath, testIds] of selectedTestIdsByEvalFile.entries()) {
|
|
5804
|
+
const uniqueTestIds = [...new Set(testIds)];
|
|
5805
|
+
filtersByEvalFile.set(
|
|
5806
|
+
testFilePath,
|
|
5807
|
+
uniqueTestIds.length === 1 ? uniqueTestIds[0] : uniqueTestIds
|
|
5808
|
+
);
|
|
5809
|
+
}
|
|
5810
|
+
return {
|
|
5811
|
+
testFiles: [...testFiles],
|
|
5812
|
+
filtersByEvalFile
|
|
5813
|
+
};
|
|
5814
|
+
}
|
|
5815
|
+
async function runExperimentSteps(params) {
|
|
5816
|
+
const steps = params.steps ?? [];
|
|
5817
|
+
if (steps.length === 0) {
|
|
5818
|
+
return;
|
|
5819
|
+
}
|
|
5820
|
+
for (let index = 0; index < steps.length; index++) {
|
|
5821
|
+
const step = steps[index];
|
|
5822
|
+
const command = buildExperimentStepCommand(step);
|
|
5823
|
+
const cwd = resolveExperimentStepCwd(params.cwd, params.experimentConfig, step.cwd);
|
|
5824
|
+
console.log(`Experiment ${params.label} ${index + 1}/${steps.length}: ${command.display}`);
|
|
5825
|
+
await runExperimentCommand(command.argv, {
|
|
5826
|
+
cwd,
|
|
5827
|
+
env: step.env,
|
|
5828
|
+
timeoutMs: step.timeoutSeconds ? step.timeoutSeconds * 1e3 : void 0,
|
|
5829
|
+
label: `experiment ${params.label}`
|
|
5830
|
+
});
|
|
5831
|
+
}
|
|
5832
|
+
}
|
|
5833
|
+
async function runExperimentSetup(params) {
|
|
5834
|
+
const setup = params.config?.setup;
|
|
5835
|
+
if (typeof setup === "function") {
|
|
5836
|
+
console.log("Experiment setup: running TypeScript setup()");
|
|
5837
|
+
await setup({
|
|
5838
|
+
cwd: params.cwd,
|
|
5839
|
+
runDir: params.runDir,
|
|
5840
|
+
experiment: params.config,
|
|
5841
|
+
env: process.env
|
|
5842
|
+
});
|
|
5843
|
+
return;
|
|
5844
|
+
}
|
|
5845
|
+
await runExperimentSteps({
|
|
5846
|
+
label: "setup",
|
|
5847
|
+
steps: setup,
|
|
5848
|
+
cwd: params.cwd,
|
|
5849
|
+
experimentConfig: params.config
|
|
5850
|
+
});
|
|
5851
|
+
}
|
|
5852
|
+
function buildExperimentStepCommand(step) {
|
|
5853
|
+
if (step.command && step.command.length > 0) {
|
|
5854
|
+
return { argv: step.command, display: step.command.join(" ") };
|
|
5855
|
+
}
|
|
5856
|
+
if (typeof step.script === "string" && step.script.trim().length > 0) {
|
|
5857
|
+
return {
|
|
5858
|
+
argv: shellCommand(step.script),
|
|
5859
|
+
display: step.script
|
|
5860
|
+
};
|
|
5861
|
+
}
|
|
5862
|
+
if (Array.isArray(step.script) && step.script.length > 0) {
|
|
5863
|
+
return { argv: step.script, display: step.script.join(" ") };
|
|
5864
|
+
}
|
|
5865
|
+
throw new Error("Experiment step must define command or script.");
|
|
5866
|
+
}
|
|
5867
|
+
function shellCommand(script) {
|
|
5868
|
+
return process.platform === "win32" ? ["cmd", "/c", script] : ["sh", "-c", script];
|
|
5869
|
+
}
|
|
5870
|
+
function resolveExperimentStepCwd(cwd, experimentConfig, stepCwd) {
|
|
5871
|
+
const base = experimentConfig?.sourcePath ? path15.dirname(experimentConfig.sourcePath) : cwd;
|
|
5872
|
+
if (!stepCwd) {
|
|
5873
|
+
return base;
|
|
5874
|
+
}
|
|
5875
|
+
return path15.isAbsolute(stepCwd) ? stepCwd : path15.resolve(base, stepCwd);
|
|
5876
|
+
}
|
|
5877
|
+
async function runExperimentCommand(argv, options) {
|
|
5878
|
+
if (argv.length === 0) {
|
|
5879
|
+
throw new Error(`${options.label} command must not be empty.`);
|
|
5880
|
+
}
|
|
5881
|
+
await new Promise((resolve, reject) => {
|
|
5882
|
+
const cmd = argv[0];
|
|
5883
|
+
if (!cmd) {
|
|
5884
|
+
reject(new Error(`${options.label} command must not be empty.`));
|
|
5885
|
+
return;
|
|
5886
|
+
}
|
|
5887
|
+
const args = argv.slice(1);
|
|
5888
|
+
const child = spawn(cmd, args, {
|
|
5889
|
+
cwd: options.cwd,
|
|
5890
|
+
env: options.env ? { ...process.env, ...options.env } : process.env,
|
|
5891
|
+
stdio: "inherit"
|
|
5892
|
+
});
|
|
5893
|
+
let completed = false;
|
|
5894
|
+
const timeout = options.timeoutMs !== void 0 ? setTimeout(() => {
|
|
5895
|
+
if (!completed) {
|
|
5896
|
+
completed = true;
|
|
5897
|
+
child.kill("SIGKILL");
|
|
5898
|
+
reject(new Error(`${options.label} timed out after ${options.timeoutMs}ms`));
|
|
5899
|
+
}
|
|
5900
|
+
}, options.timeoutMs) : void 0;
|
|
5901
|
+
child.on("error", (error) => {
|
|
5902
|
+
if (completed) {
|
|
5903
|
+
return;
|
|
5904
|
+
}
|
|
5905
|
+
completed = true;
|
|
5906
|
+
if (timeout !== void 0) {
|
|
5907
|
+
clearTimeout(timeout);
|
|
5908
|
+
}
|
|
5909
|
+
reject(error);
|
|
5910
|
+
});
|
|
5911
|
+
child.on("exit", (code) => {
|
|
5912
|
+
if (completed) {
|
|
5913
|
+
return;
|
|
5914
|
+
}
|
|
5915
|
+
completed = true;
|
|
5916
|
+
if (timeout !== void 0) {
|
|
5917
|
+
clearTimeout(timeout);
|
|
5918
|
+
}
|
|
5919
|
+
if (code === 0) {
|
|
5920
|
+
resolve();
|
|
5921
|
+
} else {
|
|
5922
|
+
reject(new Error(`${options.label} exited with code ${code ?? "unknown"}`));
|
|
5923
|
+
}
|
|
5924
|
+
});
|
|
5925
|
+
});
|
|
5519
5926
|
}
|
|
5520
5927
|
function createProgressReporter(maxWorkers, options) {
|
|
5521
5928
|
const display = new ProgressDisplay(maxWorkers, options);
|
|
@@ -5529,7 +5936,7 @@ function createProgressReporter(maxWorkers, options) {
|
|
|
5529
5936
|
};
|
|
5530
5937
|
}
|
|
5531
5938
|
function makeTestCaseKey(testFilePath, testId) {
|
|
5532
|
-
return `${
|
|
5939
|
+
return `${path15.resolve(testFilePath)}::${testId}`;
|
|
5533
5940
|
}
|
|
5534
5941
|
function resolveTargetLabel(requestedName, resolvedName) {
|
|
5535
5942
|
if (resolvedName !== requestedName) {
|
|
@@ -5584,22 +5991,40 @@ function applyVerboseOverride(selection, cliVerbose) {
|
|
|
5584
5991
|
};
|
|
5585
5992
|
}
|
|
5586
5993
|
async function prepareFileMetadata(params) {
|
|
5587
|
-
const { testFilePath, repoRoot, cwd, options } = params;
|
|
5994
|
+
const { testFilePath, repoRoot, cwd, options, suiteFilter } = params;
|
|
5588
5995
|
await ensureFileExists(testFilePath, "Test file");
|
|
5589
5996
|
await loadEnvFromHierarchy({
|
|
5590
5997
|
testFilePath,
|
|
5591
5998
|
repoRoot,
|
|
5592
5999
|
verbose: options.verbose
|
|
5593
6000
|
});
|
|
5594
|
-
const relativePath =
|
|
6001
|
+
const relativePath = path15.relative(cwd, testFilePath);
|
|
5595
6002
|
const category = deriveCategory(relativePath);
|
|
5596
6003
|
const suite = await loadTestSuite(testFilePath, repoRoot, {
|
|
5597
6004
|
verbose: options.verbose,
|
|
5598
|
-
filter: options.filter,
|
|
6005
|
+
filter: suiteFilter ?? options.filter,
|
|
5599
6006
|
category
|
|
5600
6007
|
});
|
|
5601
|
-
const
|
|
6008
|
+
const testCases = suiteFilter && options.filter ? suite.tests.filter((testCase) => matchesTestFilter(testCase.id, options.filter ?? "")) : suite.tests;
|
|
6009
|
+
const testIds = testCases.map((value) => value.id);
|
|
5602
6010
|
const suiteTargets = suite.targets;
|
|
6011
|
+
if (testCases.length === 0) {
|
|
6012
|
+
return {
|
|
6013
|
+
testIds,
|
|
6014
|
+
testCases,
|
|
6015
|
+
selections: [],
|
|
6016
|
+
trialsConfig: options.experimentTrialsConfig,
|
|
6017
|
+
suiteTargets,
|
|
6018
|
+
yamlWorkers: suite.workers,
|
|
6019
|
+
yamlCache: suite.cacheConfig?.enabled,
|
|
6020
|
+
yamlCachePath: suite.cacheConfig?.cachePath,
|
|
6021
|
+
budgetUsd: suite.budgetUsd,
|
|
6022
|
+
failOnError: suite.failOnError,
|
|
6023
|
+
threshold: suite.threshold,
|
|
6024
|
+
tags: suite.metadata?.tags,
|
|
6025
|
+
providerFactory: suite.providerFactory
|
|
6026
|
+
};
|
|
6027
|
+
}
|
|
5603
6028
|
let selections;
|
|
5604
6029
|
if (options.transcript) {
|
|
5605
6030
|
const transcriptSelection = {
|
|
@@ -5616,7 +6041,7 @@ async function prepareFileMetadata(params) {
|
|
|
5616
6041
|
selections = [
|
|
5617
6042
|
{
|
|
5618
6043
|
selection: transcriptSelection,
|
|
5619
|
-
inlineTargetLabel: `transcript (${
|
|
6044
|
+
inlineTargetLabel: `transcript (${path15.basename(options.transcript)})`
|
|
5620
6045
|
}
|
|
5621
6046
|
];
|
|
5622
6047
|
} else if (suite.inlineTarget && options.cliTargets.length === 0) {
|
|
@@ -5671,15 +6096,20 @@ async function prepareFileMetadata(params) {
|
|
|
5671
6096
|
const cliTargets = options.cliTargets;
|
|
5672
6097
|
const suiteTargets2 = suite.targets;
|
|
5673
6098
|
const suiteTargetRefs = suite.targetRefs;
|
|
6099
|
+
const experimentTargetRefs = options.experimentTargetRefs;
|
|
5674
6100
|
let targetNames;
|
|
6101
|
+
let targetRefs;
|
|
5675
6102
|
if (cliTargets.length > 0) {
|
|
5676
6103
|
targetNames = cliTargets;
|
|
6104
|
+
targetRefs = experimentTargetRefs;
|
|
5677
6105
|
} else if (suiteTargets2 && suiteTargets2.length > 0) {
|
|
5678
6106
|
targetNames = suiteTargets2;
|
|
6107
|
+
targetRefs = suiteTargetRefs;
|
|
5679
6108
|
} else {
|
|
5680
6109
|
targetNames = [];
|
|
6110
|
+
targetRefs = void 0;
|
|
5681
6111
|
}
|
|
5682
|
-
if (targetNames.length > 1) {
|
|
6112
|
+
if (targetNames.length > 1 || targetNames.length === 1 && targetRefs) {
|
|
5683
6113
|
const multiSelections = await selectMultipleTargets({
|
|
5684
6114
|
testFilePath,
|
|
5685
6115
|
repoRoot,
|
|
@@ -5691,7 +6121,7 @@ async function prepareFileMetadata(params) {
|
|
|
5691
6121
|
dryRunDelayMax: options.dryRunDelayMax,
|
|
5692
6122
|
env: process.env,
|
|
5693
6123
|
targetNames,
|
|
5694
|
-
targetRefs
|
|
6124
|
+
targetRefs
|
|
5695
6125
|
});
|
|
5696
6126
|
selections = multiSelections.map((sel) => ({
|
|
5697
6127
|
selection: sel,
|
|
@@ -5710,9 +6140,7 @@ async function prepareFileMetadata(params) {
|
|
|
5710
6140
|
dryRunDelayMax: options.dryRunDelayMax,
|
|
5711
6141
|
env: process.env
|
|
5712
6142
|
});
|
|
5713
|
-
const singleTargetHooks =
|
|
5714
|
-
(ref) => ref.name === selection.targetName
|
|
5715
|
-
)?.hooks;
|
|
6143
|
+
const singleTargetHooks = targetRefs?.find((ref) => ref.name === selection.targetName)?.hooks;
|
|
5716
6144
|
const augmentedSelection = singleTargetHooks ? { ...selection, targetHooks: singleTargetHooks } : selection;
|
|
5717
6145
|
selections = [
|
|
5718
6146
|
{
|
|
@@ -5727,9 +6155,9 @@ async function prepareFileMetadata(params) {
|
|
|
5727
6155
|
}
|
|
5728
6156
|
return {
|
|
5729
6157
|
testIds,
|
|
5730
|
-
testCases
|
|
6158
|
+
testCases,
|
|
5731
6159
|
selections,
|
|
5732
|
-
trialsConfig:
|
|
6160
|
+
trialsConfig: options.experimentTrialsConfig,
|
|
5733
6161
|
suiteTargets,
|
|
5734
6162
|
yamlWorkers: suite.workers,
|
|
5735
6163
|
yamlCache: suite.cacheConfig?.enabled,
|
|
@@ -5782,7 +6210,7 @@ async function runSingleEvalFile(params) {
|
|
|
5782
6210
|
} = params;
|
|
5783
6211
|
const targetName = selection.targetName;
|
|
5784
6212
|
const replayRecording = options.recordReplay ? {
|
|
5785
|
-
fixturesPath:
|
|
6213
|
+
fixturesPath: path15.resolve(options.recordReplay),
|
|
5786
6214
|
sourceTarget: targetName,
|
|
5787
6215
|
variant: options.recordReplayVariant
|
|
5788
6216
|
} : void 0;
|
|
@@ -5926,7 +6354,7 @@ async function runEvalCommand(input) {
|
|
|
5926
6354
|
);
|
|
5927
6355
|
}
|
|
5928
6356
|
const repoRoot = await findRepoRoot(cwd);
|
|
5929
|
-
const yamlConfig = await loadConfig(
|
|
6357
|
+
const yamlConfig = await loadConfig(path15.join(cwd, "_"), repoRoot);
|
|
5930
6358
|
let requiredVersionCheck;
|
|
5931
6359
|
if (yamlConfig?.required_version) {
|
|
5932
6360
|
requiredVersionCheck = await enforceRequiredVersion(yamlConfig.required_version, {
|
|
@@ -5934,6 +6362,33 @@ async function runEvalCommand(input) {
|
|
|
5934
6362
|
});
|
|
5935
6363
|
}
|
|
5936
6364
|
let options = normalizeOptions(input.rawOptions, config, yamlConfig?.execution);
|
|
6365
|
+
const resolvedExperiment = await resolveExperimentForRun({
|
|
6366
|
+
cwd,
|
|
6367
|
+
explicitExperiment: options.experiment,
|
|
6368
|
+
yamlDefaultExperiment: resolveDefaultExperimentReference(yamlConfig),
|
|
6369
|
+
tsDefaultExperiment: normalizeTsDefaultExperiment(config)
|
|
6370
|
+
});
|
|
6371
|
+
options = {
|
|
6372
|
+
...applyExperimentOptions(options, resolvedExperiment.config),
|
|
6373
|
+
experiment: resolvedExperiment.name
|
|
6374
|
+
};
|
|
6375
|
+
const suiteSelection = await resolveExperimentSuiteSelection(
|
|
6376
|
+
options.experimentConfig?.suites,
|
|
6377
|
+
cwd
|
|
6378
|
+
);
|
|
6379
|
+
const evalPathInputs = input.testFiles.length > 0 ? [...input.testFiles] : suiteSelection ? [...suiteSelection.testFiles] : [];
|
|
6380
|
+
if (evalPathInputs.length === 0 && process.stdin.isTTY) {
|
|
6381
|
+
const { launchInteractiveWizard } = await import("./interactive-2WMVAASS.js");
|
|
6382
|
+
await launchInteractiveWizard();
|
|
6383
|
+
return void 0;
|
|
6384
|
+
}
|
|
6385
|
+
const resolvedTestFiles = await resolveEvalPaths(evalPathInputs, cwd);
|
|
6386
|
+
options = {
|
|
6387
|
+
...options,
|
|
6388
|
+
...suiteSelection !== void 0 && {
|
|
6389
|
+
suiteFiltersByEvalFile: suiteSelection.filtersByEvalFile
|
|
6390
|
+
}
|
|
6391
|
+
};
|
|
5937
6392
|
if (!process.env.AGENTV_EXPERIMENT) {
|
|
5938
6393
|
process.env.AGENTV_EXPERIMENT = normalizeExperimentName(options.experiment);
|
|
5939
6394
|
}
|
|
@@ -5962,7 +6417,7 @@ async function runEvalCommand(input) {
|
|
|
5962
6417
|
}
|
|
5963
6418
|
let retryNonErrorResults;
|
|
5964
6419
|
if (options.retryErrors) {
|
|
5965
|
-
const retryPath =
|
|
6420
|
+
const retryPath = path15.resolve(options.retryErrors);
|
|
5966
6421
|
await ensureFileExists(retryPath, "Retry-errors JSONL file");
|
|
5967
6422
|
const completedIds = await loadFullyCompletedTestIds(retryPath);
|
|
5968
6423
|
const errorIds = await loadErrorTestIds(retryPath);
|
|
@@ -5980,7 +6435,7 @@ async function runEvalCommand(input) {
|
|
|
5980
6435
|
if (cachedDir) {
|
|
5981
6436
|
options = { ...options, outputDir: cachedDir };
|
|
5982
6437
|
const flagLabel = options.rerunFailed ? "rerun-failed" : "resume";
|
|
5983
|
-
const displayDir =
|
|
6438
|
+
const displayDir = path15.relative(cwd, cachedDir) || cachedDir;
|
|
5984
6439
|
console.log(`Auto-detected last run dir for --${flagLabel}: ${displayDir}`);
|
|
5985
6440
|
}
|
|
5986
6441
|
}
|
|
@@ -5989,7 +6444,7 @@ async function runEvalCommand(input) {
|
|
|
5989
6444
|
if (options.resume && !options.retryErrors) {
|
|
5990
6445
|
const explicitResumeDir = options.outputDir;
|
|
5991
6446
|
if (explicitResumeDir) {
|
|
5992
|
-
const resumeIndexPath =
|
|
6447
|
+
const resumeIndexPath = path15.join(path15.resolve(explicitResumeDir), "index.jsonl");
|
|
5993
6448
|
if (existsSync7(resumeIndexPath)) {
|
|
5994
6449
|
const content = await readFile8(resumeIndexPath, "utf8");
|
|
5995
6450
|
const existingResults = parseJsonlResults(content);
|
|
@@ -6014,7 +6469,7 @@ async function runEvalCommand(input) {
|
|
|
6014
6469
|
}
|
|
6015
6470
|
}
|
|
6016
6471
|
if (options.workspacePath) {
|
|
6017
|
-
const resolvedWorkspace =
|
|
6472
|
+
const resolvedWorkspace = path15.resolve(options.workspacePath);
|
|
6018
6473
|
try {
|
|
6019
6474
|
const { stat: stat3 } = await import("node:fs/promises");
|
|
6020
6475
|
const stats = await stat3(resolvedWorkspace);
|
|
@@ -6037,22 +6492,22 @@ async function runEvalCommand(input) {
|
|
|
6037
6492
|
let outputPath;
|
|
6038
6493
|
const runDirName = process.env.AGENTV_RUN_TIMESTAMP?.trim() || createRunDirName();
|
|
6039
6494
|
if (explicitDir) {
|
|
6040
|
-
runDir =
|
|
6495
|
+
runDir = path15.resolve(explicitDir);
|
|
6041
6496
|
mkdirSync2(runDir, { recursive: true });
|
|
6042
|
-
outputPath =
|
|
6497
|
+
outputPath = path15.join(runDir, "index.jsonl");
|
|
6043
6498
|
} else {
|
|
6044
6499
|
outputPath = buildDefaultOutputPathForExperiment(cwd, options.experiment, runDirName);
|
|
6045
|
-
runDir =
|
|
6500
|
+
runDir = path15.dirname(outputPath);
|
|
6046
6501
|
}
|
|
6047
6502
|
if (!process.env.AGENTV_RUN_TIMESTAMP) {
|
|
6048
|
-
process.env.AGENTV_RUN_TIMESTAMP =
|
|
6503
|
+
process.env.AGENTV_RUN_TIMESTAMP = path15.basename(runDir);
|
|
6049
6504
|
}
|
|
6050
6505
|
process.env.AGENTV_RUN_DIR = runDir;
|
|
6051
6506
|
let otelExporter = null;
|
|
6052
6507
|
const useFileExport = !!options.otelFile;
|
|
6053
6508
|
if (options.exportOtel || useFileExport) {
|
|
6054
6509
|
try {
|
|
6055
|
-
const { OtelTraceExporter } = await import("./dist-
|
|
6510
|
+
const { OtelTraceExporter } = await import("./dist-KJ6PELQY.js");
|
|
6056
6511
|
let endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
6057
6512
|
let headers = {};
|
|
6058
6513
|
let resourceAttributes = {};
|
|
@@ -6085,7 +6540,7 @@ async function runEvalCommand(input) {
|
|
|
6085
6540
|
resourceAttributes,
|
|
6086
6541
|
captureContent,
|
|
6087
6542
|
groupTurns: options.otelGroupTurns,
|
|
6088
|
-
otlpFilePath: options.otelFile ?
|
|
6543
|
+
otlpFilePath: options.otelFile ? path15.resolve(options.otelFile) : void 0
|
|
6089
6544
|
});
|
|
6090
6545
|
const initialized = await otelExporter.init();
|
|
6091
6546
|
if (!initialized) {
|
|
@@ -6103,9 +6558,13 @@ async function runEvalCommand(input) {
|
|
|
6103
6558
|
}
|
|
6104
6559
|
const primaryWritePath = outputPath;
|
|
6105
6560
|
console.log(`Artifact directory: ${runDir}`);
|
|
6106
|
-
|
|
6561
|
+
await runExperimentSetup({
|
|
6562
|
+
config: options.experimentConfig,
|
|
6563
|
+
cwd,
|
|
6564
|
+
runDir
|
|
6565
|
+
});
|
|
6107
6566
|
if (options.otelFile) {
|
|
6108
|
-
console.log(`OTLP JSON file: ${
|
|
6567
|
+
console.log(`OTLP JSON file: ${path15.resolve(options.otelFile)}`);
|
|
6109
6568
|
}
|
|
6110
6569
|
const evaluationRunner = await resolveEvaluationRunner();
|
|
6111
6570
|
const allResults = [];
|
|
@@ -6123,7 +6582,8 @@ async function runEvalCommand(input) {
|
|
|
6123
6582
|
testFilePath,
|
|
6124
6583
|
repoRoot,
|
|
6125
6584
|
cwd,
|
|
6126
|
-
options
|
|
6585
|
+
options,
|
|
6586
|
+
suiteFilter: options.suiteFiltersByEvalFile?.get(path15.resolve(testFilePath))
|
|
6127
6587
|
});
|
|
6128
6588
|
fileMetadata.set(testFilePath, meta);
|
|
6129
6589
|
}
|
|
@@ -6133,7 +6593,7 @@ async function runEvalCommand(input) {
|
|
|
6133
6593
|
for (const [testFilePath, meta] of fileMetadata.entries()) {
|
|
6134
6594
|
if (!matchesTagFilters(meta.tags, options.tags, options.excludeTags)) {
|
|
6135
6595
|
fileMetadata.delete(testFilePath);
|
|
6136
|
-
skippedFiles.push(
|
|
6596
|
+
skippedFiles.push(path15.relative(cwd, testFilePath));
|
|
6137
6597
|
}
|
|
6138
6598
|
}
|
|
6139
6599
|
if (skippedFiles.length > 0 && options.verbose) {
|
|
@@ -6156,12 +6616,12 @@ async function runEvalCommand(input) {
|
|
|
6156
6616
|
tsConfigCache: options.tsConfigCache
|
|
6157
6617
|
});
|
|
6158
6618
|
const activeCachePath = options.cachePath ?? yamlCachePath ?? options.tsConfigCachePath;
|
|
6159
|
-
const cache = cacheEnabled ? new ResponseCache(activeCachePath ?
|
|
6619
|
+
const cache = cacheEnabled ? new ResponseCache(activeCachePath ? path15.resolve(activeCachePath) : void 0) : void 0;
|
|
6160
6620
|
if (cache) {
|
|
6161
6621
|
console.log(`Response cache: enabled (${cache.cachePath})`);
|
|
6162
6622
|
}
|
|
6163
6623
|
if (options.recordReplay) {
|
|
6164
|
-
console.log(`Replay recording: ${
|
|
6624
|
+
console.log(`Replay recording: ${path15.resolve(options.recordReplay)}`);
|
|
6165
6625
|
}
|
|
6166
6626
|
const yamlThreshold = firstMeta?.threshold;
|
|
6167
6627
|
const resolvedThreshold = options.threshold ?? yamlThreshold;
|
|
@@ -6257,7 +6717,7 @@ async function runEvalCommand(input) {
|
|
|
6257
6717
|
const activeTestFiles = resolvedTestFiles.filter((f) => fileMetadata.has(f));
|
|
6258
6718
|
let transcriptProviderFactory;
|
|
6259
6719
|
if (options.transcript) {
|
|
6260
|
-
const { TranscriptProvider } = await import("./dist-
|
|
6720
|
+
const { TranscriptProvider } = await import("./dist-KJ6PELQY.js");
|
|
6261
6721
|
const transcriptProvider = await TranscriptProvider.fromFile(options.transcript);
|
|
6262
6722
|
const totalTests = [...fileMetadata.values()].reduce(
|
|
6263
6723
|
(sum, meta) => sum + meta.testCases.length,
|
|
@@ -6275,10 +6735,11 @@ async function runEvalCommand(input) {
|
|
|
6275
6735
|
}
|
|
6276
6736
|
if (!isResumeAppend && totalEvalCount > 0) {
|
|
6277
6737
|
const evalFile = activeTestFiles.length === 1 ? activeTestFiles[0] : "";
|
|
6278
|
-
await
|
|
6738
|
+
await writeInitialRunSummaryArtifact(runDir, {
|
|
6279
6739
|
evalFile,
|
|
6280
6740
|
plannedTestCount: totalEvalCount,
|
|
6281
|
-
experiment: normalizeExperimentName(options.experiment)
|
|
6741
|
+
experiment: normalizeExperimentName(options.experiment),
|
|
6742
|
+
experimentMetadata: options.experimentMetadata
|
|
6282
6743
|
});
|
|
6283
6744
|
}
|
|
6284
6745
|
let wipLoop;
|
|
@@ -6306,7 +6767,7 @@ async function runEvalCommand(input) {
|
|
|
6306
6767
|
if (!targetPrep2) continue;
|
|
6307
6768
|
const budgetMsg = `Run budget exceeded ($${runBudgetTracker.currentCostUsd.toFixed(4)} / $${runBudgetTracker.budgetCapUsd.toFixed(4)})`;
|
|
6308
6769
|
console.log(`
|
|
6309
|
-
\u26A0 ${budgetMsg} \u2014 skipping ${
|
|
6770
|
+
\u26A0 ${budgetMsg} \u2014 skipping ${path15.basename(testFilePath)}`);
|
|
6310
6771
|
for (const { selection } of targetPrep2.selections) {
|
|
6311
6772
|
const skippedResults = targetPrep2.testCases.map((testCase) => ({
|
|
6312
6773
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -6385,7 +6846,7 @@ async function runEvalCommand(input) {
|
|
|
6385
6846
|
threshold: resolvedThreshold,
|
|
6386
6847
|
providerFactory: transcriptProviderFactory ?? targetPrep.providerFactory
|
|
6387
6848
|
});
|
|
6388
|
-
const evalFile =
|
|
6849
|
+
const evalFile = path15.relative(cwd, testFilePath);
|
|
6389
6850
|
const existingSummary = remoteEvalSummaries.find(
|
|
6390
6851
|
(summary2) => summary2.evalFile === evalFile
|
|
6391
6852
|
);
|
|
@@ -6402,7 +6863,7 @@ async function runEvalCommand(input) {
|
|
|
6402
6863
|
const message = fileError instanceof Error ? fileError.message : String(fileError);
|
|
6403
6864
|
console.error(
|
|
6404
6865
|
`
|
|
6405
|
-
[ERROR] \u26A0 Eval file failed: ${
|
|
6866
|
+
[ERROR] \u26A0 Eval file failed: ${path15.basename(testFilePath)} \u2014 ${message}
|
|
6406
6867
|
`
|
|
6407
6868
|
);
|
|
6408
6869
|
const errorResults = filteredTestCases.map(
|
|
@@ -6481,7 +6942,7 @@ ${formatRequiredVersionFailureNote(requiredVersionCheck)}`);
|
|
|
6481
6942
|
);
|
|
6482
6943
|
const taskBundleTargets = buildTaskBundleTargetSelections(activeTestFiles, fileMetadata);
|
|
6483
6944
|
if (isResumeAppend) {
|
|
6484
|
-
const { writePerTestArtifacts } = await import("./artifact-writer-
|
|
6945
|
+
const { writePerTestArtifacts } = await import("./artifact-writer-QD52FC56.js");
|
|
6485
6946
|
await writePerTestArtifacts(allResults, runDir, {
|
|
6486
6947
|
experiment: normalizeExperimentName(options.experiment),
|
|
6487
6948
|
cwd,
|
|
@@ -6489,37 +6950,36 @@ ${formatRequiredVersionFailureNote(requiredVersionCheck)}`);
|
|
|
6489
6950
|
sourceTests,
|
|
6490
6951
|
taskBundleTargets
|
|
6491
6952
|
});
|
|
6492
|
-
const {
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6953
|
+
const { summaryPath } = await aggregateRunDir(runDir, {
|
|
6954
|
+
evalFile,
|
|
6955
|
+
experiment: normalizeExperimentName(options.experiment),
|
|
6956
|
+
experimentMetadata: options.experimentMetadata
|
|
6957
|
+
});
|
|
6958
|
+
const indexPath = path15.join(runDir, "index.jsonl");
|
|
6497
6959
|
console.log(`Artifact workspace updated: ${runDir}`);
|
|
6498
6960
|
console.log(` Index: ${indexPath}`);
|
|
6499
6961
|
console.log(` Per-test artifacts: ${runDir} (${allResults.length} new test directories)`);
|
|
6500
|
-
console.log(`
|
|
6501
|
-
console.log(` Benchmark: ${workspaceBenchmarkPath}`);
|
|
6962
|
+
console.log(` Summary: ${summaryPath}`);
|
|
6502
6963
|
} else {
|
|
6503
|
-
const {
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6964
|
+
const { testArtifactDir, summaryPath, indexPath } = await writeArtifactsFromResults(
|
|
6965
|
+
allResults,
|
|
6966
|
+
runDir,
|
|
6967
|
+
{
|
|
6968
|
+
evalFile,
|
|
6969
|
+
experiment: normalizeExperimentName(options.experiment),
|
|
6970
|
+
experimentMetadata: options.experimentMetadata,
|
|
6971
|
+
cwd,
|
|
6972
|
+
repoRoot,
|
|
6973
|
+
sourceTests,
|
|
6974
|
+
taskBundleTargets
|
|
6975
|
+
}
|
|
6976
|
+
);
|
|
6516
6977
|
console.log(`Artifact workspace written to: ${runDir}`);
|
|
6517
6978
|
console.log(` Index: ${indexPath}`);
|
|
6518
6979
|
console.log(
|
|
6519
6980
|
` Per-test artifacts: ${testArtifactDir} (${allResults.length} test directories)`
|
|
6520
6981
|
);
|
|
6521
|
-
console.log(`
|
|
6522
|
-
console.log(` Benchmark: ${workspaceBenchmarkPath}`);
|
|
6982
|
+
console.log(` Summary: ${summaryPath}`);
|
|
6523
6983
|
}
|
|
6524
6984
|
}
|
|
6525
6985
|
const resultsWithWorkspaces = allResults.filter((r) => r.workspacePath);
|
|
@@ -6559,9 +7019,9 @@ Results written to: ${outputPath}`);
|
|
|
6559
7019
|
});
|
|
6560
7020
|
}
|
|
6561
7021
|
if (summary.executionErrorCount > 0 && !options.retryErrors && !options.resume) {
|
|
6562
|
-
const evalFileArgs = activeTestFiles.map((f) =>
|
|
7022
|
+
const evalFileArgs = activeTestFiles.map((f) => path15.relative(cwd, f)).join(" ");
|
|
6563
7023
|
const targetFlag = options.target ? ` --target ${options.target}` : "";
|
|
6564
|
-
const relativeRunDir =
|
|
7024
|
+
const relativeRunDir = path15.relative(cwd, runDir);
|
|
6565
7025
|
console.log(
|
|
6566
7026
|
`
|
|
6567
7027
|
Tip: ${summary.executionErrorCount} execution error(s) detected. Re-run failed tests with:
|
|
@@ -6579,6 +7039,12 @@ Tip: ${summary.executionErrorCount} execution error(s) detected. Re-run failed t
|
|
|
6579
7039
|
wipCleanedUp = true;
|
|
6580
7040
|
await wipLoop.stopAndDeleteWipBranch();
|
|
6581
7041
|
}
|
|
7042
|
+
await runExperimentSteps({
|
|
7043
|
+
label: "script",
|
|
7044
|
+
steps: options.experimentConfig?.scripts,
|
|
7045
|
+
cwd,
|
|
7046
|
+
experimentConfig: options.experimentConfig
|
|
7047
|
+
});
|
|
6582
7048
|
return {
|
|
6583
7049
|
executionErrorCount: summary.executionErrorCount,
|
|
6584
7050
|
outputPath,
|
|
@@ -6610,7 +7076,7 @@ async function resolveEvaluationRunner() {
|
|
|
6610
7076
|
if (!overridePath) {
|
|
6611
7077
|
return runEvaluation;
|
|
6612
7078
|
}
|
|
6613
|
-
const resolved =
|
|
7079
|
+
const resolved = path15.isAbsolute(overridePath) ? overridePath : path15.resolve(process.cwd(), overridePath);
|
|
6614
7080
|
const moduleUrl = pathToFileURL2(resolved).href;
|
|
6615
7081
|
const mod = await import(moduleUrl);
|
|
6616
7082
|
const candidate = mod.runEvaluation;
|
|
@@ -6622,43 +7088,6 @@ async function resolveEvaluationRunner() {
|
|
|
6622
7088
|
return candidate;
|
|
6623
7089
|
}
|
|
6624
7090
|
|
|
6625
|
-
// src/commands/eval/discover.ts
|
|
6626
|
-
import path15 from "node:path";
|
|
6627
|
-
import fg2 from "fast-glob";
|
|
6628
|
-
async function discoverEvalFiles(cwd) {
|
|
6629
|
-
const repoRoot = await findRepoRoot(cwd);
|
|
6630
|
-
const config = await loadConfig(path15.join(cwd, "_"), repoRoot);
|
|
6631
|
-
const patterns = config?.eval_patterns && config.eval_patterns.length > 0 ? config.eval_patterns : DEFAULT_EVAL_PATTERNS;
|
|
6632
|
-
const ignore = ["**/node_modules/**", "**/dist/**"];
|
|
6633
|
-
const matches = await fg2(patterns, {
|
|
6634
|
-
cwd,
|
|
6635
|
-
absolute: true,
|
|
6636
|
-
onlyFiles: true,
|
|
6637
|
-
ignore,
|
|
6638
|
-
followSymbolicLinks: true,
|
|
6639
|
-
caseSensitiveMatch: false
|
|
6640
|
-
});
|
|
6641
|
-
const evalFiles = matches.map((absPath) => {
|
|
6642
|
-
const relativePath = path15.relative(cwd, absPath);
|
|
6643
|
-
const category = deriveCategory(relativePath);
|
|
6644
|
-
return { path: absPath, relativePath, category };
|
|
6645
|
-
});
|
|
6646
|
-
evalFiles.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
6647
|
-
return evalFiles;
|
|
6648
|
-
}
|
|
6649
|
-
function getCategories(files) {
|
|
6650
|
-
const categories = /* @__PURE__ */ new Set();
|
|
6651
|
-
for (const file of files) {
|
|
6652
|
-
categories.add(file.category);
|
|
6653
|
-
}
|
|
6654
|
-
const sorted = Array.from(categories);
|
|
6655
|
-
sorted.sort();
|
|
6656
|
-
return sorted;
|
|
6657
|
-
}
|
|
6658
|
-
function filterByCategory(files, category) {
|
|
6659
|
-
return files.filter((f) => f.category === category);
|
|
6660
|
-
}
|
|
6661
|
-
|
|
6662
7091
|
export {
|
|
6663
7092
|
resolveEvalPaths,
|
|
6664
7093
|
findRepoRoot,
|
|
@@ -6714,6 +7143,7 @@ export {
|
|
|
6714
7143
|
isRemoteRunId,
|
|
6715
7144
|
getRemoteResultsStatus,
|
|
6716
7145
|
syncRemoteResults,
|
|
7146
|
+
confirmRemoteResultsMerge,
|
|
6717
7147
|
listMergedResultFiles,
|
|
6718
7148
|
findRunById,
|
|
6719
7149
|
ensureRemoteRunAvailable,
|
|
@@ -6723,9 +7153,9 @@ export {
|
|
|
6723
7153
|
maybeAutoExportRunArtifacts,
|
|
6724
7154
|
resolveRunCacheFile,
|
|
6725
7155
|
loadRunCache,
|
|
6726
|
-
runEvalCommand,
|
|
6727
7156
|
discoverEvalFiles,
|
|
6728
7157
|
getCategories,
|
|
6729
|
-
filterByCategory
|
|
7158
|
+
filterByCategory,
|
|
7159
|
+
runEvalCommand
|
|
6730
7160
|
};
|
|
6731
|
-
//# sourceMappingURL=chunk-
|
|
7161
|
+
//# sourceMappingURL=chunk-IBI7A5RP.js.map
|