agentv 4.43.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.
Files changed (53) hide show
  1. package/README.md +2 -2
  2. package/dist/{artifact-writer-STR7E5UO.js → artifact-writer-QD52FC56.js} +12 -10
  3. package/dist/{chunk-E2NL57MZ.js → chunk-6JVM4GJI.js} +3 -2
  4. package/dist/chunk-6JVM4GJI.js.map +1 -0
  5. package/dist/{chunk-IFQXBQSY.js → chunk-6Q56CEXV.js} +333 -99
  6. package/dist/chunk-6Q56CEXV.js.map +1 -0
  7. package/dist/{chunk-RFJM2UBD.js → chunk-GZJMODLW.js} +1067 -669
  8. package/dist/chunk-GZJMODLW.js.map +1 -0
  9. package/dist/{chunk-ROLNQBYU.js → chunk-IBI7A5RP.js} +621 -191
  10. package/dist/chunk-IBI7A5RP.js.map +1 -0
  11. package/dist/{chunk-NPVGBFF6.js → chunk-IJEZFZJR.js} +2 -43
  12. package/dist/chunk-IJEZFZJR.js.map +1 -0
  13. package/dist/{chunk-BPGJ4HBU.js → chunk-RCIEHFQ2.js} +3 -3
  14. package/dist/{chunk-5NDSGGMJ.js → chunk-UG4JHZYM.js} +1176 -224
  15. package/dist/chunk-UG4JHZYM.js.map +1 -0
  16. package/dist/cli.js +7 -7
  17. package/dist/dashboard/assets/index-BVMrdN8a.js +119 -0
  18. package/dist/dashboard/assets/{index-DitffAxS.js → index-D5_8DE_B.js} +1 -1
  19. package/dist/dashboard/assets/index-DZWXfWsv.css +1 -0
  20. package/dist/dashboard/index.html +2 -2
  21. package/dist/{dist-FTTL5IOY.js → dist-KJ6PELQY.js} +45 -11
  22. package/dist/{docker-workspace-RPPXBT27-B4AQHVWA.js → docker-workspace-ZJ2ESVBI-6UDETQII.js} +2 -2
  23. package/dist/{exec-AR6JUUN5-6MBPURPR.js → exec-MYPAJJP7-C5HD5WG5.js} +2 -2
  24. package/dist/index.js +7 -7
  25. package/dist/{interactive-RE4DXH4A.js → interactive-2WMVAASS.js} +7 -7
  26. package/dist/skills/agentv-bench/SKILL.md +3 -3
  27. package/dist/skills/agentv-bench/agents/analyzer.md +1 -1
  28. package/dist/skills/agentv-bench/references/autoresearch.md +1 -1
  29. package/dist/skills/agentv-bench/references/eval-yaml-spec.md +13 -3
  30. package/dist/skills/agentv-bench/references/migrating-from-skill-creator.md +2 -2
  31. package/dist/skills/agentv-bench/references/schemas.md +6 -6
  32. package/dist/skills/agentv-bench/references/subagent-pipeline.md +1 -1
  33. package/dist/skills/agentv-eval-writer/SKILL.md +11 -1
  34. package/dist/skills/agentv-eval-writer/references/config-schema.json +16 -0
  35. package/dist/skills/agentv-eval-writer/references/eval-schema.json +3 -63
  36. package/dist/skills/agentv-eval-writer/references/experiment-schema.json +278 -0
  37. package/dist/{ts-eval-loader-HQDMXQQV-LBW3N3W6.js → ts-eval-loader-RE43OAGX-AMRCUKBZ.js} +3 -3
  38. package/package.json +1 -1
  39. package/dist/chunk-5NDSGGMJ.js.map +0 -1
  40. package/dist/chunk-E2NL57MZ.js.map +0 -1
  41. package/dist/chunk-IFQXBQSY.js.map +0 -1
  42. package/dist/chunk-NPVGBFF6.js.map +0 -1
  43. package/dist/chunk-RFJM2UBD.js.map +0 -1
  44. package/dist/chunk-ROLNQBYU.js.map +0 -1
  45. package/dist/dashboard/assets/index-1Hvy8sBy.js +0 -119
  46. package/dist/dashboard/assets/index-J5sPcQO3.css +0 -1
  47. /package/dist/{artifact-writer-STR7E5UO.js.map → artifact-writer-QD52FC56.js.map} +0 -0
  48. /package/dist/{chunk-BPGJ4HBU.js.map → chunk-RCIEHFQ2.js.map} +0 -0
  49. /package/dist/{dist-FTTL5IOY.js.map → dist-KJ6PELQY.js.map} +0 -0
  50. /package/dist/{docker-workspace-RPPXBT27-B4AQHVWA.js.map → docker-workspace-ZJ2ESVBI-6UDETQII.js.map} +0 -0
  51. /package/dist/{exec-AR6JUUN5-6MBPURPR.js.map → exec-MYPAJJP7-C5HD5WG5.js.map} +0 -0
  52. /package/dist/{interactive-RE4DXH4A.js.map → interactive-2WMVAASS.js.map} +0 -0
  53. /package/dist/{ts-eval-loader-HQDMXQQV-LBW3N3W6.js.map → ts-eval-loader-RE43OAGX-AMRCUKBZ.js.map} +0 -0
@@ -2,7 +2,7 @@ import { createRequire } from 'node:module'; const require = createRequire(impor
2
2
  import {
3
3
  execFileWithStdin,
4
4
  execShellWithStdin
5
- } from "./chunk-NPVGBFF6.js";
5
+ } from "./chunk-IJEZFZJR.js";
6
6
  import {
7
7
  AgentvProvider,
8
8
  AnthropicProvider,
@@ -493,8 +493,8 @@ function getErrorMap() {
493
493
 
494
494
  // ../../node_modules/.bun/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
495
495
  var makeIssue = (params) => {
496
- const { data, path: path53, errorMaps, issueData } = params;
497
- const fullPath = [...path53, ...issueData.path || []];
496
+ const { data, path: path51, errorMaps, issueData } = params;
497
+ const fullPath = [...path51, ...issueData.path || []];
498
498
  const fullIssue = {
499
499
  ...issueData,
500
500
  path: fullPath
@@ -610,11 +610,11 @@ var errorUtil;
610
610
 
611
611
  // ../../node_modules/.bun/zod@3.25.76/node_modules/zod/v3/types.js
612
612
  var ParseInputLazyPath = class {
613
- constructor(parent, value, path53, key) {
613
+ constructor(parent, value, path51, key) {
614
614
  this._cachedPath = [];
615
615
  this.parent = parent;
616
616
  this.data = value;
617
- this._path = path53;
617
+ this._path = path51;
618
618
  this._key = key;
619
619
  }
620
620
  get path() {
@@ -4056,19 +4056,26 @@ var coerce = {
4056
4056
  };
4057
4057
  var NEVER = INVALID;
4058
4058
 
4059
- // ../../packages/core/dist/chunk-WSIPYTCH.js
4059
+ // ../../packages/core/dist/chunk-LP6SQKR3.js
4060
4060
  import { parse } from "yaml";
4061
- import os from "node:os";
4062
4061
  import path from "node:path";
4062
+ import os from "node:os";
4063
+ import path2 from "node:path";
4063
4064
  import { constants } from "node:fs";
4064
4065
  import { access, readFile } from "node:fs/promises";
4065
- import path2 from "node:path";
4066
+ import path3 from "node:path";
4066
4067
  import { existsSync, readFileSync } from "node:fs";
4067
4068
  import { homedir } from "node:os";
4068
- import path3 from "node:path";
4069
- import { readFile as readFile2, readdir, stat } from "node:fs/promises";
4070
4069
  import path4 from "node:path";
4070
+ import { readFile as readFile2, readdir, stat } from "node:fs/promises";
4071
+ import path5 from "node:path";
4071
4072
  import fg from "fast-glob";
4073
+ import { constants as constants2 } from "node:fs";
4074
+ import { access as access2 } from "node:fs/promises";
4075
+ import path6 from "node:path";
4076
+ import { fileURLToPath } from "node:url";
4077
+ import { readFile as readFile3 } from "node:fs/promises";
4078
+ import path7 from "node:path";
4072
4079
  var CONTENT_TYPES = /* @__PURE__ */ new Set(["text", "image", "file"]);
4073
4080
  function isContent(value) {
4074
4081
  if (!value || typeof value !== "object") return false;
@@ -4171,13 +4178,40 @@ var PARSE_OPTIONS = { merge: true };
4171
4178
  function parseYamlValue(content) {
4172
4179
  return parse(content, PARSE_OPTIONS);
4173
4180
  }
4181
+ var AGENTV_CONFIG_FILE_NAME = "config.yaml";
4182
+ var AGENTV_CONFIG_YML_FILE_NAME = "config.yml";
4183
+ var AGENTV_LOCAL_CONFIG_FILE_NAME = "config.local.yaml";
4184
+ var AGENTV_LOCAL_CONFIG_YML_FILE_NAME = "config.local.yml";
4185
+ function getLocalConfigPath(configPath2) {
4186
+ const basename = path.basename(configPath2);
4187
+ const localName = basename === AGENTV_CONFIG_YML_FILE_NAME ? AGENTV_LOCAL_CONFIG_YML_FILE_NAME : AGENTV_LOCAL_CONFIG_FILE_NAME;
4188
+ return path.join(path.dirname(configPath2), localName);
4189
+ }
4190
+ function isAgentVConfigFileName(basename) {
4191
+ return basename === AGENTV_CONFIG_FILE_NAME || basename === AGENTV_CONFIG_YML_FILE_NAME || basename === AGENTV_LOCAL_CONFIG_FILE_NAME || basename === AGENTV_LOCAL_CONFIG_YML_FILE_NAME;
4192
+ }
4193
+ function isPlainConfigObject(value) {
4194
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
4195
+ return false;
4196
+ }
4197
+ const prototype = Object.getPrototypeOf(value);
4198
+ return prototype === Object.prototype || prototype === null;
4199
+ }
4200
+ function mergeConfigObjects(base, overlay) {
4201
+ const merged = { ...base };
4202
+ for (const [key, overlayValue] of Object.entries(overlay)) {
4203
+ const baseValue = merged[key];
4204
+ merged[key] = isPlainConfigObject(baseValue) && isPlainConfigObject(overlayValue) ? mergeConfigObjects(baseValue, overlayValue) : overlayValue;
4205
+ }
4206
+ return merged;
4207
+ }
4174
4208
  function readEnvPath(name) {
4175
4209
  const value = process.env[name];
4176
4210
  if (!value || value === "undefined") return void 0;
4177
4211
  return value;
4178
4212
  }
4179
4213
  function getAgentvConfigDir() {
4180
- return readEnvPath("AGENTV_HOME") ?? path.join(os.homedir(), ".agentv");
4214
+ return readEnvPath("AGENTV_HOME") ?? path2.join(os.homedir(), ".agentv");
4181
4215
  }
4182
4216
  function getAgentvHome() {
4183
4217
  return getAgentvConfigDir();
@@ -4186,16 +4220,16 @@ function getAgentvDataDir() {
4186
4220
  return readEnvPath("AGENTV_DATA_DIR") ?? getAgentvConfigDir();
4187
4221
  }
4188
4222
  function getWorkspacesRoot() {
4189
- return path.join(getAgentvDataDir(), "workspaces");
4223
+ return path2.join(getAgentvDataDir(), "workspaces");
4190
4224
  }
4191
4225
  function getSubagentsRoot() {
4192
- return path.join(getAgentvDataDir(), "subagents");
4226
+ return path2.join(getAgentvDataDir(), "subagents");
4193
4227
  }
4194
4228
  function getTraceStateRoot() {
4195
- return path.join(getAgentvDataDir(), "trace-state");
4229
+ return path2.join(getAgentvDataDir(), "trace-state");
4196
4230
  }
4197
4231
  function getWorkspacePoolRoot() {
4198
- return path.join(getAgentvDataDir(), "workspace-pool");
4232
+ return path2.join(getAgentvDataDir(), "workspace-pool");
4199
4233
  }
4200
4234
  async function fileExists(filePath) {
4201
4235
  try {
@@ -4217,14 +4251,14 @@ async function readJsonFile(filePath) {
4217
4251
  return JSON.parse(content);
4218
4252
  }
4219
4253
  async function findGitRoot(startPath) {
4220
- let currentDir = path2.dirname(path2.resolve(startPath));
4221
- const root = path2.parse(currentDir).root;
4254
+ let currentDir = path3.dirname(path3.resolve(startPath));
4255
+ const root = path3.parse(currentDir).root;
4222
4256
  while (currentDir !== root) {
4223
- const gitPath = path2.join(currentDir, ".git");
4257
+ const gitPath = path3.join(currentDir, ".git");
4224
4258
  if (await fileExists(gitPath)) {
4225
4259
  return currentDir;
4226
4260
  }
4227
- const parentDir = path2.dirname(currentDir);
4261
+ const parentDir = path3.dirname(currentDir);
4228
4262
  if (parentDir === currentDir) {
4229
4263
  break;
4230
4264
  }
@@ -4235,8 +4269,8 @@ async function findGitRoot(startPath) {
4235
4269
  function buildDirectoryChain(filePath, repoRoot) {
4236
4270
  const directories = [];
4237
4271
  const seen = /* @__PURE__ */ new Set();
4238
- const boundary = path2.resolve(repoRoot);
4239
- let current = path2.resolve(path2.dirname(filePath));
4272
+ const boundary = path3.resolve(repoRoot);
4273
+ let current = path3.resolve(path3.dirname(filePath));
4240
4274
  while (current !== void 0) {
4241
4275
  if (!seen.has(current)) {
4242
4276
  directories.push(current);
@@ -4245,7 +4279,7 @@ function buildDirectoryChain(filePath, repoRoot) {
4245
4279
  if (current === boundary) {
4246
4280
  break;
4247
4281
  }
4248
- const parent = path2.dirname(current);
4282
+ const parent = path3.dirname(current);
4249
4283
  if (parent === current) {
4250
4284
  break;
4251
4285
  }
@@ -4259,16 +4293,16 @@ function buildDirectoryChain(filePath, repoRoot) {
4259
4293
  function buildSearchRoots(evalPath, repoRoot) {
4260
4294
  const uniqueRoots = [];
4261
4295
  const addRoot = (root) => {
4262
- const normalized = path2.resolve(root);
4296
+ const normalized = path3.resolve(root);
4263
4297
  if (!uniqueRoots.includes(normalized)) {
4264
4298
  uniqueRoots.push(normalized);
4265
4299
  }
4266
4300
  };
4267
- let currentDir = path2.dirname(evalPath);
4301
+ let currentDir = path3.dirname(evalPath);
4268
4302
  let reachedBoundary = false;
4269
4303
  while (!reachedBoundary) {
4270
4304
  addRoot(currentDir);
4271
- const parentDir = path2.dirname(currentDir);
4305
+ const parentDir = path3.dirname(currentDir);
4272
4306
  if (currentDir === repoRoot || parentDir === currentDir) {
4273
4307
  reachedBoundary = true;
4274
4308
  } else {
@@ -4286,16 +4320,16 @@ function trimLeadingSeparators(value) {
4286
4320
  async function resolveFileReference(rawValue, searchRoots) {
4287
4321
  const displayPath = trimLeadingSeparators(rawValue);
4288
4322
  const potentialPaths = [];
4289
- if (path2.isAbsolute(rawValue)) {
4290
- potentialPaths.push(path2.normalize(rawValue));
4323
+ if (path3.isAbsolute(rawValue)) {
4324
+ potentialPaths.push(path3.normalize(rawValue));
4291
4325
  }
4292
4326
  for (const base of searchRoots) {
4293
- potentialPaths.push(path2.resolve(base, displayPath));
4327
+ potentialPaths.push(path3.resolve(base, displayPath));
4294
4328
  }
4295
4329
  const attempted = [];
4296
4330
  const seen = /* @__PURE__ */ new Set();
4297
4331
  for (const candidate of potentialPaths) {
4298
- const absoluteCandidate = path2.resolve(candidate);
4332
+ const absoluteCandidate = path3.resolve(candidate);
4299
4333
  if (seen.has(absoluteCandidate)) {
4300
4334
  continue;
4301
4335
  }
@@ -4478,11 +4512,11 @@ function normalizeCliHealthcheck(input, env, targetName, evalFilePath) {
4478
4512
  allowLiteral: true,
4479
4513
  optionalEnv: true
4480
4514
  });
4481
- if (cwd && evalFilePath && !path3.isAbsolute(cwd)) {
4482
- cwd = path3.resolve(path3.dirname(path3.resolve(evalFilePath)), cwd);
4515
+ if (cwd && evalFilePath && !path4.isAbsolute(cwd)) {
4516
+ cwd = path4.resolve(path4.dirname(path4.resolve(evalFilePath)), cwd);
4483
4517
  }
4484
4518
  if (!cwd && evalFilePath) {
4485
- cwd = path3.dirname(path3.resolve(evalFilePath));
4519
+ cwd = path4.dirname(path4.resolve(evalFilePath));
4486
4520
  }
4487
4521
  return {
4488
4522
  command,
@@ -4499,11 +4533,11 @@ function normalizeCliTargetInput(input, env, evalFilePath) {
4499
4533
  allowLiteral: true,
4500
4534
  optionalEnv: true
4501
4535
  });
4502
- if (cwd && evalFilePath && !path3.isAbsolute(cwd)) {
4503
- cwd = path3.resolve(path3.dirname(path3.resolve(evalFilePath)), cwd);
4536
+ if (cwd && evalFilePath && !path4.isAbsolute(cwd)) {
4537
+ cwd = path4.resolve(path4.dirname(path4.resolve(evalFilePath)), cwd);
4504
4538
  }
4505
4539
  if (!cwd && evalFilePath) {
4506
- cwd = path3.dirname(path3.resolve(evalFilePath));
4540
+ cwd = path4.dirname(path4.resolve(evalFilePath));
4507
4541
  }
4508
4542
  const timeoutSeconds = input.timeout_seconds;
4509
4543
  const timeoutMs = timeoutSeconds !== void 0 ? Math.floor(timeoutSeconds * 1e3) : void 0;
@@ -5547,6 +5581,7 @@ function resolvePiCliConfig(target, env, _evalFilePath) {
5547
5581
  allowLiteral: true,
5548
5582
  optionalEnv: true
5549
5583
  });
5584
+ const piCliSubprovider = normalizePiCliSubprovider(subprovider, baseUrl);
5550
5585
  const tools = resolveOptionalString(toolsSource, env, `${target.name} pi-cli tools`, {
5551
5586
  allowLiteral: true,
5552
5587
  optionalEnv: true
@@ -5570,7 +5605,7 @@ function resolvePiCliConfig(target, env, _evalFilePath) {
5570
5605
  const systemPrompt = typeof systemPromptSource === "string" && systemPromptSource.trim().length > 0 ? systemPromptSource.trim() : void 0;
5571
5606
  return {
5572
5607
  executable,
5573
- subprovider,
5608
+ subprovider: piCliSubprovider,
5574
5609
  model,
5575
5610
  apiKey,
5576
5611
  baseUrl,
@@ -5585,6 +5620,13 @@ function resolvePiCliConfig(target, env, _evalFilePath) {
5585
5620
  systemPrompt
5586
5621
  };
5587
5622
  }
5623
+ function normalizePiCliSubprovider(subprovider, baseUrl) {
5624
+ if (!baseUrl) return subprovider;
5625
+ if (!subprovider || subprovider.toLowerCase() === "openai") {
5626
+ return "azure";
5627
+ }
5628
+ return subprovider;
5629
+ }
5588
5630
  function resolveClaudeConfig(target, env, _evalFilePath) {
5589
5631
  const executableSource = target.executable ?? target.command ?? target.binary;
5590
5632
  const modelSource = target.model;
@@ -5635,7 +5677,7 @@ function resolveClaudeConfig(target, env, _evalFilePath) {
5635
5677
  };
5636
5678
  }
5637
5679
  function resolveCcMirrorBinaryPath(variant) {
5638
- const variantJsonPath = path3.join(homedir(), ".cc-mirror", variant, "variant.json");
5680
+ const variantJsonPath = path4.join(homedir(), ".cc-mirror", variant, "variant.json");
5639
5681
  if (!existsSync(variantJsonPath)) {
5640
5682
  throw new Error(
5641
5683
  `cc-mirror variant "${variant}": ${variantJsonPath} not found. Install the variant or set "executable" explicitly.`
@@ -5721,7 +5763,7 @@ function resolveReplayConfig(target, env, evalFilePath) {
5721
5763
  };
5722
5764
  }
5723
5765
  function resolveReplaySourcePath(sourcePath, evalFilePath) {
5724
- return evalFilePath && !path3.isAbsolute(sourcePath) ? path3.resolve(path3.dirname(path3.resolve(evalFilePath)), sourcePath) : path3.resolve(sourcePath);
5766
+ return evalFilePath && !path4.isAbsolute(sourcePath) ? path4.resolve(path4.dirname(path4.resolve(evalFilePath)), sourcePath) : path4.resolve(sourcePath);
5725
5767
  }
5726
5768
  function resolveVSCodeConfig(target, env, insiders, _evalFilePath) {
5727
5769
  const executableSource = target.executable;
@@ -5762,8 +5804,8 @@ function resolveCliConfig(target, env, evalFilePath) {
5762
5804
  const parseResult = CliTargetInputSchema.safeParse(target, { errorMap: cliErrorMap });
5763
5805
  if (!parseResult.success) {
5764
5806
  const firstError = parseResult.error.errors[0];
5765
- const path53 = firstError?.path.join(".") || "";
5766
- const prefix = path53 ? `${target.name} ${path53}: ` : `${target.name}: `;
5807
+ const path83 = firstError?.path.join(".") || "";
5808
+ const prefix = path83 ? `${target.name} ${path83}: ` : `${target.name}: `;
5767
5809
  throw new Error(`${prefix}${firstError?.message}`);
5768
5810
  }
5769
5811
  const normalized = normalizeCliTargetInput(parseResult.data, env, evalFilePath);
@@ -5784,11 +5826,11 @@ function resolveDiscoveredProviderConfig(target, providerKind, env, evalFilePath
5784
5826
  allowLiteral: true,
5785
5827
  optionalEnv: true
5786
5828
  });
5787
- if (cwd && evalFilePath && !path3.isAbsolute(cwd)) {
5788
- cwd = path3.resolve(path3.dirname(path3.resolve(evalFilePath)), cwd);
5829
+ if (cwd && evalFilePath && !path4.isAbsolute(cwd)) {
5830
+ cwd = path4.resolve(path4.dirname(path4.resolve(evalFilePath)), cwd);
5789
5831
  }
5790
5832
  if (!cwd && evalFilePath) {
5791
- cwd = path3.dirname(path3.resolve(evalFilePath));
5833
+ cwd = path4.dirname(path4.resolve(evalFilePath));
5792
5834
  }
5793
5835
  return {
5794
5836
  command,
@@ -6142,7 +6184,7 @@ function parseJsonlCases(content, filePath) {
6142
6184
  return results;
6143
6185
  }
6144
6186
  async function loadCasesFromFile(filePath) {
6145
- const ext = path4.extname(filePath).toLowerCase();
6187
+ const ext = path5.extname(filePath).toLowerCase();
6146
6188
  let content;
6147
6189
  try {
6148
6190
  content = await readFile2(filePath, "utf8");
@@ -6169,7 +6211,7 @@ async function loadCasesFromFile(filePath) {
6169
6211
  }
6170
6212
  async function resolveFileReference2(ref, evalFileDir) {
6171
6213
  const rawPath = extractFilePath(ref);
6172
- const absolutePattern = path4.resolve(evalFileDir, rawPath);
6214
+ const absolutePattern = path5.resolve(evalFileDir, rawPath);
6173
6215
  if (isGlobPattern(rawPath)) {
6174
6216
  const matches = await fg(absolutePattern.replaceAll("\\", "/"), {
6175
6217
  onlyFiles: true,
@@ -6196,10 +6238,10 @@ async function loadCasesFromDirectory(dirPath) {
6196
6238
  const subdirs = entries.filter((e) => e.isDirectory()).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
6197
6239
  const results = [];
6198
6240
  for (const subdir of subdirs) {
6199
- const subdirPath = path4.join(dirPath, subdir.name);
6241
+ const subdirPath = path5.join(dirPath, subdir.name);
6200
6242
  let caseFilePath;
6201
6243
  for (const filename of ["case.yaml", "case.yml"]) {
6202
- const candidate = path4.join(subdirPath, filename);
6244
+ const candidate = path5.join(subdirPath, filename);
6203
6245
  try {
6204
6246
  const s = await stat(candidate);
6205
6247
  if (s.isFile()) {
@@ -6235,7 +6277,7 @@ async function loadCasesFromDirectory(dirPath) {
6235
6277
  caseObj.id = subdir.name;
6236
6278
  }
6237
6279
  if (!caseObj.workspace) {
6238
- const workspaceDirPath = path4.join(subdirPath, "workspace");
6280
+ const workspaceDirPath = path5.join(subdirPath, "workspace");
6239
6281
  try {
6240
6282
  const s = await stat(workspaceDirPath);
6241
6283
  if (s.isDirectory()) {
@@ -6260,18 +6302,172 @@ async function expandFileReferences(tests, evalFileDir) {
6260
6302
  }
6261
6303
  return expanded;
6262
6304
  }
6305
+ async function fileExists2(absolutePath) {
6306
+ try {
6307
+ await access2(absolutePath, constants2.F_OK);
6308
+ return true;
6309
+ } catch {
6310
+ return false;
6311
+ }
6312
+ }
6313
+ function resolveToAbsolutePath(candidate) {
6314
+ if (candidate instanceof URL) {
6315
+ return candidate.protocol === "file:" ? fileURLToPath(candidate) : candidate.pathname;
6316
+ }
6317
+ if (typeof candidate === "string") {
6318
+ if (candidate.startsWith("file:")) {
6319
+ return fileURLToPath(candidate);
6320
+ }
6321
+ return path6.resolve(candidate);
6322
+ }
6323
+ throw new TypeError("Unsupported repoRoot value. Expected string or URL.");
6324
+ }
6325
+ function buildDirectoryChain2(filePath, repoRoot) {
6326
+ const directories = [];
6327
+ const seen = /* @__PURE__ */ new Set();
6328
+ const boundary = path6.resolve(repoRoot);
6329
+ let current = path6.resolve(path6.dirname(filePath));
6330
+ while (current !== void 0) {
6331
+ if (!seen.has(current)) {
6332
+ directories.push(current);
6333
+ seen.add(current);
6334
+ }
6335
+ if (current === boundary) {
6336
+ break;
6337
+ }
6338
+ const parent = path6.dirname(current);
6339
+ if (parent === current) {
6340
+ break;
6341
+ }
6342
+ current = parent;
6343
+ }
6344
+ if (!seen.has(boundary)) {
6345
+ directories.push(boundary);
6346
+ }
6347
+ return directories;
6348
+ }
6349
+ function buildSearchRoots2(evalPath, repoRoot) {
6350
+ const uniqueRoots = [];
6351
+ const addRoot = (root) => {
6352
+ const normalized = path6.resolve(root);
6353
+ if (!uniqueRoots.includes(normalized)) {
6354
+ uniqueRoots.push(normalized);
6355
+ }
6356
+ };
6357
+ let currentDir = path6.dirname(evalPath);
6358
+ let reachedBoundary = false;
6359
+ while (!reachedBoundary) {
6360
+ addRoot(currentDir);
6361
+ const parentDir = path6.dirname(currentDir);
6362
+ if (currentDir === repoRoot || parentDir === currentDir) {
6363
+ reachedBoundary = true;
6364
+ } else {
6365
+ currentDir = parentDir;
6366
+ }
6367
+ }
6368
+ addRoot(repoRoot);
6369
+ addRoot(process.cwd());
6370
+ return uniqueRoots;
6371
+ }
6372
+ function trimLeadingSeparators2(value) {
6373
+ const trimmed = value.replace(/^[/\\]+/, "");
6374
+ return trimmed.length > 0 ? trimmed : value;
6375
+ }
6376
+ async function resolveFileReference3(rawValue, searchRoots) {
6377
+ const displayPath = trimLeadingSeparators2(rawValue);
6378
+ const potentialPaths = [];
6379
+ if (path6.isAbsolute(rawValue)) {
6380
+ potentialPaths.push(path6.normalize(rawValue));
6381
+ }
6382
+ for (const base of searchRoots) {
6383
+ potentialPaths.push(path6.resolve(base, displayPath));
6384
+ }
6385
+ const attempted = [];
6386
+ const seen = /* @__PURE__ */ new Set();
6387
+ for (const candidate of potentialPaths) {
6388
+ const absoluteCandidate = path6.resolve(candidate);
6389
+ if (seen.has(absoluteCandidate)) {
6390
+ continue;
6391
+ }
6392
+ seen.add(absoluteCandidate);
6393
+ attempted.push(absoluteCandidate);
6394
+ if (await fileExists2(absoluteCandidate)) {
6395
+ return { displayPath, resolvedPath: absoluteCandidate, attempted };
6396
+ }
6397
+ }
6398
+ return { displayPath, attempted };
6399
+ }
6400
+ var PROMPT_MD_FILENAME = "PROMPT.md";
6401
+ function asStringArray(value) {
6402
+ if (!Array.isArray(value)) {
6403
+ return void 0;
6404
+ }
6405
+ return value.filter((entry) => typeof entry === "string");
6406
+ }
6407
+ function basenameForPortablePath(value) {
6408
+ return value.split(/[\\/]/).at(-1) ?? value;
6409
+ }
6410
+ function isPromptMdPath(value) {
6411
+ return basenameForPortablePath(value) === PROMPT_MD_FILENAME;
6412
+ }
6413
+ function splitInputFiles(value) {
6414
+ const files = asStringArray(value);
6415
+ if (!files) {
6416
+ return {};
6417
+ }
6418
+ const promptFile = files.find(isPromptMdPath);
6419
+ const remaining = promptFile ? files.filter((file2) => !isPromptMdPath(file2)) : files;
6420
+ return {
6421
+ files,
6422
+ ...promptFile ? { promptFile } : {},
6423
+ ...remaining.length > 0 ? { remainingInputFiles: remaining } : {}
6424
+ };
6425
+ }
6426
+ async function readPromptFile(promptPath) {
6427
+ return (await readFile3(promptPath, "utf8")).replace(/\r\n/g, "\n");
6428
+ }
6429
+ async function loadPromptMdFallback(options) {
6430
+ const testSplit = splitInputFiles(options.testInputFiles);
6431
+ const suiteSplit = splitInputFiles(options.suiteInputFiles);
6432
+ const inputFilesSource = testSplit.files ? "test" : suiteSplit.files ? "suite" : void 0;
6433
+ const activeSplit = inputFilesSource === "test" ? testSplit : suiteSplit;
6434
+ if (activeSplit.promptFile) {
6435
+ const resolved = await resolveFileReference3(activeSplit.promptFile, options.searchRoots);
6436
+ if (resolved.resolvedPath) {
6437
+ return {
6438
+ promptText: await readPromptFile(resolved.resolvedPath),
6439
+ promptPath: path7.resolve(resolved.resolvedPath),
6440
+ source: "input_files",
6441
+ ...inputFilesSource ? { inputFilesSource } : {},
6442
+ ...activeSplit.remainingInputFiles ? { remainingInputFiles: activeSplit.remainingInputFiles } : {}
6443
+ };
6444
+ }
6445
+ }
6446
+ const siblingPromptPath = path7.join(
6447
+ path7.dirname(path7.resolve(options.evalFilePath)),
6448
+ PROMPT_MD_FILENAME
6449
+ );
6450
+ if (await fileExists2(siblingPromptPath)) {
6451
+ return {
6452
+ promptText: await readPromptFile(siblingPromptPath),
6453
+ promptPath: siblingPromptPath,
6454
+ source: "sibling"
6455
+ };
6456
+ }
6457
+ return void 0;
6458
+ }
6263
6459
 
6264
- // ../../packages/core/dist/chunk-5W7DQNEF.js
6265
- import path51 from "node:path";
6460
+ // ../../packages/core/dist/chunk-ZAXCSMNE.js
6461
+ import path50 from "node:path";
6266
6462
  import { pathToFileURL as pathToFileURL2 } from "node:url";
6267
6463
  import { existsSync as existsSync7 } from "node:fs";
6268
- import path50 from "node:path";
6464
+ import path49 from "node:path";
6269
6465
  import micromatch4 from "micromatch";
6270
- import { mkdir, readFile as readFile3, writeFile } from "node:fs/promises";
6271
- import path5 from "node:path";
6466
+ import { mkdir, readFile as readFile4, writeFile } from "node:fs/promises";
6467
+ import path8 from "node:path";
6272
6468
  import { createHash as createHash6, randomUUID as randomUUID10 } from "node:crypto";
6273
- import path48 from "node:path";
6274
- import { fileURLToPath as fileURLToPath5 } from "node:url";
6469
+ import path47 from "node:path";
6470
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
6275
6471
  import micromatch3 from "micromatch";
6276
6472
  import { mkdtemp, rm, writeFile as writeFile2 } from "node:fs/promises";
6277
6473
  import { tmpdir } from "node:os";
@@ -6282,22 +6478,22 @@ import fs from "node:fs/promises";
6282
6478
  import path32 from "node:path";
6283
6479
  import { readFile as readFile22 } from "node:fs/promises";
6284
6480
  import path22 from "node:path";
6285
- import { fileURLToPath } from "node:url";
6481
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
6286
6482
  import { spawn } from "node:child_process";
6287
6483
  import { randomUUID } from "node:crypto";
6288
6484
  import { createWriteStream } from "node:fs";
6289
6485
  import { mkdir as mkdir2 } from "node:fs/promises";
6290
- import path6 from "node:path";
6486
+ import path62 from "node:path";
6291
6487
  import path42 from "node:path";
6292
6488
  import path52 from "node:path";
6293
6489
  import { randomUUID as randomUUID2 } from "node:crypto";
6294
6490
  import { createWriteStream as createWriteStream2 } from "node:fs";
6295
6491
  import { mkdir as mkdir3 } from "node:fs/promises";
6296
- import path7 from "node:path";
6492
+ import path72 from "node:path";
6297
6493
  import { exec as execWithCallback } from "node:child_process";
6298
6494
  import fs2 from "node:fs/promises";
6299
6495
  import os2 from "node:os";
6300
- import path8 from "node:path";
6496
+ import path82 from "node:path";
6301
6497
  import { promisify } from "node:util";
6302
6498
  import { randomUUID as randomUUID3 } from "node:crypto";
6303
6499
  import { createWriteStream as createWriteStream3 } from "node:fs";
@@ -6990,10 +7186,10 @@ function assignProp(target, prop, value) {
6990
7186
  configurable: true
6991
7187
  });
6992
7188
  }
6993
- function getElementAtPath(obj, path53) {
6994
- if (!path53)
7189
+ function getElementAtPath(obj, path51) {
7190
+ if (!path51)
6995
7191
  return obj;
6996
- return path53.reduce((acc, key) => acc?.[key], obj);
7192
+ return path51.reduce((acc, key) => acc?.[key], obj);
6997
7193
  }
6998
7194
  function promiseAllObject(promisesObj) {
6999
7195
  const keys = Object.keys(promisesObj);
@@ -7313,11 +7509,11 @@ function aborted(x, startIndex = 0) {
7313
7509
  }
7314
7510
  return false;
7315
7511
  }
7316
- function prefixIssues(path53, issues) {
7512
+ function prefixIssues(path51, issues) {
7317
7513
  return issues.map((iss) => {
7318
7514
  var _a;
7319
7515
  (_a = iss).path ?? (_a.path = []);
7320
- iss.path.unshift(path53);
7516
+ iss.path.unshift(path51);
7321
7517
  return iss;
7322
7518
  });
7323
7519
  }
@@ -7454,7 +7650,7 @@ function treeifyError(error40, _mapper) {
7454
7650
  return issue2.message;
7455
7651
  };
7456
7652
  const result = { errors: [] };
7457
- const processError = (error41, path53 = []) => {
7653
+ const processError = (error41, path51 = []) => {
7458
7654
  var _a, _b;
7459
7655
  for (const issue2 of error41.issues) {
7460
7656
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -7464,7 +7660,7 @@ function treeifyError(error40, _mapper) {
7464
7660
  } else if (issue2.code === "invalid_element") {
7465
7661
  processError({ issues: issue2.issues }, issue2.path);
7466
7662
  } else {
7467
- const fullpath = [...path53, ...issue2.path];
7663
+ const fullpath = [...path51, ...issue2.path];
7468
7664
  if (fullpath.length === 0) {
7469
7665
  result.errors.push(mapper(issue2));
7470
7666
  continue;
@@ -7494,9 +7690,9 @@ function treeifyError(error40, _mapper) {
7494
7690
  processError(error40);
7495
7691
  return result;
7496
7692
  }
7497
- function toDotPath(path53) {
7693
+ function toDotPath(path51) {
7498
7694
  const segs = [];
7499
- for (const seg of path53) {
7695
+ for (const seg of path51) {
7500
7696
  if (typeof seg === "number")
7501
7697
  segs.push(`[${seg}]`);
7502
7698
  else if (typeof seg === "symbol")
@@ -18926,7 +19122,7 @@ var RequestError = class _RequestError extends Error {
18926
19122
  }
18927
19123
  };
18928
19124
 
18929
- // ../../packages/core/dist/chunk-5W7DQNEF.js
19125
+ // ../../packages/core/dist/chunk-ZAXCSMNE.js
18930
19126
  import { exec as execCallback } from "node:child_process";
18931
19127
  import { readdirSync, statSync } from "node:fs";
18932
19128
  import { readFile as readFile32, readdir as readdir2, stat as stat2 } from "node:fs/promises";
@@ -18936,11 +19132,11 @@ import { randomUUID as randomUUID4 } from "node:crypto";
18936
19132
  import { createWriteStream as createWriteStream4, existsSync as existsSync2, readdirSync as readdirSync2 } from "node:fs";
18937
19133
  import { arch, homedir as homedir3, platform } from "node:os";
18938
19134
  import path11 from "node:path";
18939
- import { fileURLToPath as fileURLToPath2 } from "node:url";
19135
+ import { fileURLToPath as fileURLToPath22 } from "node:url";
18940
19136
  import { readFile as readFile5 } from "node:fs/promises";
18941
19137
  import { homedir as homedir4 } from "node:os";
18942
19138
  import path14 from "node:path";
18943
- import { readFile as readFile4, readdir as readdir22, stat as stat22 } from "node:fs/promises";
19139
+ import { readFile as readFile42, readdir as readdir22, stat as stat22 } from "node:fs/promises";
18944
19140
  import { homedir as homedir32 } from "node:os";
18945
19141
  import path13 from "node:path";
18946
19142
  import { randomUUID as randomUUID6 } from "node:crypto";
@@ -18967,7 +19163,7 @@ import { readFile as readFile7 } from "node:fs/promises";
18967
19163
  import { createHash as createHash3 } from "node:crypto";
18968
19164
  import { createHash as createHash2 } from "node:crypto";
18969
19165
  import { exec as exec2 } from "node:child_process";
18970
- import { constants as constants2, access as access2 } from "node:fs/promises";
19166
+ import { constants as constants22, access as access22 } from "node:fs/promises";
18971
19167
  import path29 from "node:path";
18972
19168
  import { promisify as promisify4 } from "node:util";
18973
19169
  import { stat as stat5, writeFile as writeFile7 } from "node:fs/promises";
@@ -19023,28 +19219,24 @@ import { stringify as stringifyYaml } from "yaml";
19023
19219
  import { readdir as readdir7, stat as stat7 } from "node:fs/promises";
19024
19220
  import path39 from "node:path";
19025
19221
  import { readFile as readFile18, stat as stat9 } from "node:fs/promises";
19026
- import path47 from "node:path";
19222
+ import path46 from "node:path";
19027
19223
  import micromatch2 from "micromatch";
19028
19224
  import { stringify as stringifyYaml2 } from "yaml";
19029
19225
  import { readFile as readFile12 } from "node:fs/promises";
19030
19226
  import path41 from "node:path";
19031
19227
  import { readFile as readFile13 } from "node:fs/promises";
19032
- import path43 from "node:path";
19033
- import { constants as constants4 } from "node:fs";
19034
- import { access as access4 } from "node:fs/promises";
19035
19228
  import path422 from "node:path";
19036
- import { fileURLToPath as fileURLToPath4 } from "node:url";
19037
19229
  import { readFile as readFile15 } from "node:fs/promises";
19038
- import path44 from "node:path";
19230
+ import path43 from "node:path";
19039
19231
  import { readFile as readFile14 } from "node:fs/promises";
19040
19232
  import { readFile as readFile17 } from "node:fs/promises";
19041
- import path46 from "node:path";
19233
+ import path45 from "node:path";
19042
19234
  import micromatch from "micromatch";
19043
19235
  import { readFile as readFile16 } from "node:fs/promises";
19044
- import path45 from "node:path";
19236
+ import path44 from "node:path";
19045
19237
  import { createHash as createHash7 } from "node:crypto";
19046
19238
  import { copyFile as copyFile3, mkdir as mkdir18, readFile as readFile20, writeFile as writeFile10 } from "node:fs/promises";
19047
- import path49 from "node:path";
19239
+ import path48 from "node:path";
19048
19240
  import { readFile as readFile19 } from "node:fs/promises";
19049
19241
  var DEFAULT_CACHE_PATH = ".agentv/cache";
19050
19242
  var ResponseCache = class {
@@ -19055,7 +19247,7 @@ var ResponseCache = class {
19055
19247
  async get(key) {
19056
19248
  const filePath = this.keyToPath(key);
19057
19249
  try {
19058
- const data = await readFile3(filePath, "utf8");
19250
+ const data = await readFile4(filePath, "utf8");
19059
19251
  return JSON.parse(data);
19060
19252
  } catch {
19061
19253
  return void 0;
@@ -19063,13 +19255,13 @@ var ResponseCache = class {
19063
19255
  }
19064
19256
  async set(key, value) {
19065
19257
  const filePath = this.keyToPath(key);
19066
- const dir = path5.dirname(filePath);
19258
+ const dir = path8.dirname(filePath);
19067
19259
  await mkdir(dir, { recursive: true });
19068
19260
  await writeFile(filePath, JSON.stringify(value, null, 2), "utf8");
19069
19261
  }
19070
19262
  keyToPath(key) {
19071
19263
  const prefix = key.slice(0, 2);
19072
- return path5.join(this.cachePath, prefix, `${key}.json`);
19264
+ return path8.join(this.cachePath, prefix, `${key}.json`);
19073
19265
  }
19074
19266
  };
19075
19267
  function shouldEnableCache(params) {
@@ -19737,7 +19929,7 @@ var CodeGrader = class {
19737
19929
  let exitCode = 0;
19738
19930
  let execStderr = "";
19739
19931
  if (context.dockerConfig) {
19740
- const { DockerWorkspaceProvider } = await import("./docker-workspace-RPPXBT27-B4AQHVWA.js");
19932
+ const { DockerWorkspaceProvider } = await import("./docker-workspace-ZJ2ESVBI-6UDETQII.js");
19741
19933
  const dockerProvider = new DockerWorkspaceProvider(context.dockerConfig);
19742
19934
  const result = await dockerProvider.runGraderInContainer({
19743
19935
  command: [...this.command],
@@ -20012,7 +20204,7 @@ function normalizePreprocessorType(value) {
20012
20204
  }
20013
20205
  function resolveLocalFilePath(value, basePath) {
20014
20206
  if (value.startsWith("file://")) {
20015
- return fileURLToPath(value);
20207
+ return fileURLToPath2(value);
20016
20208
  }
20017
20209
  if (/^[a-z]+:\/\//i.test(value)) {
20018
20210
  return void 0;
@@ -22757,115 +22949,115 @@ var FieldAccuracyGrader = class {
22757
22949
  * Evaluate a single field against the expected value.
22758
22950
  */
22759
22951
  evaluateField(fieldConfig, candidateData, expectedData) {
22760
- const { path: path522, match, required: required2 = true, weight = 1 } = fieldConfig;
22761
- const candidateValue = resolvePath(candidateData, path522);
22762
- const expectedValue = resolvePath(expectedData, path522);
22952
+ const { path: path51, match, required: required2 = true, weight = 1 } = fieldConfig;
22953
+ const candidateValue = resolvePath(candidateData, path51);
22954
+ const expectedValue = resolvePath(expectedData, path51);
22763
22955
  if (expectedValue === void 0) {
22764
22956
  return {
22765
- path: path522,
22957
+ path: path51,
22766
22958
  score: 1,
22767
22959
  // No expected value means no comparison needed
22768
22960
  weight,
22769
22961
  hit: true,
22770
- message: `${path522}: no expected value`
22962
+ message: `${path51}: no expected value`
22771
22963
  };
22772
22964
  }
22773
22965
  if (candidateValue === void 0) {
22774
22966
  if (required2) {
22775
22967
  return {
22776
- path: path522,
22968
+ path: path51,
22777
22969
  score: 0,
22778
22970
  weight,
22779
22971
  hit: false,
22780
- message: `${path522} (required, missing)`
22972
+ message: `${path51} (required, missing)`
22781
22973
  };
22782
22974
  }
22783
22975
  return {
22784
- path: path522,
22976
+ path: path51,
22785
22977
  score: 1,
22786
22978
  // Don't penalize missing optional fields
22787
22979
  weight: 0,
22788
22980
  // Zero weight means it won't affect the score
22789
22981
  hit: true,
22790
- message: `${path522}: optional field missing`
22982
+ message: `${path51}: optional field missing`
22791
22983
  };
22792
22984
  }
22793
22985
  switch (match) {
22794
22986
  case "exact":
22795
- return this.compareExact(path522, candidateValue, expectedValue, weight);
22987
+ return this.compareExact(path51, candidateValue, expectedValue, weight);
22796
22988
  case "numeric_tolerance":
22797
22989
  return this.compareNumericTolerance(
22798
- path522,
22990
+ path51,
22799
22991
  candidateValue,
22800
22992
  expectedValue,
22801
22993
  fieldConfig,
22802
22994
  weight
22803
22995
  );
22804
22996
  case "date":
22805
- return this.compareDate(path522, candidateValue, expectedValue, fieldConfig, weight);
22997
+ return this.compareDate(path51, candidateValue, expectedValue, fieldConfig, weight);
22806
22998
  default:
22807
22999
  return {
22808
- path: path522,
23000
+ path: path51,
22809
23001
  score: 0,
22810
23002
  weight,
22811
23003
  hit: false,
22812
- message: `${path522}: unknown match type "${match}"`
23004
+ message: `${path51}: unknown match type "${match}"`
22813
23005
  };
22814
23006
  }
22815
23007
  }
22816
23008
  /**
22817
23009
  * Exact equality comparison.
22818
23010
  */
22819
- compareExact(path522, candidateValue, expectedValue, weight) {
23011
+ compareExact(path51, candidateValue, expectedValue, weight) {
22820
23012
  if (deepEqual(candidateValue, expectedValue)) {
22821
23013
  return {
22822
- path: path522,
23014
+ path: path51,
22823
23015
  score: 1,
22824
23016
  weight,
22825
23017
  hit: true,
22826
- message: path522
23018
+ message: path51
22827
23019
  };
22828
23020
  }
22829
23021
  if (typeof candidateValue !== typeof expectedValue) {
22830
23022
  return {
22831
- path: path522,
23023
+ path: path51,
22832
23024
  score: 0,
22833
23025
  weight,
22834
23026
  hit: false,
22835
- message: `${path522} (type mismatch: got ${typeof candidateValue}, expected ${typeof expectedValue})`
23027
+ message: `${path51} (type mismatch: got ${typeof candidateValue}, expected ${typeof expectedValue})`
22836
23028
  };
22837
23029
  }
22838
23030
  return {
22839
- path: path522,
23031
+ path: path51,
22840
23032
  score: 0,
22841
23033
  weight,
22842
23034
  hit: false,
22843
- message: `${path522} (value mismatch)`
23035
+ message: `${path51} (value mismatch)`
22844
23036
  };
22845
23037
  }
22846
23038
  /**
22847
23039
  * Numeric comparison with absolute or relative tolerance.
22848
23040
  */
22849
- compareNumericTolerance(path522, candidateValue, expectedValue, fieldConfig, weight) {
23041
+ compareNumericTolerance(path51, candidateValue, expectedValue, fieldConfig, weight) {
22850
23042
  const { tolerance = 0, relative = false } = fieldConfig;
22851
23043
  const candidateNum = toNumber(candidateValue);
22852
23044
  const expectedNum = toNumber(expectedValue);
22853
23045
  if (candidateNum === null || expectedNum === null) {
22854
23046
  return {
22855
- path: path522,
23047
+ path: path51,
22856
23048
  score: 0,
22857
23049
  weight,
22858
23050
  hit: false,
22859
- message: `${path522} (non-numeric value)`
23051
+ message: `${path51} (non-numeric value)`
22860
23052
  };
22861
23053
  }
22862
23054
  if (!Number.isFinite(candidateNum) || !Number.isFinite(expectedNum)) {
22863
23055
  return {
22864
- path: path522,
23056
+ path: path51,
22865
23057
  score: 0,
22866
23058
  weight,
22867
23059
  hit: false,
22868
- message: `${path522} (invalid numeric value)`
23060
+ message: `${path51} (invalid numeric value)`
22869
23061
  };
22870
23062
  }
22871
23063
  const diff = Math.abs(candidateNum - expectedNum);
@@ -22878,61 +23070,61 @@ var FieldAccuracyGrader = class {
22878
23070
  }
22879
23071
  if (withinTolerance) {
22880
23072
  return {
22881
- path: path522,
23073
+ path: path51,
22882
23074
  score: 1,
22883
23075
  weight,
22884
23076
  hit: true,
22885
- message: `${path522} (within tolerance: diff=${diff.toFixed(2)})`
23077
+ message: `${path51} (within tolerance: diff=${diff.toFixed(2)})`
22886
23078
  };
22887
23079
  }
22888
23080
  return {
22889
- path: path522,
23081
+ path: path51,
22890
23082
  score: 0,
22891
23083
  weight,
22892
23084
  hit: false,
22893
- message: `${path522} (outside tolerance: diff=${diff.toFixed(2)}, tolerance=${tolerance})`
23085
+ message: `${path51} (outside tolerance: diff=${diff.toFixed(2)}, tolerance=${tolerance})`
22894
23086
  };
22895
23087
  }
22896
23088
  /**
22897
23089
  * Date comparison with format normalization.
22898
23090
  */
22899
- compareDate(path522, candidateValue, expectedValue, fieldConfig, weight) {
23091
+ compareDate(path51, candidateValue, expectedValue, fieldConfig, weight) {
22900
23092
  const formats = fieldConfig.formats ?? DEFAULT_DATE_FORMATS;
22901
23093
  const candidateDate = parseDate(String(candidateValue), formats);
22902
23094
  const expectedDate = parseDate(String(expectedValue), formats);
22903
23095
  if (candidateDate === null) {
22904
23096
  return {
22905
- path: path522,
23097
+ path: path51,
22906
23098
  score: 0,
22907
23099
  weight,
22908
23100
  hit: false,
22909
- message: `${path522} (unparseable candidate date)`
23101
+ message: `${path51} (unparseable candidate date)`
22910
23102
  };
22911
23103
  }
22912
23104
  if (expectedDate === null) {
22913
23105
  return {
22914
- path: path522,
23106
+ path: path51,
22915
23107
  score: 0,
22916
23108
  weight,
22917
23109
  hit: false,
22918
- message: `${path522} (unparseable expected date)`
23110
+ message: `${path51} (unparseable expected date)`
22919
23111
  };
22920
23112
  }
22921
23113
  if (candidateDate.getFullYear() === expectedDate.getFullYear() && candidateDate.getMonth() === expectedDate.getMonth() && candidateDate.getDate() === expectedDate.getDate()) {
22922
23114
  return {
22923
- path: path522,
23115
+ path: path51,
22924
23116
  score: 1,
22925
23117
  weight,
22926
23118
  hit: true,
22927
- message: path522
23119
+ message: path51
22928
23120
  };
22929
23121
  }
22930
23122
  return {
22931
- path: path522,
23123
+ path: path51,
22932
23124
  score: 0,
22933
23125
  weight,
22934
23126
  hit: false,
22935
- message: `${path522} (date mismatch: got ${formatDateISO(candidateDate)}, expected ${formatDateISO(expectedDate)})`
23127
+ message: `${path51} (date mismatch: got ${formatDateISO(candidateDate)}, expected ${formatDateISO(expectedDate)})`
22936
23128
  };
22937
23129
  }
22938
23130
  /**
@@ -22965,11 +23157,11 @@ var FieldAccuracyGrader = class {
22965
23157
  };
22966
23158
  }
22967
23159
  };
22968
- function resolvePath(obj, path522) {
22969
- if (!path522 || !obj) {
23160
+ function resolvePath(obj, path51) {
23161
+ if (!path51 || !obj) {
22970
23162
  return void 0;
22971
23163
  }
22972
- const parts = path522.split(/\.|\[|\]/).filter((p) => p.length > 0);
23164
+ const parts = path51.split(/\.|\[|\]/).filter((p) => p.length > 0);
22973
23165
  let current = obj;
22974
23166
  for (const part of parts) {
22975
23167
  if (current === null || current === void 0) {
@@ -23500,8 +23692,8 @@ var TokenUsageGrader = class {
23500
23692
  };
23501
23693
  }
23502
23694
  };
23503
- function getNestedValue(obj, path522) {
23504
- const parts = path522.split(".");
23695
+ function getNestedValue(obj, path51) {
23696
+ const parts = path51.split(".");
23505
23697
  let current = obj;
23506
23698
  for (const part of parts) {
23507
23699
  if (current === null || current === void 0 || typeof current !== "object") {
@@ -24602,10 +24794,10 @@ var ClaudeCliProvider = class {
24602
24794
  }
24603
24795
  resolveCwd(cwdOverride) {
24604
24796
  if (cwdOverride) {
24605
- return path6.resolve(cwdOverride);
24797
+ return path62.resolve(cwdOverride);
24606
24798
  }
24607
24799
  if (this.config.cwd) {
24608
- return path6.resolve(this.config.cwd);
24800
+ return path62.resolve(this.config.cwd);
24609
24801
  }
24610
24802
  return void 0;
24611
24803
  }
@@ -24615,7 +24807,7 @@ var ClaudeCliProvider = class {
24615
24807
  return void 0;
24616
24808
  }
24617
24809
  if (this.config.logDir) {
24618
- return path6.resolve(this.config.logDir);
24810
+ return path62.resolve(this.config.logDir);
24619
24811
  }
24620
24812
  return resolveDefaultProviderLogDir("claude-cli", request);
24621
24813
  }
@@ -24631,7 +24823,7 @@ var ClaudeCliProvider = class {
24631
24823
  console.warn(`Skipping Claude CLI stream logging (could not create ${logDir}): ${message}`);
24632
24824
  return void 0;
24633
24825
  }
24634
- const filePath = path6.join(logDir, buildLogFilename(request, this.targetName));
24826
+ const filePath = path62.join(logDir, buildLogFilename(request, this.targetName));
24635
24827
  try {
24636
24828
  const logger = await ClaudeCliStreamLogger.create({
24637
24829
  filePath,
@@ -25091,10 +25283,10 @@ var ClaudeSdkProvider = class {
25091
25283
  }
25092
25284
  resolveCwd(cwdOverride) {
25093
25285
  if (cwdOverride) {
25094
- return path7.resolve(cwdOverride);
25286
+ return path72.resolve(cwdOverride);
25095
25287
  }
25096
25288
  if (this.config.cwd) {
25097
- return path7.resolve(this.config.cwd);
25289
+ return path72.resolve(this.config.cwd);
25098
25290
  }
25099
25291
  return void 0;
25100
25292
  }
@@ -25104,7 +25296,7 @@ var ClaudeSdkProvider = class {
25104
25296
  return void 0;
25105
25297
  }
25106
25298
  if (this.config.logDir) {
25107
- return path7.resolve(this.config.logDir);
25299
+ return path72.resolve(this.config.logDir);
25108
25300
  }
25109
25301
  return resolveDefaultProviderLogDir("claude", request);
25110
25302
  }
@@ -25120,7 +25312,7 @@ var ClaudeSdkProvider = class {
25120
25312
  console.warn(`Skipping Claude stream logging (could not create ${logDir}): ${message}`);
25121
25313
  return void 0;
25122
25314
  }
25123
- const filePath = path7.join(logDir, buildLogFilename2(request, this.targetName));
25315
+ const filePath = path72.join(logDir, buildLogFilename2(request, this.targetName));
25124
25316
  try {
25125
25317
  const logger = await ClaudeStreamLogger.create({
25126
25318
  filePath,
@@ -25807,7 +25999,7 @@ function normalizeInputFiles2(inputFiles) {
25807
25999
  }
25808
26000
  const unique = /* @__PURE__ */ new Map();
25809
26001
  for (const inputFile of inputFiles) {
25810
- const absolutePath = path8.resolve(inputFile);
26002
+ const absolutePath = path82.resolve(inputFile);
25811
26003
  if (!unique.has(absolutePath)) {
25812
26004
  unique.set(absolutePath, absolutePath);
25813
26005
  }
@@ -25821,7 +26013,7 @@ function formatFileList(files, template) {
25821
26013
  const formatter = template ?? "{path}";
25822
26014
  return files.map((filePath) => {
25823
26015
  const escapedPath = shellEscape(filePath);
25824
- const escapedName = shellEscape(path8.basename(filePath));
26016
+ const escapedName = shellEscape(path82.basename(filePath));
25825
26017
  return formatter.replaceAll("{path}", escapedPath).replaceAll("{basename}", escapedName);
25826
26018
  }).join(" ");
25827
26019
  }
@@ -25845,7 +26037,7 @@ function generateOutputFilePath(evalCaseId, extension = ".json") {
25845
26037
  const safeEvalId = evalCaseId || "unknown";
25846
26038
  const timestamp = Date.now();
25847
26039
  const random = Math.random().toString(36).substring(2, 9);
25848
- return path8.join(os2.tmpdir(), `agentv-${safeEvalId}-${timestamp}-${random}${extension}`);
26040
+ return path82.join(os2.tmpdir(), `agentv-${safeEvalId}-${timestamp}-${random}${extension}`);
25849
26041
  }
25850
26042
  function formatTimeoutSuffix2(timeoutMs) {
25851
26043
  if (!timeoutMs || timeoutMs <= 0) {
@@ -26481,7 +26673,7 @@ function resolvePlatformCliPath() {
26481
26673
  const binaryName = os22 === "win32" ? "copilot.exe" : "copilot";
26482
26674
  try {
26483
26675
  const resolved = import.meta.resolve(`${packageName}/package.json`);
26484
- const packageJsonPath = resolved.startsWith("file:") ? fileURLToPath2(resolved) : resolved;
26676
+ const packageJsonPath = resolved.startsWith("file:") ? fileURLToPath22(resolved) : resolved;
26485
26677
  const binaryPath = path11.join(path11.dirname(packageJsonPath), binaryName);
26486
26678
  if (existsSync2(binaryPath)) {
26487
26679
  return binaryPath;
@@ -27463,7 +27655,7 @@ async function discoverCopilotSessions(opts) {
27463
27655
  const workspacePath = path13.join(sessionDir, "workspace.yaml");
27464
27656
  const eventsPath = path13.join(sessionDir, "events.jsonl");
27465
27657
  try {
27466
- const workspaceContent = await readFile4(workspacePath, "utf8");
27658
+ const workspaceContent = await readFile42(workspacePath, "utf8");
27467
27659
  const workspace = parseYamlValue(workspaceContent) ?? {};
27468
27660
  const cwd = String(workspace.cwd ?? "");
27469
27661
  let updatedAt;
@@ -33317,7 +33509,7 @@ async function locateVSCodeExecutable(candidate) {
33317
33509
  if (includesPathSeparator) {
33318
33510
  const resolved = path29.isAbsolute(candidate) ? candidate : path29.resolve(candidate);
33319
33511
  try {
33320
- await access2(resolved, constants2.F_OK);
33512
+ await access22(resolved, constants22.F_OK);
33321
33513
  return resolved;
33322
33514
  } catch {
33323
33515
  throw new Error(
@@ -33330,7 +33522,7 @@ async function locateVSCodeExecutable(candidate) {
33330
33522
  const { stdout } = await execAsync4(`${locator} ${candidate}`);
33331
33523
  const lines = stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
33332
33524
  if (lines.length > 0 && lines[0]) {
33333
- await access2(lines[0], constants2.F_OK);
33525
+ await access22(lines[0], constants22.F_OK);
33334
33526
  return lines[0];
33335
33527
  }
33336
33528
  } catch {
@@ -33482,7 +33674,7 @@ function assertTargetDefinition(value, index, filePath) {
33482
33674
  }
33483
33675
  return value;
33484
33676
  }
33485
- async function fileExists2(filePath) {
33677
+ async function fileExists3(filePath) {
33486
33678
  try {
33487
33679
  await access32(filePath, constants32.F_OK);
33488
33680
  return true;
@@ -33492,7 +33684,7 @@ async function fileExists2(filePath) {
33492
33684
  }
33493
33685
  async function readTargetDefinitions(filePath) {
33494
33686
  const absolutePath = path30.resolve(filePath);
33495
- if (!await fileExists2(absolutePath)) {
33687
+ if (!await fileExists3(absolutePath)) {
33496
33688
  throw new Error(`targets.yaml not found at ${absolutePath}`);
33497
33689
  }
33498
33690
  const raw = await readFile10(absolutePath, "utf8");
@@ -34587,13 +34779,23 @@ var WorkspacePoolManager = class {
34587
34779
  }
34588
34780
  };
34589
34781
  function getProjectsRegistryPath() {
34590
- return path37.join(getAgentvConfigDir(), "config.yaml");
34782
+ return path37.join(getAgentvConfigDir(), AGENTV_CONFIG_FILE_NAME);
34591
34783
  }
34592
34784
  function readTrimmedString(value) {
34593
34785
  if (typeof value !== "string") return void 0;
34594
34786
  const trimmed = value.trim();
34595
34787
  return trimmed.length > 0 ? trimmed : void 0;
34596
34788
  }
34789
+ var warnedRemovedBackupAndForcePushPolicy = false;
34790
+ function warnRemovedBackupAndForcePushPolicy() {
34791
+ if (warnedRemovedBackupAndForcePushPolicy) {
34792
+ return;
34793
+ }
34794
+ warnedRemovedBackupAndForcePushPolicy = true;
34795
+ console.warn(
34796
+ "[agentv] projects[].results.sync.push_conflict_policy: 'backup_and_force_push' is no longer supported and was ignored while loading the project registry. Remove the field or set it to 'block'; AgentV never force-pushes result branches."
34797
+ );
34798
+ }
34597
34799
  function fromYaml(raw) {
34598
34800
  if (!raw || typeof raw !== "object") return null;
34599
34801
  const e = raw;
@@ -34637,11 +34839,14 @@ function fromYaml(raw) {
34637
34839
  sync: {
34638
34840
  ...typeof sync.auto_push === "boolean" ? { autoPush: sync.auto_push } : {},
34639
34841
  ...typeof sync.require_push === "boolean" ? { requirePush: sync.require_push } : {},
34640
- ...sync.push_conflict_policy === "block" || sync.push_conflict_policy === "backup_and_force_push" ? { pushConflictPolicy: sync.push_conflict_policy } : {}
34842
+ ...sync.push_conflict_policy === "block" ? { pushConflictPolicy: sync.push_conflict_policy } : {}
34641
34843
  }
34642
34844
  } : {},
34643
34845
  ...typeof r.branch_prefix === "string" && r.branch_prefix.trim().length > 0 ? { branchPrefix: r.branch_prefix.trim() } : {}
34644
34846
  };
34847
+ if (sync?.push_conflict_policy === "backup_and_force_push") {
34848
+ warnRemovedBackupAndForcePushPolicy();
34849
+ }
34645
34850
  }
34646
34851
  }
34647
34852
  return entry;
@@ -34703,12 +34908,12 @@ function toYaml(entry) {
34703
34908
  }
34704
34909
  function loadProjectRegistry() {
34705
34910
  const registryPath = getProjectsRegistryPath();
34706
- if (!existsSync4(registryPath)) {
34911
+ const localRegistryPath = getLocalConfigPath(registryPath);
34912
+ if (!existsSync4(registryPath) && !existsSync4(localRegistryPath)) {
34707
34913
  return { projects: [] };
34708
34914
  }
34709
34915
  try {
34710
- const raw = readFileSync22(registryPath, "utf-8");
34711
- const parsed = parseYamlValue(raw);
34916
+ const parsed = readMergedHomeConfig(registryPath);
34712
34917
  if (!parsed || typeof parsed !== "object") {
34713
34918
  return { projects: [] };
34714
34919
  }
@@ -34720,7 +34925,7 @@ function loadProjectRegistry() {
34720
34925
  }
34721
34926
  }
34722
34927
  function saveProjectRegistry(registry2) {
34723
- const registryPath = getProjectsRegistryPath();
34928
+ const registryPath = getProjectsRegistryWritePath();
34724
34929
  const dir = path37.dirname(registryPath);
34725
34930
  if (!existsSync4(dir)) {
34726
34931
  mkdirSync2(dir, { recursive: true });
@@ -34737,6 +34942,17 @@ function readHomeConfig(configPath2) {
34737
34942
  return {};
34738
34943
  }
34739
34944
  }
34945
+ function readMergedHomeConfig(configPath2) {
34946
+ const base = readHomeConfig(configPath2);
34947
+ const local = readHomeConfig(getLocalConfigPath(configPath2));
34948
+ return Object.keys(base).length > 0 && Object.keys(local).length > 0 ? mergeConfigObjects(base, local) : Object.keys(local).length > 0 ? local : base;
34949
+ }
34950
+ function getProjectsRegistryWritePath() {
34951
+ const registryPath = getProjectsRegistryPath();
34952
+ const localRegistryPath = getLocalConfigPath(registryPath);
34953
+ const localConfig = readHomeConfig(localRegistryPath);
34954
+ return Object.prototype.hasOwnProperty.call(localConfig, "projects") ? localRegistryPath : registryPath;
34955
+ }
34740
34956
  function deriveProjectId(dirPath, existingIds) {
34741
34957
  const base = path37.basename(dirPath).toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
34742
34958
  let candidate = base || "project";
@@ -34898,11 +35114,13 @@ var RepoManager = class {
34898
35114
  progress;
34899
35115
  heartbeatMs;
34900
35116
  timeoutMs;
35117
+ projectConfigDir;
34901
35118
  constructor(verbose = false, options = {}) {
34902
35119
  this.verbose = verbose;
34903
35120
  this.progress = options.progress ?? true;
34904
35121
  this.heartbeatMs = options.heartbeatMs ?? DEFAULT_HEARTBEAT_MS;
34905
35122
  this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
35123
+ this.projectConfigDir = options.projectConfigDir;
34906
35124
  }
34907
35125
  async runGit(args, opts) {
34908
35126
  const startedAt = Date.now();
@@ -35005,8 +35223,7 @@ ${output}` : ""}`
35005
35223
  });
35006
35224
  });
35007
35225
  }
35008
- loadConfiguredMirrors() {
35009
- const filePath = configPath();
35226
+ loadConfiguredMirrorsFrom(filePath) {
35010
35227
  if (!existsSync5(filePath)) return {};
35011
35228
  try {
35012
35229
  const parsed = parseYamlValue(readFileSync3(filePath, "utf-8"));
@@ -35027,6 +35244,50 @@ ${output}` : ""}`
35027
35244
  return {};
35028
35245
  }
35029
35246
  }
35247
+ findProjectAgentvDir() {
35248
+ if (!this.projectConfigDir) return void 0;
35249
+ let current = path38.resolve(this.projectConfigDir);
35250
+ while (true) {
35251
+ const candidateDir = path38.join(current, ".agentv");
35252
+ if (existsSync5(path38.join(candidateDir, "config.yaml")) || existsSync5(path38.join(candidateDir, "config.override.yaml"))) {
35253
+ return candidateDir;
35254
+ }
35255
+ const reachedRepoRoot = existsSync5(path38.join(current, ".git"));
35256
+ const parent = path38.dirname(current);
35257
+ if (reachedRepoRoot || parent === current) return void 0;
35258
+ current = parent;
35259
+ }
35260
+ }
35261
+ mergeConfiguredMirrorLayers(layers) {
35262
+ const mirrorsByRepo = /* @__PURE__ */ new Map();
35263
+ const repoByIdentity = /* @__PURE__ */ new Map();
35264
+ for (const layer of layers) {
35265
+ for (const [repo, localPath] of Object.entries(layer)) {
35266
+ const repoIdentity = normalizeRepoIdentity(repo);
35267
+ const previousRepo = repoByIdentity.get(repoIdentity);
35268
+ if (previousRepo) mirrorsByRepo.delete(previousRepo);
35269
+ repoByIdentity.set(repoIdentity, repo);
35270
+ mirrorsByRepo.set(repo, localPath);
35271
+ }
35272
+ }
35273
+ return Object.fromEntries(mirrorsByRepo);
35274
+ }
35275
+ loadConfiguredMirrors() {
35276
+ const globalMirrors = this.loadConfiguredMirrorsFrom(configPath());
35277
+ const projectAgentvDir = this.findProjectAgentvDir();
35278
+ if (!projectAgentvDir) return globalMirrors;
35279
+ const projectMirrors = this.loadConfiguredMirrorsFrom(
35280
+ path38.join(projectAgentvDir, "config.yaml")
35281
+ );
35282
+ const projectOverrideMirrors = this.loadConfiguredMirrorsFrom(
35283
+ path38.join(projectAgentvDir, "config.override.yaml")
35284
+ );
35285
+ return this.mergeConfiguredMirrorLayers([
35286
+ globalMirrors,
35287
+ projectMirrors,
35288
+ projectOverrideMirrors
35289
+ ]);
35290
+ }
35030
35291
  findConfiguredMirror(repoIdentity) {
35031
35292
  const mirrors = this.loadConfiguredMirrors();
35032
35293
  for (const [repo, localPath] of Object.entries(mirrors)) {
@@ -35548,7 +35809,7 @@ async function prepareSharedWorkspaceSetup(options) {
35548
35809
  const slotsNeeded = workers;
35549
35810
  setupLog(`acquiring ${slotsNeeded} workspace pool slot(s) (pool capacity: ${poolMaxSlots})`);
35550
35811
  poolManager = new WorkspacePoolManager(getWorkspacePoolRoot());
35551
- const poolRepoManager = new RepoManager(verbose);
35812
+ const poolRepoManager = new RepoManager(verbose, { projectConfigDir: evalDir });
35552
35813
  repoManager = poolRepoManager;
35553
35814
  for (let i = 0; i < slotsNeeded; i++) {
35554
35815
  const slot = await poolManager.acquireWorkspace({
@@ -35597,7 +35858,7 @@ async function prepareSharedWorkspaceSetup(options) {
35597
35858
  const hasReposToMaterialize = !!suiteWorkspace?.repos?.length && !usePool && !isPerTestIsolation;
35598
35859
  const needsRepoMaterialisation = hasReposToMaterialize && (!useStaticWorkspace || staticMaterialised);
35599
35860
  const needsPerRepoCheck = hasReposToMaterialize && useStaticWorkspace && !staticMaterialised && isYamlConfiguredPath;
35600
- repoManager = repoManager ?? (needsRepoMaterialisation || needsPerRepoCheck ? new RepoManager(verbose) : void 0);
35861
+ repoManager = repoManager ?? (needsRepoMaterialisation || needsPerRepoCheck ? new RepoManager(verbose, { projectConfigDir: evalDir }) : void 0);
35601
35862
  if ((needsRepoMaterialisation || needsPerRepoCheck) && repoManager && sharedWorkspacePath && suiteWorkspace?.repos) {
35602
35863
  try {
35603
35864
  if (needsPerRepoCheck) {
@@ -35635,7 +35896,7 @@ async function prepareSharedWorkspaceSetup(options) {
35635
35896
  const suiteDockerConfig = suiteWorkspace?.docker;
35636
35897
  if (suiteDockerConfig) {
35637
35898
  setupLog(`pulling Docker image: ${suiteDockerConfig.image}`);
35638
- const { DockerWorkspaceProvider } = await import("./docker-workspace-RPPXBT27-B4AQHVWA.js");
35899
+ const { DockerWorkspaceProvider } = await import("./docker-workspace-ZJ2ESVBI-6UDETQII.js");
35639
35900
  const dockerSetup = new DockerWorkspaceProvider(suiteDockerConfig);
35640
35901
  if (!await dockerSetup.isDockerAvailable()) {
35641
35902
  throw new Error(
@@ -35972,7 +36233,7 @@ async function prepareEvalCaseWorkspace(options) {
35972
36233
  await mkdir17(workspacePath, { recursive: true });
35973
36234
  }
35974
36235
  if (evalCase.workspace?.repos?.length && workspacePath) {
35975
- const perCaseRepoManager = new RepoManager(setupDebug);
36236
+ const perCaseRepoManager = new RepoManager(setupDebug, { projectConfigDir: evalDir });
35976
36237
  try {
35977
36238
  if (setupDebug) {
35978
36239
  console.log(
@@ -36395,101 +36656,6 @@ function parseAgentSkillsEvals(parsed, source = "evals.json", baseDir) {
36395
36656
  }
36396
36657
  return tests;
36397
36658
  }
36398
- async function fileExists3(absolutePath) {
36399
- try {
36400
- await access4(absolutePath, constants4.F_OK);
36401
- return true;
36402
- } catch {
36403
- return false;
36404
- }
36405
- }
36406
- function resolveToAbsolutePath(candidate) {
36407
- if (candidate instanceof URL) {
36408
- return candidate.protocol === "file:" ? fileURLToPath4(candidate) : candidate.pathname;
36409
- }
36410
- if (typeof candidate === "string") {
36411
- if (candidate.startsWith("file:")) {
36412
- return fileURLToPath4(candidate);
36413
- }
36414
- return path422.resolve(candidate);
36415
- }
36416
- throw new TypeError("Unsupported repoRoot value. Expected string or URL.");
36417
- }
36418
- function buildDirectoryChain2(filePath, repoRoot) {
36419
- const directories = [];
36420
- const seen = /* @__PURE__ */ new Set();
36421
- const boundary = path422.resolve(repoRoot);
36422
- let current = path422.resolve(path422.dirname(filePath));
36423
- while (current !== void 0) {
36424
- if (!seen.has(current)) {
36425
- directories.push(current);
36426
- seen.add(current);
36427
- }
36428
- if (current === boundary) {
36429
- break;
36430
- }
36431
- const parent = path422.dirname(current);
36432
- if (parent === current) {
36433
- break;
36434
- }
36435
- current = parent;
36436
- }
36437
- if (!seen.has(boundary)) {
36438
- directories.push(boundary);
36439
- }
36440
- return directories;
36441
- }
36442
- function buildSearchRoots2(evalPath, repoRoot) {
36443
- const uniqueRoots = [];
36444
- const addRoot = (root) => {
36445
- const normalized = path422.resolve(root);
36446
- if (!uniqueRoots.includes(normalized)) {
36447
- uniqueRoots.push(normalized);
36448
- }
36449
- };
36450
- let currentDir = path422.dirname(evalPath);
36451
- let reachedBoundary = false;
36452
- while (!reachedBoundary) {
36453
- addRoot(currentDir);
36454
- const parentDir = path422.dirname(currentDir);
36455
- if (currentDir === repoRoot || parentDir === currentDir) {
36456
- reachedBoundary = true;
36457
- } else {
36458
- currentDir = parentDir;
36459
- }
36460
- }
36461
- addRoot(repoRoot);
36462
- addRoot(process.cwd());
36463
- return uniqueRoots;
36464
- }
36465
- function trimLeadingSeparators2(value) {
36466
- const trimmed = value.replace(/^[/\\]+/, "");
36467
- return trimmed.length > 0 ? trimmed : value;
36468
- }
36469
- async function resolveFileReference3(rawValue, searchRoots) {
36470
- const displayPath = trimLeadingSeparators2(rawValue);
36471
- const potentialPaths = [];
36472
- if (path422.isAbsolute(rawValue)) {
36473
- potentialPaths.push(path422.normalize(rawValue));
36474
- }
36475
- for (const base of searchRoots) {
36476
- potentialPaths.push(path422.resolve(base, displayPath));
36477
- }
36478
- const attempted = [];
36479
- const seen = /* @__PURE__ */ new Set();
36480
- for (const candidate of potentialPaths) {
36481
- const absoluteCandidate = path422.resolve(candidate);
36482
- if (seen.has(absoluteCandidate)) {
36483
- continue;
36484
- }
36485
- seen.add(absoluteCandidate);
36486
- attempted.push(absoluteCandidate);
36487
- if (await fileExists3(absoluteCandidate)) {
36488
- return { displayPath, resolvedPath: absoluteCandidate, attempted };
36489
- }
36490
- }
36491
- return { displayPath, attempted };
36492
- }
36493
36659
  var ANSI_YELLOW2 = "\x1B[33m";
36494
36660
  var ANSI_RESET22 = "\x1B[0m";
36495
36661
  var DEFAULT_EVAL_PATTERNS = [
@@ -36499,25 +36665,50 @@ var DEFAULT_EVAL_PATTERNS = [
36499
36665
  ];
36500
36666
  async function loadConfig(evalFilePath, repoRoot) {
36501
36667
  const directories = buildDirectoryChain2(evalFilePath, repoRoot);
36502
- const globalConfigPath = path43.join(getAgentvConfigDir(), "config.yaml");
36668
+ const globalConfigPath = path422.join(getAgentvConfigDir(), AGENTV_CONFIG_FILE_NAME);
36503
36669
  for (const directory of directories) {
36504
- const configPath2 = path43.join(directory, ".agentv", "config.yaml");
36505
- if (!await fileExists3(configPath2)) {
36670
+ const configPath2 = path422.join(directory, ".agentv", AGENTV_CONFIG_FILE_NAME);
36671
+ if (!await configPairExists(configPath2)) {
36506
36672
  continue;
36507
36673
  }
36508
- const config2 = await readConfigFile(configPath2);
36509
- if (config2) {
36510
- return config2;
36511
- }
36674
+ return readConfigFilePair(configPath2);
36512
36675
  }
36513
- return await fileExists3(globalConfigPath) ? readConfigFile(globalConfigPath) : null;
36676
+ return await configPairExists(globalConfigPath) ? readConfigFilePair(globalConfigPath) : null;
36514
36677
  }
36515
- async function readConfigFile(configPath2) {
36678
+ async function configPairExists(configPath2) {
36679
+ return await fileExists2(configPath2) || await fileExists2(getLocalConfigPath(configPath2));
36680
+ }
36681
+ async function readConfigObjectFile(configPath2) {
36682
+ if (!await fileExists2(configPath2)) {
36683
+ return void 0;
36684
+ }
36516
36685
  try {
36517
36686
  const rawConfig = await readFile13(configPath2, "utf8");
36518
- const parsed = interpolateEnv(parseYamlValue(rawConfig), process.env);
36687
+ const parsed = parseYamlValue(rawConfig);
36688
+ if (!isPlainConfigObject(parsed)) {
36689
+ logWarning(`Invalid AgentV config format at ${configPath2}`);
36690
+ return void 0;
36691
+ }
36692
+ return parsed;
36693
+ } catch (error40) {
36694
+ logWarning(`Could not read AgentV config at ${configPath2}: ${error40.message}`);
36695
+ return void 0;
36696
+ }
36697
+ }
36698
+ async function readConfigFilePair(configPath2) {
36699
+ const base = await readConfigObjectFile(configPath2);
36700
+ const local = await readConfigObjectFile(getLocalConfigPath(configPath2));
36701
+ const rawMerged = base && local ? mergeConfigObjects(base, local) : local ?? base;
36702
+ if (!rawMerged) {
36703
+ return null;
36704
+ }
36705
+ return parseConfigObject(rawMerged, local ? getLocalConfigPath(configPath2) : configPath2);
36706
+ }
36707
+ function parseConfigObject(rawConfig, configPath2) {
36708
+ try {
36709
+ const parsed = interpolateEnv(rawConfig, process.env);
36519
36710
  if (!isJsonObject(parsed)) {
36520
- logWarning(`Invalid config.yaml format at ${configPath2}`);
36711
+ logWarning(`Invalid AgentV config format at ${configPath2}`);
36521
36712
  return null;
36522
36713
  }
36523
36714
  const config2 = parsed;
@@ -36539,17 +36730,27 @@ async function readConfigFile(configPath2) {
36539
36730
  parsed.execution,
36540
36731
  configPath2
36541
36732
  );
36733
+ const defaultExperiment = parseDefaultExperiment(
36734
+ parsed.default_experiment,
36735
+ configPath2
36736
+ );
36737
+ const experiments = parseExperimentsConfig(
36738
+ parsed.experiments,
36739
+ configPath2
36740
+ );
36542
36741
  const results = parseResultsConfig(parsed.results, configPath2);
36543
36742
  const hooks = parseHooksConfig(parsed.hooks, configPath2);
36544
36743
  return {
36545
36744
  required_version: requiredVersion,
36546
36745
  eval_patterns: evalPatterns,
36746
+ ...defaultExperiment && { default_experiment: defaultExperiment },
36747
+ ...experiments && { experiments },
36547
36748
  execution: executionDefaults,
36548
36749
  results,
36549
36750
  ...hooks && { hooks }
36550
36751
  };
36551
36752
  } catch (error40) {
36552
- logWarning(`Could not read config.yaml at ${configPath2}: ${error40.message}`);
36753
+ logWarning(`Could not parse AgentV config at ${configPath2}: ${error40.message}`);
36553
36754
  return null;
36554
36755
  }
36555
36756
  }
@@ -36661,58 +36862,6 @@ function extractTargetsFromTestCase(testCase) {
36661
36862
  }
36662
36863
  return void 0;
36663
36864
  }
36664
- var VALID_TRIAL_STRATEGIES = /* @__PURE__ */ new Set([
36665
- "pass_at_k",
36666
- "mean",
36667
- "confidence_interval"
36668
- ]);
36669
- function extractTrialsConfig(suite) {
36670
- const execution = suite.execution;
36671
- if (!execution || typeof execution !== "object" || Array.isArray(execution)) {
36672
- return void 0;
36673
- }
36674
- const trials = execution.trials;
36675
- if (!trials || typeof trials !== "object" || Array.isArray(trials)) {
36676
- return void 0;
36677
- }
36678
- const trialsObj = trials;
36679
- const count = trialsObj.count;
36680
- if (count === void 0 || count === null) {
36681
- return void 0;
36682
- }
36683
- if (typeof count !== "number" || !Number.isInteger(count) || count < 1) {
36684
- logWarning(
36685
- `Invalid trials.count: ${count}, must be a positive integer. Ignoring trials config.`
36686
- );
36687
- return void 0;
36688
- }
36689
- if (count === 1) {
36690
- return void 0;
36691
- }
36692
- const rawStrategy = trialsObj.strategy;
36693
- let strategy = "pass_at_k";
36694
- if (rawStrategy !== void 0 && rawStrategy !== null) {
36695
- if (typeof rawStrategy !== "string" || !VALID_TRIAL_STRATEGIES.has(rawStrategy)) {
36696
- logWarning(
36697
- `Invalid trials.strategy: '${rawStrategy}'. Must be one of: pass_at_k, mean, confidence_interval. Defaulting to pass_at_k.`
36698
- );
36699
- } else {
36700
- strategy = rawStrategy;
36701
- }
36702
- }
36703
- const rawCostLimit = trialsObj.cost_limit_usd ?? trialsObj.costLimitUsd;
36704
- let costLimitUsd;
36705
- if (rawCostLimit !== void 0 && rawCostLimit !== null) {
36706
- if (typeof rawCostLimit === "number" && rawCostLimit > 0) {
36707
- costLimitUsd = rawCostLimit;
36708
- } else {
36709
- logWarning(
36710
- `Invalid trials.cost_limit_usd: ${rawCostLimit}. Must be a positive number. Ignoring.`
36711
- );
36712
- }
36713
- }
36714
- return { count, strategy, costLimitUsd };
36715
- }
36716
36865
  function extractCacheConfig(suite) {
36717
36866
  const execution = suite.execution;
36718
36867
  if (!execution || typeof execution !== "object" || Array.isArray(execution)) {
@@ -36843,6 +36992,36 @@ function parseExecutionDefaults(raw, configPath2) {
36843
36992
  }
36844
36993
  return Object.keys(result).length > 0 ? result : void 0;
36845
36994
  }
36995
+ function resolveDefaultExperimentReference(config2) {
36996
+ return config2?.experiments?.default ?? config2?.default_experiment;
36997
+ }
36998
+ function parseDefaultExperiment(raw, configPath2) {
36999
+ if (raw === void 0 || raw === null) {
37000
+ return void 0;
37001
+ }
37002
+ const value = readTrimmedString2(raw);
37003
+ if (!value) {
37004
+ logWarning(`Invalid default_experiment in ${configPath2}, expected non-empty string`);
37005
+ return void 0;
37006
+ }
37007
+ return value;
37008
+ }
37009
+ function parseExperimentsConfig(raw, configPath2) {
37010
+ if (raw === void 0 || raw === null) {
37011
+ return void 0;
37012
+ }
37013
+ if (typeof raw !== "object" || Array.isArray(raw)) {
37014
+ logWarning(`Invalid experiments in ${configPath2}, expected object`);
37015
+ return void 0;
37016
+ }
37017
+ const obj = raw;
37018
+ const defaultExperiment = readTrimmedString2(obj.default);
37019
+ if (obj.default !== void 0 && !defaultExperiment) {
37020
+ logWarning(`Invalid experiments.default in ${configPath2}, expected non-empty string`);
37021
+ return void 0;
37022
+ }
37023
+ return defaultExperiment ? { default: defaultExperiment } : void 0;
37024
+ }
36846
37025
  function isFilesystemPath(p) {
36847
37026
  return p.startsWith("/") || p.startsWith("~/") || p.startsWith("~\\") || p === "~" || /^[A-Za-z]:[/\\]/.test(p);
36848
37027
  }
@@ -37006,16 +37185,20 @@ function parseResultsConfig(raw, configPath2) {
37006
37185
  logWarning(`Invalid results.sync.require_push in ${configPath2}, expected boolean`);
37007
37186
  return void 0;
37008
37187
  }
37009
- if (syncObj.push_conflict_policy !== void 0 && syncObj.push_conflict_policy !== "block" && syncObj.push_conflict_policy !== "backup_and_force_push") {
37188
+ if (syncObj.push_conflict_policy === "backup_and_force_push") {
37010
37189
  logWarning(
37011
- `Invalid results.sync.push_conflict_policy in ${configPath2}, expected 'block' or 'backup_and_force_push'`
37190
+ `results.sync.push_conflict_policy: 'backup_and_force_push' in ${configPath2} is no longer supported. Remove the field or set it to 'block'; AgentV never force-pushes result branches.`
37012
37191
  );
37013
37192
  return void 0;
37014
37193
  }
37194
+ if (syncObj.push_conflict_policy !== void 0 && syncObj.push_conflict_policy !== "block") {
37195
+ logWarning(`Invalid results.sync.push_conflict_policy in ${configPath2}, expected 'block'`);
37196
+ return void 0;
37197
+ }
37015
37198
  sync = {
37016
37199
  ...typeof syncObj.auto_push === "boolean" && { auto_push: syncObj.auto_push },
37017
37200
  ...typeof syncObj.require_push === "boolean" && { require_push: syncObj.require_push },
37018
- ...(syncObj.push_conflict_policy === "block" || syncObj.push_conflict_policy === "backup_and_force_push") && {
37201
+ ...syncObj.push_conflict_policy === "block" && {
37019
37202
  push_conflict_policy: syncObj.push_conflict_policy
37020
37203
  }
37021
37204
  };
@@ -37146,8 +37329,8 @@ function isTemplateReference(value) {
37146
37329
  }
37147
37330
  async function resolveAssertionTemplateReference(include, searchRoots) {
37148
37331
  const templateCandidates = isTemplateReference(include) ? [
37149
- path44.join(".agentv", "templates", `${include}.yaml`),
37150
- path44.join(".agentv", "templates", `${include}.yml`)
37332
+ path43.join(".agentv", "templates", `${include}.yaml`),
37333
+ path43.join(".agentv", "templates", `${include}.yml`)
37151
37334
  ] : [include];
37152
37335
  const attempted = [];
37153
37336
  for (const candidate of templateCandidates) {
@@ -37200,10 +37383,10 @@ ${resolved.attempted.map((attempt) => ` Tried: ${attempt}`).join("\n")}` : "";
37200
37383
  `Invalid assertion template file in '${evalId}': ${resolved.resolvedPath} is missing a top-level assertions array`
37201
37384
  );
37202
37385
  }
37203
- const templateDir = path44.dirname(resolved.resolvedPath);
37386
+ const templateDir = path43.dirname(resolved.resolvedPath);
37204
37387
  const nestedSearchRoots = [
37205
37388
  templateDir,
37206
- ...searchRoots.filter((root) => path44.resolve(root) !== templateDir)
37389
+ ...searchRoots.filter((root) => path43.resolve(root) !== templateDir)
37207
37390
  ];
37208
37391
  return await expandGraderEntries(assertions, nestedSearchRoots, evalId, {
37209
37392
  depth: nextDepth,
@@ -37264,7 +37447,7 @@ async function collectAssertionTemplateReferencesFromValue(value, searchRoots, e
37264
37447
  references.push({
37265
37448
  kind: "assertion_template",
37266
37449
  displayPath: resolved.displayPath,
37267
- ...resolved.resolvedPath ? { resolvedPath: path44.resolve(resolved.resolvedPath) } : {}
37450
+ ...resolved.resolvedPath ? { resolvedPath: path43.resolve(resolved.resolvedPath) } : {}
37268
37451
  });
37269
37452
  if (resolved.resolvedPath) {
37270
37453
  if (includeContext.chain.includes(resolved.resolvedPath)) {
@@ -37274,10 +37457,10 @@ async function collectAssertionTemplateReferencesFromValue(value, searchRoots, e
37274
37457
  const content = await readFile15(resolved.resolvedPath, "utf8");
37275
37458
  const parsed = interpolateEnv(parseYamlValue(content), process.env);
37276
37459
  if (isJsonObject2(parsed) && Array.isArray(parsed.assertions)) {
37277
- const templateDir = path44.dirname(resolved.resolvedPath);
37460
+ const templateDir = path43.dirname(resolved.resolvedPath);
37278
37461
  const nestedSearchRoots = [
37279
37462
  templateDir,
37280
- ...searchRoots.filter((root) => path44.resolve(root) !== templateDir)
37463
+ ...searchRoots.filter((root) => path43.resolve(root) !== templateDir)
37281
37464
  ];
37282
37465
  references.push(
37283
37466
  ...await collectAssertionTemplateReferencesFromValue(
@@ -37447,7 +37630,7 @@ async function parseGraderList(candidateEvaluators, searchRoots, evalId, default
37447
37630
  }
37448
37631
  command = parseCommandToArgv(trimmed);
37449
37632
  } else {
37450
- command = asStringArray(
37633
+ command = asStringArray2(
37451
37634
  rawCommand,
37452
37635
  `code-grader command for evaluator '${name}' in '${evalId}'`
37453
37636
  );
@@ -37463,7 +37646,7 @@ async function parseGraderList(candidateEvaluators, searchRoots, evalId, default
37463
37646
  if (cwd) {
37464
37647
  const resolved = await resolveFileReference3(cwd, searchRoots);
37465
37648
  if (resolved.resolvedPath) {
37466
- resolvedCwd = path44.resolve(resolved.resolvedPath);
37649
+ resolvedCwd = path43.resolve(resolved.resolvedPath);
37467
37650
  } else {
37468
37651
  logWarning2(
37469
37652
  `Code-grader evaluator '${name}' in '${evalId}': cwd not found (${resolved.displayPath})`,
@@ -37653,7 +37836,7 @@ async function parseGraderList(candidateEvaluators, searchRoots, evalId, default
37653
37836
  aggregatorPrompt = fileRef;
37654
37837
  const resolved = await resolveFileReference3(fileRef, searchRoots);
37655
37838
  if (resolved.resolvedPath) {
37656
- promptPath2 = path44.resolve(resolved.resolvedPath);
37839
+ promptPath2 = path43.resolve(resolved.resolvedPath);
37657
37840
  } else {
37658
37841
  throw new Error(
37659
37842
  `Composite aggregator in '${evalId}': prompt file not found: ${resolved.displayPath}`
@@ -38323,7 +38506,7 @@ async function parseGraderList(candidateEvaluators, searchRoots, evalId, default
38323
38506
  `${ANSI_YELLOW22}Warning: 'prompt.script' is deprecated in evaluator '${name}' in '${evalId}'. Use 'prompt.command' instead.${ANSI_RESET3}`
38324
38507
  );
38325
38508
  }
38326
- const commandArray = asStringArray(
38509
+ const commandArray = asStringArray2(
38327
38510
  rawPrompt.command ?? rawPrompt.script,
38328
38511
  `prompt.command for evaluator '${name}' in '${evalId}'`
38329
38512
  );
@@ -38333,7 +38516,7 @@ async function parseGraderList(candidateEvaluators, searchRoots, evalId, default
38333
38516
  const commandPath = commandArray[commandArray.length - 1];
38334
38517
  const resolved = await resolveFileReference3(commandPath, searchRoots);
38335
38518
  if (resolved.resolvedPath) {
38336
- resolvedPromptScript = [...commandArray.slice(0, -1), path44.resolve(resolved.resolvedPath)];
38519
+ resolvedPromptScript = [...commandArray.slice(0, -1), path43.resolve(resolved.resolvedPath)];
38337
38520
  } else {
38338
38521
  throw new Error(
38339
38522
  `Grader '${name}' in '${evalId}': prompt command file not found: ${resolved.displayPath}`
@@ -38348,7 +38531,7 @@ async function parseGraderList(candidateEvaluators, searchRoots, evalId, default
38348
38531
  prompt = fileRef;
38349
38532
  const resolved = await resolveFileReference3(fileRef, searchRoots);
38350
38533
  if (resolved.resolvedPath) {
38351
- promptPath = path44.resolve(resolved.resolvedPath);
38534
+ promptPath = path43.resolve(resolved.resolvedPath);
38352
38535
  try {
38353
38536
  await validateCustomPromptContent(promptPath);
38354
38537
  } catch (error40) {
@@ -38487,7 +38670,7 @@ async function parsePreprocessors(rawValue, searchRoots, evaluatorName, evalId)
38487
38670
  if (!type) {
38488
38671
  throw new Error(`Grader '${evaluatorName}' in '${evalId}': preprocessor.type is required`);
38489
38672
  }
38490
- const command = asStringArray(
38673
+ const command = asStringArray2(
38491
38674
  rawEntry.command,
38492
38675
  `preprocessor command for evaluator '${evaluatorName}' in '${evalId}'`
38493
38676
  );
@@ -38506,7 +38689,7 @@ async function parsePreprocessors(rawValue, searchRoots, evaluatorName, evalId)
38506
38689
  preprocessors.push({
38507
38690
  type,
38508
38691
  command,
38509
- resolvedCommand: [...command.slice(0, -1), path44.resolve(resolved.resolvedPath)]
38692
+ resolvedCommand: [...command.slice(0, -1), path43.resolve(resolved.resolvedPath)]
38510
38693
  });
38511
38694
  }
38512
38695
  return preprocessors;
@@ -38573,7 +38756,7 @@ function asStringArrayStrict(value) {
38573
38756
  const result = value.filter((v) => typeof v === "string");
38574
38757
  return result.length > 0 ? result : void 0;
38575
38758
  }
38576
- function asStringArray(value, description) {
38759
+ function asStringArray2(value, description) {
38577
38760
  if (value === void 0) {
38578
38761
  return void 0;
38579
38762
  }
@@ -38601,10 +38784,10 @@ async function resolveOptionalCommandSource(command, searchRoots) {
38601
38784
  return void 0;
38602
38785
  }
38603
38786
  const resolved = await resolveFileReference3(candidate, searchRoots);
38604
- return resolved.resolvedPath ? path44.resolve(resolved.resolvedPath) : void 0;
38787
+ return resolved.resolvedPath ? path43.resolve(resolved.resolvedPath) : void 0;
38605
38788
  }
38606
38789
  function looksLikeFilePath(value) {
38607
- return path44.isAbsolute(value) || value.startsWith(".") || value.includes("/") || value.includes("\\") || /\.[cm]?[jt]sx?$|\.py$|\.sh$|\.bash$|\.rb$|\.go$|\.rs$/i.test(value);
38790
+ return path43.isAbsolute(value) || value.startsWith(".") || value.includes("/") || value.includes("\\") || /\.[cm]?[jt]sx?$|\.py$|\.sh$|\.bash$|\.rb$|\.go$|\.rs$/i.test(value);
38608
38791
  }
38609
38792
  function parseCommandToArgv(command) {
38610
38793
  if (process.platform === "win32") {
@@ -38992,7 +39175,7 @@ var IMAGE_MEDIA_TYPES = {
38992
39175
  ".bmp": "image/bmp"
38993
39176
  };
38994
39177
  function detectImageMediaType(filePath) {
38995
- const ext = path45.extname(filePath).toLowerCase();
39178
+ const ext = path44.extname(filePath).toLowerCase();
38996
39179
  return IMAGE_MEDIA_TYPES[ext];
38997
39180
  }
38998
39181
  var ANSI_YELLOW3 = "\x1B[33m";
@@ -39056,7 +39239,7 @@ async function processMessages(options) {
39056
39239
  ...cloneJsonObject(rawSegment),
39057
39240
  path: displayPath,
39058
39241
  text: fileContent,
39059
- resolvedPath: path45.resolve(resolvedPath)
39242
+ resolvedPath: path44.resolve(resolvedPath)
39060
39243
  });
39061
39244
  if (verbose) {
39062
39245
  const label = messageType === "input" ? "[File]" : "[Expected Output File]";
@@ -39180,7 +39363,7 @@ async function processExpectedMessages(options) {
39180
39363
  type: "file",
39181
39364
  path: displayPath,
39182
39365
  text: fileContent,
39183
- resolvedPath: path45.resolve(resolvedPath)
39366
+ resolvedPath: path44.resolve(resolvedPath)
39184
39367
  });
39185
39368
  if (verbose) {
39186
39369
  console.log(` [Expected Output File] Found: ${displayPath}`);
@@ -39326,7 +39509,7 @@ function matchesFilter(id, filter) {
39326
39509
  return typeof filter === "string" ? micromatch.isMatch(id, filter) : filter.some((pattern) => micromatch.isMatch(id, pattern));
39327
39510
  }
39328
39511
  function detectFormat(filePath) {
39329
- const ext = path46.extname(filePath).toLowerCase();
39512
+ const ext = path45.extname(filePath).toLowerCase();
39330
39513
  if (ext === ".jsonl") return "jsonl";
39331
39514
  if (ext === ".yaml" || ext === ".yml") return "yaml";
39332
39515
  if (ext === ".json") return "agent-skills-json";
@@ -39336,10 +39519,10 @@ function detectFormat(filePath) {
39336
39519
  );
39337
39520
  }
39338
39521
  async function loadSidecarMetadata(jsonlPath, verbose) {
39339
- const dir = path46.dirname(jsonlPath);
39340
- const base = path46.basename(jsonlPath, ".jsonl");
39341
- const sidecarPath = path46.join(dir, `${base}.yaml`);
39342
- if (!await fileExists3(sidecarPath)) {
39522
+ const dir = path45.dirname(jsonlPath);
39523
+ const base = path45.basename(jsonlPath, ".jsonl");
39524
+ const sidecarPath = path45.join(dir, `${base}.yaml`);
39525
+ if (!await fileExists2(sidecarPath)) {
39343
39526
  if (verbose) {
39344
39527
  logWarning4(`Sidecar metadata file not found: ${sidecarPath} (using defaults)`);
39345
39528
  }
@@ -39387,13 +39570,13 @@ function parseJsonlContent(content, filePath) {
39387
39570
  async function loadTestsFromJsonl(evalFilePath, repoRoot, options) {
39388
39571
  const verbose = options?.verbose ?? false;
39389
39572
  const filterPattern = options?.filter;
39390
- const absoluteTestPath = path46.resolve(evalFilePath);
39573
+ const absoluteTestPath = path45.resolve(evalFilePath);
39391
39574
  const repoRootPath = resolveToAbsolutePath(repoRoot);
39392
39575
  const searchRoots = buildSearchRoots2(absoluteTestPath, repoRootPath);
39393
39576
  const sidecar = await loadSidecarMetadata(absoluteTestPath, verbose);
39394
39577
  const rawFile = await readFile17(absoluteTestPath, "utf8");
39395
39578
  const rawCases = parseJsonlContent(rawFile, evalFilePath);
39396
- const fallbackSuiteName = path46.basename(absoluteTestPath, ".jsonl") || "eval";
39579
+ const fallbackSuiteName = path45.basename(absoluteTestPath, ".jsonl") || "eval";
39397
39580
  const suiteName = sidecar.name && sidecar.name.trim().length > 0 ? sidecar.name : fallbackSuiteName;
39398
39581
  const globalEvaluator = coerceEvaluator(sidecar.evaluator, "sidecar") ?? "llm-grader";
39399
39582
  const globalExecution = sidecar.execution;
@@ -39790,7 +39973,7 @@ function interpolateRawEvalCase(raw, vars) {
39790
39973
  }
39791
39974
  async function readTestSuiteMetadata(testFilePath) {
39792
39975
  try {
39793
- const absolutePath = path47.resolve(testFilePath);
39976
+ const absolutePath = path46.resolve(testFilePath);
39794
39977
  const content = await readFile18(absolutePath, "utf8");
39795
39978
  const parsed = interpolateEnv(parseYamlValue(content), process.env);
39796
39979
  if (!isJsonObject(parsed)) {
@@ -39799,8 +39982,7 @@ async function readTestSuiteMetadata(testFilePath) {
39799
39982
  return {
39800
39983
  target: extractTargetFromSuite(parsed),
39801
39984
  targets: extractTargetsFromSuite(parsed),
39802
- targetRefs: extractTargetRefsFromSuite(parsed),
39803
- trials: extractTrialsConfig(parsed)
39985
+ targetRefs: extractTargetRefsFromSuite(parsed)
39804
39986
  };
39805
39987
  } catch {
39806
39988
  return {};
@@ -39815,7 +39997,7 @@ async function loadTestSuite(evalFilePath, repoRoot, options) {
39815
39997
  return { tests: await loadTestsFromAgentSkills(evalFilePath) };
39816
39998
  }
39817
39999
  if (format === "typescript") {
39818
- const { loadTsEvalSuite: loadTsEvalSuite2 } = await import("./ts-eval-loader-HQDMXQQV-LBW3N3W6.js");
40000
+ const { loadTsEvalSuite: loadTsEvalSuite2 } = await import("./ts-eval-loader-RE43OAGX-AMRCUKBZ.js");
39819
40001
  return loadTsEvalSuite2(evalFilePath, resolveToAbsolutePath(repoRoot), options);
39820
40002
  }
39821
40003
  const { tests, parsed, suiteWorkspacePath } = await loadTestsFromYaml(
@@ -39844,7 +40026,7 @@ async function loadTests(evalFilePath, repoRoot, options) {
39844
40026
  return loadTestsFromAgentSkills(evalFilePath);
39845
40027
  }
39846
40028
  if (format === "typescript") {
39847
- const { loadTsEvalSuite: loadTsEvalSuite2 } = await import("./ts-eval-loader-HQDMXQQV-LBW3N3W6.js");
40029
+ const { loadTsEvalSuite: loadTsEvalSuite2 } = await import("./ts-eval-loader-RE43OAGX-AMRCUKBZ.js");
39848
40030
  const suite = await loadTsEvalSuite2(evalFilePath, resolveToAbsolutePath(repoRoot), options);
39849
40031
  return suite.tests;
39850
40032
  }
@@ -39853,14 +40035,14 @@ async function loadTests(evalFilePath, repoRoot, options) {
39853
40035
  }
39854
40036
  var loadEvalCases = loadTests;
39855
40037
  async function loadTestsFromYaml(evalFilePath, repoRoot, options) {
39856
- const absoluteTestPath = path47.resolve(evalFilePath);
40038
+ const absoluteTestPath = path46.resolve(evalFilePath);
39857
40039
  const rawFile = await readFile18(absoluteTestPath, "utf8");
39858
40040
  return loadTestsFromParsedYamlValue(parseYamlValue(rawFile), evalFilePath, repoRoot, options);
39859
40041
  }
39860
40042
  async function loadTestsFromParsedYamlValue(rawParsed, evalFilePath, repoRoot, options) {
39861
40043
  const verbose = options?.verbose ?? false;
39862
40044
  const filterPattern = options?.filter;
39863
- const absoluteTestPath = path47.resolve(evalFilePath);
40045
+ const absoluteTestPath = path46.resolve(evalFilePath);
39864
40046
  const repoRootPath = resolveToAbsolutePath(repoRoot);
39865
40047
  const searchRoots = buildSearchRoots2(absoluteTestPath, repoRootPath);
39866
40048
  const config2 = await loadConfig(absoluteTestPath, repoRootPath);
@@ -39871,7 +40053,7 @@ async function loadTestsFromParsedYamlValue(rawParsed, evalFilePath, repoRoot, o
39871
40053
  }
39872
40054
  const suite = interpolated;
39873
40055
  const suiteNameFromFile = asString5(suite.name)?.trim();
39874
- const fallbackSuiteName = path47.basename(absoluteTestPath).replace(/\.eval\.ya?ml$/i, "").replace(/\.ya?ml$/i, "") || "eval";
40056
+ const fallbackSuiteName = path46.basename(absoluteTestPath).replace(/\.eval\.ya?ml$/i, "").replace(/\.ya?ml$/i, "") || "eval";
39875
40057
  const suiteName = suiteNameFromFile && suiteNameFromFile.length > 0 ? suiteNameFromFile : fallbackSuiteName;
39876
40058
  const rawTestCases = resolveTests(suite);
39877
40059
  const globalEvaluator = coerceEvaluator(suite.evaluator, "global") ?? "llm-grader";
@@ -39881,10 +40063,10 @@ async function loadTestsFromParsedYamlValue(rawParsed, evalFilePath, repoRoot, o
39881
40063
  "<suite>",
39882
40064
  absoluteTestPath
39883
40065
  );
39884
- const evalFileDir = path47.dirname(absoluteTestPath);
40066
+ const evalFileDir = path46.dirname(absoluteTestPath);
39885
40067
  let expandedTestCases;
39886
40068
  if (typeof rawTestCases === "string") {
39887
- const externalPath = path47.resolve(evalFileDir, rawTestCases);
40069
+ const externalPath = path46.resolve(evalFileDir, rawTestCases);
39888
40070
  let isDir = false;
39889
40071
  try {
39890
40072
  const pathStat = await stat9(externalPath);
@@ -39939,12 +40121,41 @@ async function loadTestsFromParsedYamlValue(rawParsed, evalFilePath, repoRoot, o
39939
40121
  const skipDefaults = caseExecution?.skip_defaults === true;
39940
40122
  const caseThreshold = typeof caseExecution?.threshold === "number" && caseExecution.threshold >= 0 && caseExecution.threshold <= 1 ? caseExecution.threshold : void 0;
39941
40123
  const effectiveSuiteInputFiles = rawSuiteInputFiles && !skipDefaults ? interpolateCaseField(rawSuiteInputFiles, caseVars) : void 0;
39942
- const testInputMessages = resolveInputMessages(renderedCase, effectiveSuiteInputFiles);
40124
+ let inputCase = renderedCase;
40125
+ let inputSuiteFiles = effectiveSuiteInputFiles;
40126
+ if (renderedCase.input === void 0) {
40127
+ const promptFallback = await loadPromptMdFallback({
40128
+ evalFilePath: absoluteTestPath,
40129
+ searchRoots,
40130
+ testInputFiles: renderedCase.input_files,
40131
+ suiteInputFiles: effectiveSuiteInputFiles
40132
+ });
40133
+ if (promptFallback) {
40134
+ if (promptFallback.inputFilesSource === "test") {
40135
+ const { input_files: _inputFiles, ...caseWithoutInputFiles } = renderedCase;
40136
+ inputCase = {
40137
+ ...caseWithoutInputFiles,
40138
+ input: promptFallback.promptText,
40139
+ ...promptFallback.remainingInputFiles ? { input_files: [...promptFallback.remainingInputFiles] } : {}
40140
+ };
40141
+ inputSuiteFiles = void 0;
40142
+ } else {
40143
+ inputCase = {
40144
+ ...renderedCase,
40145
+ input: promptFallback.promptText
40146
+ };
40147
+ if (promptFallback.inputFilesSource === "suite") {
40148
+ inputSuiteFiles = promptFallback.remainingInputFiles ? [...promptFallback.remainingInputFiles] : void 0;
40149
+ }
40150
+ }
40151
+ }
40152
+ }
40153
+ const testInputMessages = resolveInputMessages(inputCase, inputSuiteFiles);
39943
40154
  const expectedMessages = resolveExpectedMessages(renderedCase) ?? [];
39944
40155
  const hasEvaluationSpec = !!outcome || expectedMessages.length > 0 || renderedCase.assertions !== void 0 || renderedCase.assert !== void 0 || Array.isArray(renderedCase.turns) && renderedCase.turns.length > 0;
39945
40156
  if (!id || !hasEvaluationSpec || !testInputMessages || testInputMessages.length === 0) {
39946
40157
  logError3(
39947
- `Skipping incomplete test: ${id ?? "unknown"}. Missing required fields: id, input, and at least one of criteria/expected_output/assertions/turns`
40158
+ `Skipping incomplete test: ${id ?? "unknown"}. Missing required fields: id, input or PROMPT.md, and at least one of criteria/expected_output/assertions/turns`
39948
40159
  );
39949
40160
  continue;
39950
40161
  }
@@ -40084,7 +40295,6 @@ function buildEvalSuiteResult(parsed, tests, suiteWorkspacePath) {
40084
40295
  const threshold = extractThreshold(parsed);
40085
40296
  return {
40086
40297
  tests,
40087
- trials: extractTrialsConfig(parsed),
40088
40298
  targets: extractTargetsFromSuite(parsed),
40089
40299
  targetRefs: extractTargetRefsFromSuite(parsed),
40090
40300
  workers: extractWorkersFromSuite(parsed),
@@ -40206,7 +40416,7 @@ function collectInputSourceReferences(inputMessages) {
40206
40416
  references.push({
40207
40417
  kind: "input_file",
40208
40418
  displayPath,
40209
- ...typeof segment.resolvedPath === "string" ? { resolvedPath: path47.resolve(segment.resolvedPath) } : {}
40419
+ ...typeof segment.resolvedPath === "string" ? { resolvedPath: path46.resolve(segment.resolvedPath) } : {}
40210
40420
  });
40211
40421
  }
40212
40422
  }
@@ -40279,7 +40489,7 @@ function collectSingleGraderSourceReferences(evaluator) {
40279
40489
  references.push({
40280
40490
  kind: "code_grader_command",
40281
40491
  displayPath: evaluator.aggregator.path,
40282
- resolvedPath: path47.resolve(evaluator.aggregator.cwd ?? "", evaluator.aggregator.path),
40492
+ resolvedPath: path46.resolve(evaluator.aggregator.cwd ?? "", evaluator.aggregator.path),
40283
40493
  graderName: evaluator.name
40284
40494
  });
40285
40495
  } else if (evaluator.aggregator.type === "llm-grader" && evaluator.aggregator.promptPath) {
@@ -40312,9 +40522,9 @@ function dedupeSourceReferences(references) {
40312
40522
  return deduped;
40313
40523
  }
40314
40524
  function toPortableRelativePath(root, candidate) {
40315
- const relative = path47.relative(root, candidate);
40316
- if (relative && !relative.startsWith("..") && !path47.isAbsolute(relative)) {
40317
- return relative.split(path47.sep).join("/");
40525
+ const relative = path46.relative(root, candidate);
40526
+ if (relative && !relative.startsWith("..") && !path46.isAbsolute(relative)) {
40527
+ return relative.split(path46.sep).join("/");
40318
40528
  }
40319
40529
  return void 0;
40320
40530
  }
@@ -40368,8 +40578,8 @@ function parseWorkspaceScriptConfig(raw, evalFileDir) {
40368
40578
  if (!command) return void 0;
40369
40579
  const timeoutMs = typeof obj.timeout_ms === "number" ? obj.timeout_ms : void 0;
40370
40580
  let cwd = typeof obj.cwd === "string" ? obj.cwd : void 0;
40371
- if (cwd && !path47.isAbsolute(cwd)) {
40372
- cwd = path47.resolve(evalFileDir, cwd);
40581
+ if (cwd && !path46.isAbsolute(cwd)) {
40582
+ cwd = path46.resolve(evalFileDir, cwd);
40373
40583
  }
40374
40584
  const config2 = { command };
40375
40585
  if (timeoutMs !== void 0) {
@@ -40407,7 +40617,7 @@ function parseWorkspaceHooksConfig(raw, evalFileDir) {
40407
40617
  }
40408
40618
  async function resolveWorkspaceConfig(raw, evalFileDir) {
40409
40619
  if (typeof raw === "string") {
40410
- const workspaceFilePath = path47.resolve(evalFileDir, raw);
40620
+ const workspaceFilePath = path46.resolve(evalFileDir, raw);
40411
40621
  let content;
40412
40622
  try {
40413
40623
  content = await readFile18(workspaceFilePath, "utf8");
@@ -40420,7 +40630,7 @@ async function resolveWorkspaceConfig(raw, evalFileDir) {
40420
40630
  `Invalid workspace file format: ${workspaceFilePath} (expected a YAML object)`
40421
40631
  );
40422
40632
  }
40423
- const workspaceFileDir = path47.dirname(workspaceFilePath);
40633
+ const workspaceFileDir = path46.dirname(workspaceFilePath);
40424
40634
  const resolvedWorkspace = parseWorkspaceConfig(parsed, workspaceFileDir);
40425
40635
  if (resolvedWorkspace) {
40426
40636
  return { ...resolvedWorkspace, workspaceFileDir };
@@ -40454,8 +40664,8 @@ function parseWorkspaceConfig(raw, evalFileDir) {
40454
40664
  throw new Error("workspace.static has been removed. Use workspace.mode='static'.");
40455
40665
  }
40456
40666
  let template = typeof obj.template === "string" ? obj.template : void 0;
40457
- if (template && !path47.isAbsolute(template)) {
40458
- template = path47.resolve(evalFileDir, template);
40667
+ if (template && !path46.isAbsolute(template)) {
40668
+ template = path46.resolve(evalFileDir, template);
40459
40669
  }
40460
40670
  const isolation = obj.isolation === "shared" || obj.isolation === "per_test" ? obj.isolation : void 0;
40461
40671
  const repos = Array.isArray(obj.repos) ? obj.repos.map(parseRepoConfig).filter(Boolean) : void 0;
@@ -40593,7 +40803,7 @@ ${detailBlock}${ANSI_RESET6}`);
40593
40803
  }
40594
40804
  }
40595
40805
  function pathFromRoot(root) {
40596
- return root instanceof URL ? fileURLToPath5(root) : String(root);
40806
+ return root instanceof URL ? fileURLToPath4(root) : String(root);
40597
40807
  }
40598
40808
  function classifyQualityStatus(score, threshold = DEFAULT_THRESHOLD) {
40599
40809
  return score >= threshold ? "ok" : "quality_failure";
@@ -40733,18 +40943,18 @@ function validateDependencyGraph(tests) {
40733
40943
  }
40734
40944
  const visited = /* @__PURE__ */ new Set();
40735
40945
  const visiting = /* @__PURE__ */ new Set();
40736
- function visit(id, path522) {
40946
+ function visit(id, path51) {
40737
40947
  if (visiting.has(id)) {
40738
- const cycle = [...path522.slice(path522.indexOf(id)), id];
40948
+ const cycle = [...path51.slice(path51.indexOf(id)), id];
40739
40949
  throw new Error(`Circular dependency detected: ${cycle.join(" \u2192 ")}`);
40740
40950
  }
40741
40951
  if (visited.has(id)) return;
40742
40952
  visiting.add(id);
40743
- path522.push(id);
40953
+ path51.push(id);
40744
40954
  for (const dep of depMap.get(id) ?? []) {
40745
- visit(dep, path522);
40955
+ visit(dep, path51);
40746
40956
  }
40747
- path522.pop();
40957
+ path51.pop();
40748
40958
  visiting.delete(id);
40749
40959
  visited.add(id);
40750
40960
  }
@@ -40850,7 +41060,7 @@ async function gradePreparedEvalCase(options) {
40850
41060
  model
40851
41061
  });
40852
41062
  const evaluatorRegistry = buildEvaluatorRegistry(evaluators, runtime.resolveGraderProvider);
40853
- const discoveryBaseDir = evalFilePath ? path48.dirname(path48.resolve(evalFilePath)) : process.cwd();
41063
+ const discoveryBaseDir = evalFilePath ? path47.dirname(path47.resolve(evalFilePath)) : process.cwd();
40854
41064
  await discoverAssertions(typeRegistry, discoveryBaseDir);
40855
41065
  await discoverGraders(typeRegistry, discoveryBaseDir);
40856
41066
  let fileChanges;
@@ -41042,7 +41252,7 @@ async function runEvaluation(options) {
41042
41252
  }
41043
41253
  const evaluatorRegistry = buildEvaluatorRegistry(evaluators, resolveGraderProvider);
41044
41254
  const typeRegistry = createBuiltinRegistry();
41045
- const discoveryBaseDir = evalFilePath ? path48.dirname(path48.resolve(evalFilePath)) : process.cwd();
41255
+ const discoveryBaseDir = evalFilePath ? path47.dirname(path47.resolve(evalFilePath)) : process.cwd();
41046
41256
  const evalDir = discoveryBaseDir;
41047
41257
  await discoverAssertions(typeRegistry, discoveryBaseDir);
41048
41258
  await discoverGraders(typeRegistry, discoveryBaseDir);
@@ -42248,7 +42458,8 @@ async function runEvalCaseWithTrials(options, trialsConfig) {
42248
42458
  costUsd: trialCost,
42249
42459
  executionStatus: result.executionStatus,
42250
42460
  failureStage: result.failureStage,
42251
- failureReasonCode: result.failureReasonCode
42461
+ failureReasonCode: result.failureReasonCode,
42462
+ result
42252
42463
  };
42253
42464
  trialResults.push(trial);
42254
42465
  if (trialCost !== void 0) {
@@ -42263,7 +42474,7 @@ async function runEvalCaseWithTrials(options, trialsConfig) {
42263
42474
  costLimited = true;
42264
42475
  break;
42265
42476
  }
42266
- if (trialsConfig.strategy === "pass_at_k" && trialVerdict === "pass") {
42477
+ if (trialsConfig.strategy === "pass_at_k" && trialsConfig.earlyExit !== false && trialVerdict === "pass") {
42267
42478
  break;
42268
42479
  }
42269
42480
  }
@@ -42574,7 +42785,7 @@ async function runEvaluatorList(options) {
42574
42785
  dockerConfig,
42575
42786
  dependencyResults
42576
42787
  };
42577
- const evalFileDir = evalCase.file_paths[0] ? path48.dirname(evalCase.file_paths[0]) : process.cwd();
42788
+ const evalFileDir = evalCase.file_paths[0] ? path47.dirname(evalCase.file_paths[0]) : process.cwd();
42578
42789
  const dispatchContext = {
42579
42790
  graderProvider,
42580
42791
  targetResolver,
@@ -43649,6 +43860,12 @@ function fromResultArtifactPointerWire(pointer) {
43649
43860
  };
43650
43861
  }
43651
43862
  var TOOL_STATUS_VALUES = ["ok", "error", "timeout", "cancelled", "unknown"];
43863
+ var TIMING_SOURCE_VALUES = [
43864
+ "provider_reported",
43865
+ "token_estimated",
43866
+ "aggregate",
43867
+ "unavailable"
43868
+ ];
43652
43869
  var FILE_READ_KEY_SET = /* @__PURE__ */ new Set([
43653
43870
  "file",
43654
43871
  "filename",
@@ -43719,6 +43936,23 @@ var ReasoningBlockWireSchema = external_exports.object({
43719
43936
  event_id: external_exports.string().optional(),
43720
43937
  content: external_exports.string().optional()
43721
43938
  }).strict();
43939
+ var MetricsTimingWireSchema = external_exports.object({
43940
+ total_tokens: external_exports.number().int().nonnegative(),
43941
+ duration_ms: external_exports.number().nonnegative(),
43942
+ total_duration_seconds: external_exports.number().nonnegative(),
43943
+ cost_usd: external_exports.number().nonnegative().nullable(),
43944
+ token_usage: external_exports.object({
43945
+ input: external_exports.number().int().nonnegative(),
43946
+ output: external_exports.number().int().nonnegative(),
43947
+ reasoning: external_exports.number().int().nonnegative()
43948
+ }).strict(),
43949
+ usage_sources: external_exports.object({
43950
+ token_usage: external_exports.enum(TIMING_SOURCE_VALUES),
43951
+ total_tokens: external_exports.enum(TIMING_SOURCE_VALUES),
43952
+ duration: external_exports.enum(TIMING_SOURCE_VALUES),
43953
+ cost: external_exports.enum(TIMING_SOURCE_VALUES)
43954
+ }).strict()
43955
+ }).strict();
43722
43956
  var MetricsWireSchema = external_exports.object({
43723
43957
  tool_calls: external_exports.record(external_exports.string(), external_exports.number().int().nonnegative()),
43724
43958
  tool_call_counts: external_exports.record(external_exports.string(), external_exports.number().int().nonnegative()),
@@ -43760,7 +43994,8 @@ var MetricsArtifactWireSchema = external_exports.object({
43760
43994
  grading_path: external_exports.string().optional(),
43761
43995
  timing_path: external_exports.string().optional()
43762
43996
  }).strict(),
43763
- metrics: MetricsWireSchema
43997
+ metrics: MetricsWireSchema,
43998
+ timing: MetricsTimingWireSchema.optional()
43764
43999
  }).strict();
43765
44000
  function dropUndefined6(value) {
43766
44001
  return Object.fromEntries(
@@ -44346,6 +44581,7 @@ var RESULT_ROW_ALIASES = {
44346
44581
  rawProviderLogPath: "raw_provider_log_path",
44347
44582
  responsePath: "response_path",
44348
44583
  startTime: "start_time",
44584
+ summaryPath: "summary_path",
44349
44585
  targetsPath: "targets_path",
44350
44586
  taskDir: "task_dir",
44351
44587
  testId: "test_id",
@@ -44451,7 +44687,7 @@ function buildSnakeCaseOnlyFieldError(field, context) {
44451
44687
  );
44452
44688
  }
44453
44689
  function looksLikeResultRow(value) {
44454
- return typeof value.test_id === "string" || Object.hasOwn(value, "score") || Object.hasOwn(value, "trace") || Object.hasOwn(value, "spans") || Object.hasOwn(value, "target") || Object.hasOwn(value, "grading_path") || Object.hasOwn(value, "timing_path");
44690
+ return typeof value.test_id === "string" || Object.hasOwn(value, "score") || Object.hasOwn(value, "trace") || Object.hasOwn(value, "spans") || Object.hasOwn(value, "target") || Object.hasOwn(value, "summary_path") || Object.hasOwn(value, "grading_path") || Object.hasOwn(value, "timing_path");
44455
44691
  }
44456
44692
  function normalizeResultRow(value, context = {}) {
44457
44693
  if (!isRecord6(value)) {
@@ -44480,7 +44716,8 @@ function normalizeResultRow(value, context = {}) {
44480
44716
  return normalized;
44481
44717
  }
44482
44718
  var RESULT_INDEX_FILENAME = "index.jsonl";
44483
- var TIMING_SOURCE_VALUES = [
44719
+ var RUN_SUMMARY_FILENAME = "summary.json";
44720
+ var TIMING_SOURCE_VALUES2 = [
44484
44721
  "provider_reported",
44485
44722
  "token_estimated",
44486
44723
  "aggregate",
@@ -44504,30 +44741,27 @@ function deduplicateByTestIdTarget(results) {
44504
44741
  return deduped;
44505
44742
  }
44506
44743
  async function aggregateRunDir(runDir, options) {
44507
- const indexPath = path49.join(runDir, RESULT_INDEX_FILENAME);
44744
+ const indexPath = path48.join(runDir, RESULT_INDEX_FILENAME);
44508
44745
  const content = await readFile20(indexPath, "utf8");
44509
44746
  const allResults = parseJsonlResults(content);
44510
44747
  const results = deduplicateByTestIdTarget(allResults);
44511
- const timing = buildTimingArtifact(results);
44512
- const timingPath = path49.join(runDir, "timing.json");
44513
- await writeFile10(timingPath, `${JSON.stringify(timing, null, 2)}
44514
- `, "utf8");
44515
- const plannedTestCount = options?.plannedTestCount ?? await readPlannedTestCount(path49.join(runDir, "benchmark.json"));
44516
- const benchmark = buildBenchmarkArtifact(
44748
+ const plannedTestCount = options?.plannedTestCount ?? await readPlannedTestCount(path48.join(runDir, RUN_SUMMARY_FILENAME));
44749
+ const summary = buildRunSummaryArtifact(
44517
44750
  results,
44518
44751
  options?.evalFile,
44519
44752
  options?.experiment,
44520
- plannedTestCount
44753
+ plannedTestCount,
44754
+ options?.experimentMetadata
44521
44755
  );
44522
- const benchmarkPath = path49.join(runDir, "benchmark.json");
44523
- await writeFile10(benchmarkPath, `${JSON.stringify(benchmark, null, 2)}
44756
+ const summaryPath = path48.join(runDir, RUN_SUMMARY_FILENAME);
44757
+ await writeFile10(summaryPath, `${JSON.stringify(summary, null, 2)}
44524
44758
  `, "utf8");
44525
44759
  const targetSet = new Set(results.map((r) => r.target ?? "unknown"));
44526
- return { benchmarkPath, timingPath, testCount: results.length, targetCount: targetSet.size };
44760
+ return { summaryPath, testCount: results.length, targetCount: targetSet.size };
44527
44761
  }
44528
- async function readPlannedTestCount(benchmarkPath) {
44762
+ async function readPlannedTestCount(summaryPath) {
44529
44763
  try {
44530
- const raw = await readFile20(benchmarkPath, "utf8");
44764
+ const raw = await readFile20(summaryPath, "utf8");
44531
44765
  const parsed = JSON.parse(raw);
44532
44766
  const value = parsed.metadata?.planned_test_count;
44533
44767
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
@@ -44637,6 +44871,60 @@ function toIndexScore(score) {
44637
44871
  function toIndexScores(scores) {
44638
44872
  return scores?.map(toIndexScore);
44639
44873
  }
44874
+ function trialRunDirName(attempt) {
44875
+ return `run-${attempt + 1}`;
44876
+ }
44877
+ function hasPersistedTrialRuns(result) {
44878
+ return (result.trials ?? []).some((trial) => trial.result !== void 0);
44879
+ }
44880
+ function toTrialArtifacts(trials) {
44881
+ if (!trials || trials.length === 0) {
44882
+ return void 0;
44883
+ }
44884
+ return trials.map((trial) => ({
44885
+ attempt: trial.attempt,
44886
+ run_path: trial.result ? trialRunDirName(trial.attempt) : void 0,
44887
+ score: trial.score,
44888
+ verdict: trial.verdict,
44889
+ scores: toIndexScores(trial.scores),
44890
+ error: trial.error,
44891
+ cost_usd: trial.costUsd,
44892
+ execution_status: trial.executionStatus,
44893
+ failure_stage: trial.failureStage,
44894
+ failure_reason_code: trial.failureReasonCode
44895
+ }));
44896
+ }
44897
+ function toIndexTrialArtifacts(result) {
44898
+ return toTrialArtifacts(result.trials) ?? toTrialArtifacts([singleRunTrial(result)]) ?? [];
44899
+ }
44900
+ function toTrialAggregationArtifact(aggregation) {
44901
+ if (!aggregation) {
44902
+ return void 0;
44903
+ }
44904
+ switch (aggregation.strategy) {
44905
+ case "pass_at_k":
44906
+ return {
44907
+ strategy: aggregation.strategy,
44908
+ passed_attempts: aggregation.passedAttempts,
44909
+ total_attempts: aggregation.totalAttempts
44910
+ };
44911
+ case "mean":
44912
+ return {
44913
+ strategy: aggregation.strategy,
44914
+ mean: aggregation.mean,
44915
+ min: aggregation.min,
44916
+ max: aggregation.max
44917
+ };
44918
+ case "confidence_interval":
44919
+ return {
44920
+ strategy: aggregation.strategy,
44921
+ mean: aggregation.mean,
44922
+ ci95_lower: aggregation.ci95Lower,
44923
+ ci95_upper: aggregation.ci95Upper,
44924
+ stddev: aggregation.stddev
44925
+ };
44926
+ }
44927
+ }
44640
44928
  function dropUndefined7(value) {
44641
44929
  return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
44642
44930
  }
@@ -44658,6 +44946,216 @@ function toIndexRerunSource(value) {
44658
44946
  source_timestamp: value.sourceTimestamp
44659
44947
  });
44660
44948
  }
44949
+ function resultDurationSeconds(result) {
44950
+ const durationMs = result.durationMs ?? result.trace?.durationMs ?? result.evalRun?.durationMs ?? 0;
44951
+ return Math.round(durationMs / 1e3 * 1e3) / 1e3;
44952
+ }
44953
+ function resultDurationMs(result) {
44954
+ const durationMs = result.durationMs ?? result.trace?.durationMs ?? result.evalRun?.durationMs;
44955
+ return typeof durationMs === "number" && Number.isFinite(durationMs) ? durationMs : void 0;
44956
+ }
44957
+ function roundMillis(value) {
44958
+ return Math.round(value * 1e3) / 1e3;
44959
+ }
44960
+ function roundSecondsFromMs(value) {
44961
+ return Math.round(value / 1e3 * 1e3) / 1e3;
44962
+ }
44963
+ function repeatAttemptResults(result) {
44964
+ const trialResults = (result.trials ?? []).map((trial) => trial.result).filter((trialResult) => trialResult !== void 0);
44965
+ return trialResults.length > 0 ? trialResults : [result];
44966
+ }
44967
+ function buildRepeatAggregateTimingArtifact(result) {
44968
+ const attemptResults = repeatAttemptResults(result);
44969
+ const timing = buildTimingArtifact(attemptResults);
44970
+ const durationsMs = attemptResults.map(resultDurationMs).filter((durationMs) => durationMs !== void 0);
44971
+ if (durationsMs.length === 0) {
44972
+ return timing;
44973
+ }
44974
+ const stats = computeStats(durationsMs);
44975
+ const minMs = Math.min(...durationsMs);
44976
+ const maxMs = Math.max(...durationsMs);
44977
+ return {
44978
+ ...timing,
44979
+ mean_duration_ms: stats.mean,
44980
+ mean_duration_seconds: roundSecondsFromMs(stats.mean),
44981
+ duration_stats: {
44982
+ count: durationsMs.length,
44983
+ mean_ms: stats.mean,
44984
+ mean_seconds: roundSecondsFromMs(stats.mean),
44985
+ stddev_ms: stats.stddev,
44986
+ stddev_seconds: roundSecondsFromMs(stats.stddev),
44987
+ min_ms: roundMillis(minMs),
44988
+ max_ms: roundMillis(maxMs)
44989
+ }
44990
+ };
44991
+ }
44992
+ function formatRepeatPassRate(passedRuns, totalRuns) {
44993
+ if (totalRuns === 0) {
44994
+ return "0%";
44995
+ }
44996
+ const percent = Math.round(passedRuns / totalRuns * 1e3) / 10;
44997
+ return `${Number.isInteger(percent) ? percent.toFixed(0) : percent.toFixed(1)}%`;
44998
+ }
44999
+ function fallbackRepeatFingerprint(result) {
45000
+ return createHash7("sha256").update(
45001
+ JSON.stringify({
45002
+ test_id: result.testId ?? "unknown",
45003
+ target: result.target ?? "unknown",
45004
+ trial_count: result.trials?.length ?? 0,
45005
+ aggregation: result.aggregation
45006
+ })
45007
+ ).digest("hex");
45008
+ }
45009
+ function buildRepeatCaseSummaryArtifact(result, timing, fingerprint) {
45010
+ const trials = result.trials ?? [];
45011
+ const totalRuns = trials.length > 0 ? trials.length : 1;
45012
+ const passedRuns = trials.length > 0 ? trials.filter((trial) => trial.verdict === "pass").length : result.executionStatus !== "execution_error" && result.score >= DEFAULT_THRESHOLD ? 1 : 0;
45013
+ const fallbackMeanMs = totalRuns > 0 ? roundMillis(timing.duration_ms / totalRuns) : 0;
45014
+ const meanDurationMs = timing.mean_duration_ms ?? fallbackMeanMs;
45015
+ return {
45016
+ total_runs: totalRuns,
45017
+ passed_runs: passedRuns,
45018
+ pass_rate: formatRepeatPassRate(passedRuns, totalRuns),
45019
+ mean_duration_ms: meanDurationMs,
45020
+ mean_duration_seconds: timing.mean_duration_seconds ?? roundSecondsFromMs(meanDurationMs),
45021
+ fingerprint: fingerprint ?? fallbackRepeatFingerprint(result),
45022
+ total_tokens: timing.total_tokens,
45023
+ duration_ms: timing.duration_ms,
45024
+ total_duration_seconds: timing.total_duration_seconds,
45025
+ duration_stats: timing.duration_stats,
45026
+ cost_usd: timing.cost_usd,
45027
+ token_usage: timing.token_usage,
45028
+ usage_sources: timing.usage_sources
45029
+ };
45030
+ }
45031
+ function toVercelRunStatus(trial, result) {
45032
+ if (trial.executionStatus === "execution_error" || result.executionStatus === "execution_error") {
45033
+ return "error";
45034
+ }
45035
+ return trial.verdict === "pass" ? "passed" : "failed";
45036
+ }
45037
+ function toFilePathList(entries) {
45038
+ return entries.map((entry) => isRecord7(entry) && typeof entry.path === "string" ? entry.path : void 0).filter((entry) => entry !== void 0);
45039
+ }
45040
+ function buildVercelRunResultArtifact(params) {
45041
+ const metrics = params.metricsArtifact.metrics;
45042
+ return dropUndefined7({
45043
+ status: toVercelRunStatus(params.trial, params.result),
45044
+ duration_ms: resultDurationMs(params.result),
45045
+ duration_seconds: resultDurationSeconds(params.result),
45046
+ model: params.result.target ?? "unknown",
45047
+ grading_path: "./grading.json",
45048
+ transcript_path: params.hasTranscript ? "./transcript.json" : void 0,
45049
+ transcript_raw_path: params.hasTranscript ? "./transcript-raw.jsonl" : void 0,
45050
+ o11y: {
45051
+ total_turns: metrics.total_turns,
45052
+ tool_calls: metrics.tool_calls,
45053
+ total_tool_calls: metrics.total_tool_calls,
45054
+ web_fetches: metrics.web_fetches,
45055
+ files_read: toFilePathList(metrics.files_read),
45056
+ files_modified: toFilePathList(metrics.files_modified),
45057
+ shell_commands: metrics.shell_commands,
45058
+ errors: metrics.errors,
45059
+ thinking_blocks: metrics.thinking_blocks
45060
+ },
45061
+ output_paths: params.hasOutput ? { answer: "./outputs/answer.md" } : void 0,
45062
+ timing: params.metricsArtifact.timing
45063
+ });
45064
+ }
45065
+ function singleRunTrial(result) {
45066
+ return {
45067
+ attempt: 0,
45068
+ score: result.score,
45069
+ verdict: result.executionStatus !== "execution_error" && result.score >= DEFAULT_THRESHOLD ? "pass" : "fail",
45070
+ scores: result.scores,
45071
+ error: result.error,
45072
+ costUsd: result.costUsd,
45073
+ executionStatus: result.executionStatus,
45074
+ failureStage: result.failureStage,
45075
+ failureReasonCode: result.failureReasonCode,
45076
+ result
45077
+ };
45078
+ }
45079
+ function materializedRunTrials(result) {
45080
+ const persisted = (result.trials ?? []).filter((trial) => trial.result !== void 0);
45081
+ return persisted.length > 0 ? persisted : [singleRunTrial(result)];
45082
+ }
45083
+ async function writeTrialRunArtifacts(params) {
45084
+ const result = params.trial.result;
45085
+ if (!result) {
45086
+ return;
45087
+ }
45088
+ const runDirName = trialRunDirName(params.trial.attempt);
45089
+ const runDir = path48.join(params.parentTestDir, runDirName);
45090
+ const grading = buildGradingArtifact(result, { includeTrials: false });
45091
+ const timing = buildTimingArtifact([result]);
45092
+ const gradingPath = path48.join(runDir, "grading.json");
45093
+ const timingPath = path48.join(runDir, "timing.json");
45094
+ const metricsPath = path48.join(runDir, CANONICAL_METRICS_ARTIFACT_PATH);
45095
+ const outputsDir = path48.join(runDir, "outputs");
45096
+ const answerOutputPath = result.output.length > 0 ? path48.join(outputsDir, "answer.md") : void 0;
45097
+ const attemptRunId = params.runId ? `${params.runId}:${runDirName}` : `${result.testId}:${result.target}:${runDirName}`;
45098
+ const envelope = buildTraceEnvelopeSidecar({
45099
+ result,
45100
+ outputDir: params.outputDir,
45101
+ testDir: runDir,
45102
+ evalPath: resolveEnvelopeEvalPath(result, params.testByTestId, params.evalFile),
45103
+ experiment: params.experiment,
45104
+ runId: attemptRunId,
45105
+ duplicatePolicy: params.duplicatePolicy
45106
+ });
45107
+ const hasTranscript = hasTranscriptProjection(result, envelope);
45108
+ const transcriptPath = hasTranscript ? path48.join(runDir, "transcript.json") : void 0;
45109
+ const transcriptRawPath = hasTranscript ? path48.join(runDir, "transcript-raw.jsonl") : void 0;
45110
+ await mkdir18(runDir, { recursive: true });
45111
+ await writeFile10(gradingPath, `${JSON.stringify(grading, null, 2)}
45112
+ `, "utf8");
45113
+ await writeFile10(timingPath, `${JSON.stringify(timing, null, 2)}
45114
+ `, "utf8");
45115
+ await mkdir18(outputsDir, { recursive: true });
45116
+ if (answerOutputPath) {
45117
+ await writeFile10(answerOutputPath, result.output, "utf8");
45118
+ }
45119
+ const rawProviderLogSource = rawProviderLogSourcePath(result);
45120
+ if (rawProviderLogSource) {
45121
+ await copyRawProviderLogArtifact(rawProviderLogSource, runDir);
45122
+ }
45123
+ if (transcriptPath && transcriptRawPath) {
45124
+ await writeFile10(
45125
+ transcriptPath,
45126
+ `${JSON.stringify(traceEnvelopeToTranscriptMessages(envelope), null, 2)}
45127
+ `,
45128
+ "utf8"
45129
+ );
45130
+ await writeTranscriptJsonl(transcriptRawPath, result, envelope);
45131
+ }
45132
+ const metricsArtifact = await writeMetricsArtifact({
45133
+ filePath: metricsPath,
45134
+ result,
45135
+ envelope,
45136
+ traceArtifactPath: "transcript.json",
45137
+ transcriptArtifactPath: transcriptRawPath ? "transcript-raw.jsonl" : void 0,
45138
+ gradingArtifactPath: "grading.json",
45139
+ timingArtifactPath: "timing.json",
45140
+ timing
45141
+ });
45142
+ await writeFile10(
45143
+ path48.join(runDir, "result.json"),
45144
+ `${JSON.stringify(
45145
+ buildVercelRunResultArtifact({
45146
+ trial: params.trial,
45147
+ result,
45148
+ metricsArtifact,
45149
+ hasTranscript,
45150
+ hasOutput: result.output.length > 0
45151
+ }),
45152
+ null,
45153
+ 2
45154
+ )}
45155
+ `,
45156
+ "utf8"
45157
+ );
45158
+ }
44661
45159
  function toIndexPreparedAttempt(value) {
44662
45160
  if (!isRecord7(value)) {
44663
45161
  return void 0;
@@ -44711,13 +45209,12 @@ function buildExportMetadata(duplicatePolicy, projectionIdentity, options) {
44711
45209
  skipped: options?.skipped
44712
45210
  };
44713
45211
  }
44714
- function buildGradingArtifact(result) {
45212
+ function buildGradingArtifact(result, options) {
44715
45213
  const assertions = buildAssertions(result);
44716
45214
  const passed = assertions.filter((e) => e.passed).length;
44717
45215
  const failed = assertions.filter((e) => !e.passed).length;
44718
45216
  const total = assertions.length;
44719
- const { toolCalls, total: totalToolCalls } = countToolCalls(result);
44720
- const errorsEncountered = result.error ? 1 : 0;
45217
+ const includeTrials = options?.includeTrials ?? true;
44721
45218
  return {
44722
45219
  assertions,
44723
45220
  summary: {
@@ -44726,17 +45223,14 @@ function buildGradingArtifact(result) {
44726
45223
  total,
44727
45224
  pass_rate: total > 0 ? Math.round(passed / total * 1e3) / 1e3 : 0
44728
45225
  },
44729
- execution_metrics: {
44730
- tool_calls: toolCalls,
44731
- total_tool_calls: totalToolCalls,
44732
- errors_encountered: errorsEncountered
44733
- },
44734
45226
  graders: buildEvaluators(result.scores),
44735
45227
  workspace_changes: parseWorkspaceChanges(result.fileChanges),
44736
45228
  conversation: result.conversationId ? {
44737
45229
  turns: result.trace?.messages.filter((message) => message.role === "assistant").length ?? 0,
44738
45230
  conversation_id: result.conversationId
44739
- } : void 0
45231
+ } : void 0,
45232
+ trials: includeTrials ? toIndexTrialArtifacts(result) : void 0,
45233
+ aggregation: includeTrials ? toTrialAggregationArtifact(result.aggregation) : void 0
44740
45234
  };
44741
45235
  }
44742
45236
  function timingMetadataSource(metadata, sourceKey) {
@@ -44744,7 +45238,7 @@ function timingMetadataSource(metadata, sourceKey) {
44744
45238
  const usageSummary = metadata?.usage_summary;
44745
45239
  const legacyKey = sourceKey === "duration" ? "duration_source" : sourceKey === "cost" ? "cost_source" : "token_usage_source";
44746
45240
  const value = isRecord7(usageSources) ? usageSources[sourceKey] : isRecord7(usageSummary) ? usageSummary[legacyKey] : metadata?.[legacyKey];
44747
- return typeof value === "string" && TIMING_SOURCE_VALUES.includes(value) ? value : void 0;
45241
+ return typeof value === "string" && TIMING_SOURCE_VALUES2.includes(value) ? value : void 0;
44748
45242
  }
44749
45243
  function sumMessageTokenUsage(messages) {
44750
45244
  let sawUsage = false;
@@ -44835,7 +45329,7 @@ function buildTimingArtifact(results) {
44835
45329
  }
44836
45330
  };
44837
45331
  }
44838
- function buildBenchmarkArtifact(results, evalFile = "", experiment, plannedTestCount) {
45332
+ function buildRunSummaryArtifact(results, evalFile = "", experiment, plannedTestCount, experimentMetadata) {
44839
45333
  const targetSet = /* @__PURE__ */ new Set();
44840
45334
  const testIdSet = /* @__PURE__ */ new Set();
44841
45335
  for (const result of results) {
@@ -44908,23 +45402,26 @@ function buildBenchmarkArtifact(results, evalFile = "", experiment, plannedTestC
44908
45402
  targets,
44909
45403
  tests_run: testIds,
44910
45404
  experiment,
45405
+ experiment_config: experimentMetadata,
44911
45406
  planned_test_count: plannedTestCount
44912
45407
  },
44913
45408
  run_summary: runSummary,
44914
45409
  per_grader_summary: perEvaluatorSummary,
45410
+ timing: buildTimingArtifact(results),
44915
45411
  notes
44916
45412
  };
44917
45413
  }
44918
- async function writeInitialBenchmarkArtifact(runDir, options) {
45414
+ async function writeInitialRunSummaryArtifact(runDir, options) {
44919
45415
  await mkdir18(runDir, { recursive: true });
44920
- const stub = buildBenchmarkArtifact(
45416
+ const stub = buildRunSummaryArtifact(
44921
45417
  [],
44922
45418
  options.evalFile,
44923
45419
  options.experiment,
44924
- options.plannedTestCount
45420
+ options.plannedTestCount,
45421
+ options.experimentMetadata
44925
45422
  );
44926
- const benchmarkPath = path49.join(runDir, "benchmark.json");
44927
- await writeFile10(benchmarkPath, `${JSON.stringify(stub, null, 2)}
45423
+ const summaryPath = path48.join(runDir, RUN_SUMMARY_FILENAME);
45424
+ await writeFile10(summaryPath, `${JSON.stringify(stub, null, 2)}
44928
45425
  `, "utf8");
44929
45426
  }
44930
45427
  function buildAggregateGradingArtifact(results) {
@@ -44973,23 +45470,10 @@ function buildArtifactSubdir(result) {
44973
45470
  segments.push(safeArtifactPathSegment(evalSet, "default"));
44974
45471
  }
44975
45472
  segments.push(safeTestId(result.testId));
44976
- return path49.posix.join(...segments);
44977
- }
44978
- function formatOutputMarkdown(output) {
44979
- return output.map((msg) => `@[${msg.role}]:
44980
- ${String(msg.content ?? "")}`).join("\n\n");
44981
- }
44982
- function extractInput(result) {
44983
- const input = result.input;
44984
- if (!input) return null;
44985
- if (typeof input === "string") return input;
44986
- if (Array.isArray(input) && input.length > 0) {
44987
- return formatOutputMarkdown(input);
44988
- }
44989
- return null;
45473
+ return path48.posix.join(...segments);
44990
45474
  }
44991
45475
  function toRelativeArtifactPath(outputDir, filePath) {
44992
- return path49.relative(outputDir, filePath).split(path49.sep).join("/");
45476
+ return path48.relative(outputDir, filePath).split(path48.sep).join("/");
44993
45477
  }
44994
45478
  function findResultSourceTest(result, testByTestId) {
44995
45479
  return testByTestId.get(result.testId ?? "unknown");
@@ -45005,15 +45489,12 @@ function rawProviderLogSourcePath(result) {
45005
45489
  const sourcePath = result.rawProviderLogPath?.trim();
45006
45490
  return sourcePath ? sourcePath : void 0;
45007
45491
  }
45008
- function rawProviderLogArtifactPath(testDir) {
45009
- return path49.join(testDir, "provider.log");
45010
- }
45011
45492
  async function copyRawProviderLogArtifact(sourcePath, testDir) {
45012
- const destinationPath = rawProviderLogArtifactPath(testDir);
45013
- if (path49.resolve(sourcePath) === path49.resolve(destinationPath)) {
45493
+ const destinationPath = path48.join(testDir, "provider.log");
45494
+ if (path48.resolve(sourcePath) === path48.resolve(destinationPath)) {
45014
45495
  return destinationPath;
45015
45496
  }
45016
- await mkdir18(path49.dirname(destinationPath), { recursive: true });
45497
+ await mkdir18(path48.dirname(destinationPath), { recursive: true });
45017
45498
  await copyFile3(sourcePath, destinationPath);
45018
45499
  return destinationPath;
45019
45500
  }
@@ -45021,14 +45502,13 @@ function buildTraceEnvelopeSidecar(params) {
45021
45502
  const hasTranscript = resultHasExecutionTraceTranscript(params.result);
45022
45503
  return buildTraceEnvelopeFromEvaluationResult(params.result, {
45023
45504
  evalPath: params.evalPath,
45024
- runId: params.runId ?? path49.basename(params.outputDir),
45505
+ runId: params.runId ?? path48.basename(params.outputDir),
45025
45506
  experiment: params.experiment,
45026
45507
  source: { path: RESULT_INDEX_FILENAME },
45027
45508
  capture: { content: "full", redactionLevel: "none", redactedFields: [] },
45028
45509
  artifacts: {
45029
45510
  trace_path: CANONICAL_TRACE_ARTIFACT_PATH,
45030
45511
  answer_path: params.result.output.length > 0 ? "outputs/answer.md" : void 0,
45031
- response_path: params.result.output.length > 0 ? "outputs/response.md" : void 0,
45032
45512
  transcript_path: hasTranscript ? CANONICAL_TRANSCRIPT_ARTIFACT_PATH : void 0,
45033
45513
  metrics_path: CANONICAL_METRICS_ARTIFACT_PATH,
45034
45514
  raw_provider_log_path: rawProviderLogSourcePath(params.result) ? "provider.log" : void 0
@@ -45036,59 +45516,6 @@ function buildTraceEnvelopeSidecar(params) {
45036
45516
  duplicatePolicy: params.duplicatePolicy
45037
45517
  });
45038
45518
  }
45039
- async function writeTraceEnvelopeSidecar(params) {
45040
- const envelope = buildTraceEnvelopeSidecar(params);
45041
- await writeFile10(
45042
- path49.join(params.testDir, CANONICAL_TRACE_ARTIFACT_PATH),
45043
- `${JSON.stringify(toTraceEnvelopeWire(envelope), null, 2)}
45044
- `,
45045
- "utf8"
45046
- );
45047
- return envelope;
45048
- }
45049
- function buildSidecarArtifactKey(family, runRelativePath) {
45050
- return path49.posix.join(family, runRelativePath);
45051
- }
45052
- async function buildArtifactPointer(params) {
45053
- const content = await readFile20(params.filePath);
45054
- const sha256 = createHash7("sha256").update(content).digest("hex");
45055
- return toResultArtifactPointerWire({
45056
- ref: AGENTV_RESULTS_ARTIFACTS_REF,
45057
- key: buildSidecarArtifactKey(params.family, params.runRelativePath),
45058
- objectVersion: `sha256:${sha256}`,
45059
- path: params.runRelativePath,
45060
- sha256,
45061
- size: content.byteLength,
45062
- schemaVersion: params.schemaVersion,
45063
- mediaType: params.mediaType,
45064
- family: params.family
45065
- });
45066
- }
45067
- async function buildTracePointer(outputDir, tracePath) {
45068
- return buildArtifactPointer({
45069
- filePath: tracePath,
45070
- runRelativePath: toRelativeArtifactPath(outputDir, tracePath),
45071
- family: "traces",
45072
- schemaVersion: EXECUTION_TRACE_SCHEMA_VERSION,
45073
- mediaType: TRACE_JSON_MEDIA_TYPE
45074
- });
45075
- }
45076
- async function buildTranscriptPointer(outputDir, transcriptPath) {
45077
- const pointer = await buildArtifactPointer({
45078
- filePath: transcriptPath,
45079
- runRelativePath: toRelativeArtifactPath(outputDir, transcriptPath),
45080
- family: "transcripts",
45081
- schemaVersion: TRANSCRIPT_SCHEMA_VERSION,
45082
- mediaType: TRANSCRIPT_JSONL_MEDIA_TYPE
45083
- });
45084
- return pointer;
45085
- }
45086
- async function buildArtifactPointers(params) {
45087
- return {
45088
- trace: await buildTracePointer(params.outputDir, params.tracePath),
45089
- ...params.transcriptPath ? { transcript: await buildTranscriptPointer(params.outputDir, params.transcriptPath) } : {}
45090
- };
45091
- }
45092
45519
  function buildIndexArtifactEntry(result, options) {
45093
45520
  return {
45094
45521
  timestamp: result.timestamp,
@@ -45104,14 +45531,17 @@ function buildIndexArtifactEntry(result, options) {
45104
45531
  start_time: result.startTime,
45105
45532
  end_time: result.endTime,
45106
45533
  scores: toIndexScores(result.scores),
45534
+ trials: toIndexTrialArtifacts(result),
45535
+ aggregation: toTrialAggregationArtifact(result.aggregation),
45107
45536
  execution_status: result.executionStatus,
45108
45537
  error: result.error,
45109
45538
  failure_stage: result.failureStage,
45110
45539
  failure_reason_code: result.failureReasonCode,
45111
45540
  workspace_path: result.workspacePath,
45112
45541
  artifact_dir: options.artifactDir ? toRelativeArtifactPath(options.outputDir, options.artifactDir) : void 0,
45113
- grading_path: toRelativeArtifactPath(options.outputDir, options.gradingPath),
45114
- timing_path: toRelativeArtifactPath(options.outputDir, options.timingPath),
45542
+ grading_path: options.gradingPath ? toRelativeArtifactPath(options.outputDir, options.gradingPath) : void 0,
45543
+ timing_path: options.timingPath ? toRelativeArtifactPath(options.outputDir, options.timingPath) : void 0,
45544
+ summary_path: options.summaryPath ? toRelativeArtifactPath(options.outputDir, options.summaryPath) : void 0,
45115
45545
  output_path: options.outputPath ? toRelativeArtifactPath(options.outputDir, options.outputPath) : void 0,
45116
45546
  answer_path: options.answerPath ? toRelativeArtifactPath(options.outputDir, options.answerPath) : void 0,
45117
45547
  trace_path: options.tracePath ? toRelativeArtifactPath(options.outputDir, options.tracePath) : void 0,
@@ -45119,8 +45549,6 @@ function buildIndexArtifactEntry(result, options) {
45119
45549
  metrics_path: options.metricsPath ? toRelativeArtifactPath(options.outputDir, options.metricsPath) : void 0,
45120
45550
  raw_provider_log_path: options.rawProviderLogPath ? toRelativeArtifactPath(options.outputDir, options.rawProviderLogPath) : void 0,
45121
45551
  artifact_pointers: options.artifactPointers,
45122
- input_path: options.inputPath ? toRelativeArtifactPath(options.outputDir, options.inputPath) : void 0,
45123
- response_path: options.responsePath ? toRelativeArtifactPath(options.outputDir, options.responsePath) : void 0,
45124
45552
  ...options.extraIndexFields,
45125
45553
  external_trace: toIndexExternalTrace(result, options.projectionIdentity?.dimensions.runId),
45126
45554
  projection_identity: options.projectionIdentity ? toProjectionIdentityWire(options.projectionIdentity) : void 0,
@@ -45130,10 +45558,10 @@ function buildIndexArtifactEntry(result, options) {
45130
45558
  }
45131
45559
  function buildResultIndexArtifact(result, extraIndexFields, options) {
45132
45560
  const artifactSubdir = buildArtifactSubdir(result);
45133
- const input = extractInput(result);
45134
45561
  const hasAnswer = result.output.length > 0;
45135
45562
  const hasTranscript = resultHasExecutionTraceTranscript(result);
45136
- const hasRawProviderLog = rawProviderLogSourcePath(result) !== void 0;
45563
+ const isSingleRun = !hasPersistedTrialRuns(result);
45564
+ const singleRunDir = path48.posix.join(artifactSubdir, trialRunDirName(0));
45137
45565
  return {
45138
45566
  timestamp: result.timestamp,
45139
45567
  test_id: result.testId ?? "unknown",
@@ -45148,23 +45576,22 @@ function buildResultIndexArtifact(result, extraIndexFields, options) {
45148
45576
  start_time: result.startTime,
45149
45577
  end_time: result.endTime,
45150
45578
  scores: toIndexScores(result.scores),
45579
+ trials: toIndexTrialArtifacts(result),
45580
+ aggregation: toTrialAggregationArtifact(result.aggregation),
45151
45581
  execution_status: result.executionStatus,
45152
45582
  error: result.error,
45153
45583
  failure_stage: result.failureStage,
45154
45584
  failure_reason_code: result.failureReasonCode,
45155
45585
  workspace_path: result.workspacePath,
45156
45586
  artifact_dir: artifactSubdir,
45157
- grading_path: path49.posix.join(artifactSubdir, "grading.json"),
45158
- timing_path: path49.posix.join(artifactSubdir, "timing.json"),
45159
- input_path: input ? path49.posix.join(artifactSubdir, "input.md") : void 0,
45160
- output_path: hasAnswer ? path49.posix.join(artifactSubdir, "outputs", "answer.md") : void 0,
45161
- answer_path: hasAnswer ? path49.posix.join(artifactSubdir, "outputs", "answer.md") : void 0,
45162
- trace_path: path49.posix.join(artifactSubdir, CANONICAL_TRACE_ARTIFACT_PATH),
45163
- transcript_path: hasTranscript ? path49.posix.join(artifactSubdir, CANONICAL_TRANSCRIPT_ARTIFACT_PATH) : void 0,
45164
- metrics_path: path49.posix.join(artifactSubdir, CANONICAL_METRICS_ARTIFACT_PATH),
45165
- raw_provider_log_path: hasRawProviderLog ? path49.posix.join(artifactSubdir, "provider.log") : void 0,
45587
+ summary_path: path48.posix.join(artifactSubdir, RUN_SUMMARY_FILENAME),
45588
+ grading_path: isSingleRun ? path48.posix.join(singleRunDir, "grading.json") : void 0,
45589
+ timing_path: isSingleRun ? path48.posix.join(singleRunDir, "timing.json") : void 0,
45590
+ metrics_path: isSingleRun ? path48.posix.join(singleRunDir, CANONICAL_METRICS_ARTIFACT_PATH) : void 0,
45591
+ output_path: isSingleRun && hasAnswer ? path48.posix.join(singleRunDir, "outputs", "answer.md") : void 0,
45592
+ answer_path: isSingleRun && hasAnswer ? path48.posix.join(singleRunDir, "outputs", "answer.md") : void 0,
45593
+ transcript_path: isSingleRun && hasTranscript ? path48.posix.join(singleRunDir, "transcript-raw.jsonl") : void 0,
45166
45594
  artifact_pointers: options?.artifactPointers,
45167
- response_path: hasAnswer ? path49.posix.join(artifactSubdir, "outputs", "response.md") : void 0,
45168
45595
  ...extraIndexFields,
45169
45596
  external_trace: toIndexExternalTrace(result, options?.projectionIdentity?.dimensions.runId),
45170
45597
  projection_identity: options?.projectionIdentity ? toProjectionIdentityWire(options.projectionIdentity) : void 0,
@@ -45189,15 +45616,20 @@ async function writeTranscriptJsonl(filePath, result, envelope) {
45189
45616
  ` : "";
45190
45617
  await writeFile10(filePath, content, "utf8");
45191
45618
  }
45192
- async function writeMetricsArtifact(params) {
45619
+ function buildMetricsArtifactPayload(params) {
45193
45620
  const artifact = buildMetricsArtifact(params.result, params.envelope, {
45194
- tracePath: CANONICAL_TRACE_ARTIFACT_PATH,
45195
- transcriptPath: params.transcriptPath ? CANONICAL_TRANSCRIPT_ARTIFACT_PATH : void 0,
45196
- gradingPath: "grading.json",
45197
- timingPath: "timing.json"
45621
+ tracePath: params.traceArtifactPath ?? CANONICAL_TRACE_ARTIFACT_PATH,
45622
+ transcriptPath: params.transcriptArtifactPath ?? (params.transcriptPath ? CANONICAL_TRANSCRIPT_ARTIFACT_PATH : void 0),
45623
+ gradingPath: params.gradingArtifactPath ?? "grading.json",
45624
+ timingPath: params.timingArtifactPath === null ? void 0 : params.timingArtifactPath ?? "timing.json"
45198
45625
  });
45199
- await writeFile10(params.filePath, `${JSON.stringify(artifact, null, 2)}
45626
+ return params.timing ? { ...artifact, timing: params.timing } : artifact;
45627
+ }
45628
+ async function writeMetricsArtifact(params) {
45629
+ const artifactWithTiming = buildMetricsArtifactPayload(params);
45630
+ await writeFile10(params.filePath, `${JSON.stringify(artifactWithTiming, null, 2)}
45200
45631
  `, "utf8");
45632
+ return artifactWithTiming;
45201
45633
  }
45202
45634
  function indexRecordKey(record2) {
45203
45635
  if (!isRecord7(record2)) {
@@ -45215,7 +45647,7 @@ function projectionIdentityRecordKey(record2) {
45215
45647
  return typeof id === "string" && id.trim().length > 0 ? id : void 0;
45216
45648
  }
45217
45649
  async function readExistingIndexRecords(outputDir) {
45218
- const indexPath = path49.join(outputDir, RESULT_INDEX_FILENAME);
45650
+ const indexPath = path48.join(outputDir, RESULT_INDEX_FILENAME);
45219
45651
  const content = await readFile20(indexPath, "utf8").catch(() => void 0);
45220
45652
  if (content === void 0) {
45221
45653
  return [];
@@ -45268,7 +45700,7 @@ async function rewriteExistingIndexRecords(outputDir, replacements) {
45268
45700
  if (replacements.length === 0) {
45269
45701
  return;
45270
45702
  }
45271
- const indexPath = path49.join(outputDir, RESULT_INDEX_FILENAME);
45703
+ const indexPath = path48.join(outputDir, RESULT_INDEX_FILENAME);
45272
45704
  const content = await readFile20(indexPath, "utf8").catch(() => void 0);
45273
45705
  if (content === void 0) {
45274
45706
  return;
@@ -45425,39 +45857,10 @@ async function writePerTestArtifacts(results, outputDir, options) {
45425
45857
  const testByTestId = new Map((options?.sourceTests ?? []).map((test) => [test.id, test]));
45426
45858
  const indexRecords = [];
45427
45859
  for (const result of results) {
45428
- const grading = buildGradingArtifact(result);
45429
- const timing = buildTimingArtifact([result]);
45430
45860
  const artifactSubdir = buildArtifactSubdir(result);
45431
- const testDir = path49.join(outputDir, artifactSubdir);
45861
+ const testDir = path48.join(outputDir, artifactSubdir);
45432
45862
  await mkdir18(testDir, { recursive: true });
45433
- await writeFile10(
45434
- path49.join(testDir, "grading.json"),
45435
- `${JSON.stringify(grading, null, 2)}
45436
- `,
45437
- "utf8"
45438
- );
45439
- await writeFile10(
45440
- path49.join(testDir, "timing.json"),
45441
- `${JSON.stringify(timing, null, 2)}
45442
- `,
45443
- "utf8"
45444
- );
45445
- const input = extractInput(result);
45446
- if (input) {
45447
- await writeFile10(path49.join(testDir, "input.md"), input, "utf8");
45448
- }
45449
- const outputsDir = path49.join(testDir, "outputs");
45450
- await mkdir18(outputsDir, { recursive: true });
45451
- if (result.output.length > 0) {
45452
- await writeFile10(path49.join(outputsDir, "answer.md"), result.output, "utf8");
45453
- await writeFile10(path49.join(outputsDir, "response.md"), result.output, "utf8");
45454
- }
45455
- const rawProviderLogSource = rawProviderLogSourcePath(result);
45456
- if (rawProviderLogSource) {
45457
- await copyRawProviderLogArtifact(rawProviderLogSource, testDir);
45458
- }
45459
- const tracePath = path49.join(testDir, CANONICAL_TRACE_ARTIFACT_PATH);
45460
- const envelope = await writeTraceEnvelopeSidecar({
45863
+ const envelope = buildTraceEnvelopeSidecar({
45461
45864
  result,
45462
45865
  outputDir,
45463
45866
  testDir,
@@ -45466,22 +45869,34 @@ async function writePerTestArtifacts(results, outputDir, options) {
45466
45869
  runId: options?.runId,
45467
45870
  duplicatePolicy
45468
45871
  });
45469
- const transcriptPath = hasTranscriptProjection(result, envelope) ? path49.join(testDir, CANONICAL_TRANSCRIPT_ARTIFACT_PATH) : void 0;
45470
- if (transcriptPath) {
45471
- await writeTranscriptJsonl(transcriptPath, result, envelope);
45872
+ const projectionIdentity = envelope.projectionIdentity;
45873
+ if (!projectionIdentity) {
45874
+ throw new Error(`Result ${result.testId ?? "unknown"} is missing projection identity`);
45472
45875
  }
45473
- const metricsPath = path49.join(testDir, CANONICAL_METRICS_ARTIFACT_PATH);
45474
- await writeMetricsArtifact({
45475
- filePath: metricsPath,
45476
- result,
45477
- envelope,
45478
- transcriptPath
45479
- });
45480
- const artifactPointers = await buildArtifactPointers({
45481
- outputDir,
45482
- tracePath,
45483
- transcriptPath
45484
- });
45876
+ const caseSummaryPath = path48.join(testDir, RUN_SUMMARY_FILENAME);
45877
+ const aggregateTiming = buildRepeatAggregateTimingArtifact(result);
45878
+ const summary = buildRepeatCaseSummaryArtifact(result, aggregateTiming, projectionIdentity.id);
45879
+ await writeFile10(caseSummaryPath, `${JSON.stringify(summary, null, 2)}
45880
+ `, "utf8");
45881
+ for (const trial of materializedRunTrials(result)) {
45882
+ await writeTrialRunArtifacts({
45883
+ trial,
45884
+ parentTestDir: testDir,
45885
+ outputDir,
45886
+ evalFile: options?.evalFile,
45887
+ experiment: options?.experiment,
45888
+ runId: options?.runId,
45889
+ duplicatePolicy,
45890
+ testByTestId
45891
+ });
45892
+ }
45893
+ const isSingleRun = !hasPersistedTrialRuns(result);
45894
+ const singleRunDir = path48.join(testDir, trialRunDirName(0));
45895
+ const singleAnswerPath = isSingleRun && result.output.length > 0 ? path48.join(singleRunDir, "outputs", "answer.md") : void 0;
45896
+ const singleTranscriptPath = isSingleRun && hasTranscriptProjection(result, envelope) ? path48.join(singleRunDir, "transcript-raw.jsonl") : void 0;
45897
+ const singleGradingPath = isSingleRun ? path48.join(singleRunDir, "grading.json") : void 0;
45898
+ const singleTimingPath = isSingleRun ? path48.join(singleRunDir, "timing.json") : void 0;
45899
+ const singleMetricsPath = isSingleRun ? path48.join(singleRunDir, CANONICAL_METRICS_ARTIFACT_PATH) : void 0;
45485
45900
  const extraIndexFields = await collectAdditionalIndexFields(
45486
45901
  result,
45487
45902
  outputDir,
@@ -45490,10 +45905,19 @@ async function writePerTestArtifacts(results, outputDir, options) {
45490
45905
  options?.additionalArtifacts
45491
45906
  );
45492
45907
  indexRecords.push({
45493
- ...buildResultIndexArtifact(result, extraIndexFields, {
45494
- projectionIdentity: envelope.projectionIdentity,
45495
- duplicatePolicy,
45496
- artifactPointers
45908
+ ...buildIndexArtifactEntry(result, {
45909
+ outputDir,
45910
+ artifactDir: testDir,
45911
+ summaryPath: caseSummaryPath,
45912
+ gradingPath: singleGradingPath,
45913
+ timingPath: singleTimingPath,
45914
+ metricsPath: singleMetricsPath,
45915
+ outputPath: singleAnswerPath,
45916
+ answerPath: singleAnswerPath,
45917
+ transcriptPath: singleTranscriptPath,
45918
+ extraIndexFields,
45919
+ projectionIdentity,
45920
+ duplicatePolicy
45497
45921
  }),
45498
45922
  experiment: options?.experiment
45499
45923
  });
@@ -45502,9 +45926,8 @@ async function writePerTestArtifacts(results, outputDir, options) {
45502
45926
  }
45503
45927
  async function writeArtifactsFromResults(results, outputDir, options) {
45504
45928
  const testArtifactDir = outputDir;
45505
- const timingPath = path49.join(outputDir, "timing.json");
45506
- const benchmarkPath = path49.join(outputDir, "benchmark.json");
45507
- const indexPath = path49.join(outputDir, RESULT_INDEX_FILENAME);
45929
+ const summaryPath = path48.join(outputDir, RUN_SUMMARY_FILENAME);
45930
+ const indexPath = path48.join(outputDir, RESULT_INDEX_FILENAME);
45508
45931
  await mkdir18(outputDir, { recursive: true });
45509
45932
  const duplicatePolicy = options?.duplicatePolicy ?? "update";
45510
45933
  const existingRecords = await readExistingIndexRecords(outputDir);
@@ -45513,17 +45936,9 @@ async function writeArtifactsFromResults(results, outputDir, options) {
45513
45936
  const testByTestId = new Map((options?.sourceTests ?? []).map((test) => [test.id, test]));
45514
45937
  const emittedIdentityIds = /* @__PURE__ */ new Set();
45515
45938
  const plans = results.map((result) => {
45516
- const grading = buildGradingArtifact(result);
45517
- const timing2 = buildTimingArtifact([result]);
45518
45939
  const artifactSubdir = buildArtifactSubdir(result);
45519
- const testDir = path49.join(outputDir, artifactSubdir);
45520
- const gradingPath = path49.join(testDir, "grading.json");
45521
- const perTestTimingPath = path49.join(testDir, "timing.json");
45522
- const input = extractInput(result);
45523
- const inputPath = input ? path49.join(testDir, "input.md") : void 0;
45524
- const outputsDir = path49.join(testDir, "outputs");
45525
- const answerPath = result.output.length > 0 ? path49.join(outputsDir, "answer.md") : void 0;
45526
- const responsePath = result.output.length > 0 ? path49.join(outputsDir, "response.md") : void 0;
45940
+ const testDir = path48.join(outputDir, artifactSubdir);
45941
+ const caseSummaryPath = path48.join(testDir, RUN_SUMMARY_FILENAME);
45527
45942
  const envelope = buildTraceEnvelopeSidecar({
45528
45943
  result,
45529
45944
  outputDir,
@@ -45533,35 +45948,29 @@ async function writeArtifactsFromResults(results, outputDir, options) {
45533
45948
  runId: options?.runId,
45534
45949
  duplicatePolicy
45535
45950
  });
45536
- const transcriptPath = hasTranscriptProjection(result, envelope) ? path49.join(testDir, CANONICAL_TRANSCRIPT_ARTIFACT_PATH) : void 0;
45537
- const tracePath = path49.join(testDir, CANONICAL_TRACE_ARTIFACT_PATH);
45538
- const metricsPath = path49.join(testDir, CANONICAL_METRICS_ARTIFACT_PATH);
45539
- const rawProviderLogSource = rawProviderLogSourcePath(result);
45540
- const rawProviderLogPath = rawProviderLogSource ? rawProviderLogArtifactPath(testDir) : void 0;
45541
45951
  const projectionIdentity = envelope.projectionIdentity;
45542
45952
  if (!projectionIdentity) {
45543
45953
  throw new Error(`Result ${result.testId ?? "unknown"} is missing projection identity`);
45544
45954
  }
45545
45955
  const identityId = projectionIdentity.id;
45956
+ const isSingleRun = !hasPersistedTrialRuns(result);
45957
+ const singleRunDir = path48.join(testDir, trialRunDirName(0));
45958
+ const singleAnswerPath = isSingleRun && result.output.length > 0 ? path48.join(singleRunDir, "outputs", "answer.md") : void 0;
45959
+ const singleTranscriptPath = isSingleRun && hasTranscriptProjection(result, envelope) ? path48.join(singleRunDir, "transcript-raw.jsonl") : void 0;
45960
+ const singleGradingPath = isSingleRun ? path48.join(singleRunDir, "grading.json") : void 0;
45961
+ const singleTimingPath = isSingleRun ? path48.join(singleRunDir, "timing.json") : void 0;
45962
+ const singleMetricsPath = isSingleRun ? path48.join(singleRunDir, CANONICAL_METRICS_ARTIFACT_PATH) : void 0;
45546
45963
  return {
45547
45964
  result,
45548
- grading,
45549
- timing: timing2,
45550
45965
  testDir,
45551
- gradingPath,
45552
- perTestTimingPath,
45553
- input,
45554
- inputPath,
45555
- outputsDir,
45556
- answerPath,
45557
- responsePath,
45558
- tracePath,
45559
- metricsPath,
45560
- envelope,
45966
+ caseSummaryPath,
45561
45967
  projectionIdentity,
45562
- transcriptPath,
45563
- rawProviderLogSource,
45564
- rawProviderLogPath,
45968
+ isSingleRun,
45969
+ singleAnswerPath,
45970
+ singleTranscriptPath,
45971
+ singleGradingPath,
45972
+ singleTimingPath,
45973
+ singleMetricsPath,
45565
45974
  identityId
45566
45975
  };
45567
45976
  });
@@ -45578,7 +45987,7 @@ async function writeArtifactsFromResults(results, outputDir, options) {
45578
45987
  }
45579
45988
  }
45580
45989
  for (const plan of plans) {
45581
- const { result, envelope, identityId } = plan;
45990
+ const { result, identityId } = plan;
45582
45991
  const existing = existingByIdentity.get(identityId);
45583
45992
  if (duplicatePolicy === "skip" && existing) {
45584
45993
  indexRecords.push(skippedExistingRecord(existing, plan.projectionIdentity, duplicatePolicy));
@@ -45589,41 +45998,26 @@ async function writeArtifactsFromResults(results, outputDir, options) {
45589
45998
  continue;
45590
45999
  }
45591
46000
  await mkdir18(plan.testDir, { recursive: true });
45592
- await writeFile10(plan.gradingPath, `${JSON.stringify(plan.grading, null, 2)}
45593
- `, "utf8");
45594
- await writeFile10(plan.perTestTimingPath, `${JSON.stringify(plan.timing, null, 2)}
45595
- `, "utf8");
45596
- if (plan.inputPath && plan.input) {
45597
- await writeFile10(plan.inputPath, plan.input, "utf8");
45598
- }
45599
- await mkdir18(plan.outputsDir, { recursive: true });
45600
- if (plan.answerPath && plan.responsePath) {
45601
- await writeFile10(plan.answerPath, result.output, "utf8");
45602
- await writeFile10(plan.responsePath, result.output, "utf8");
45603
- }
45604
- if (plan.rawProviderLogSource) {
45605
- await copyRawProviderLogArtifact(plan.rawProviderLogSource, plan.testDir);
45606
- }
45607
- await writeFile10(
45608
- plan.tracePath,
45609
- `${JSON.stringify(toTraceEnvelopeWire(envelope), null, 2)}
45610
- `,
45611
- "utf8"
46001
+ const aggregateTiming = buildRepeatAggregateTimingArtifact(result);
46002
+ const summary2 = buildRepeatCaseSummaryArtifact(
46003
+ result,
46004
+ aggregateTiming,
46005
+ options?.experimentMetadata?.fingerprint ?? plan.projectionIdentity.id
45612
46006
  );
45613
- if (plan.transcriptPath) {
45614
- await writeTranscriptJsonl(plan.transcriptPath, result, envelope);
46007
+ await writeFile10(plan.caseSummaryPath, `${JSON.stringify(summary2, null, 2)}
46008
+ `, "utf8");
46009
+ for (const trial of materializedRunTrials(result)) {
46010
+ await writeTrialRunArtifacts({
46011
+ trial,
46012
+ parentTestDir: plan.testDir,
46013
+ outputDir,
46014
+ evalFile: options?.evalFile,
46015
+ experiment: options?.experiment,
46016
+ runId: options?.runId,
46017
+ duplicatePolicy,
46018
+ testByTestId
46019
+ });
45615
46020
  }
45616
- await writeMetricsArtifact({
45617
- filePath: plan.metricsPath,
45618
- result,
45619
- envelope,
45620
- transcriptPath: plan.transcriptPath
45621
- });
45622
- const artifactPointers = await buildArtifactPointers({
45623
- outputDir,
45624
- tracePath: plan.tracePath,
45625
- transcriptPath: plan.transcriptPath
45626
- });
45627
46021
  const extraIndexFields = await collectAdditionalIndexFields(
45628
46022
  result,
45629
46023
  outputDir,
@@ -45635,17 +46029,13 @@ async function writeArtifactsFromResults(results, outputDir, options) {
45635
46029
  ...buildIndexArtifactEntry(result, {
45636
46030
  outputDir,
45637
46031
  artifactDir: plan.testDir,
45638
- gradingPath: plan.gradingPath,
45639
- timingPath: plan.perTestTimingPath,
45640
- outputPath: plan.answerPath,
45641
- answerPath: plan.answerPath,
45642
- tracePath: plan.tracePath,
45643
- transcriptPath: plan.transcriptPath,
45644
- metricsPath: plan.metricsPath,
45645
- artifactPointers,
45646
- rawProviderLogPath: plan.rawProviderLogPath,
45647
- inputPath: plan.inputPath,
45648
- responsePath: plan.responsePath,
46032
+ summaryPath: plan.caseSummaryPath,
46033
+ gradingPath: plan.singleGradingPath,
46034
+ timingPath: plan.singleTimingPath,
46035
+ metricsPath: plan.singleMetricsPath,
46036
+ outputPath: plan.singleAnswerPath,
46037
+ answerPath: plan.singleAnswerPath,
46038
+ transcriptPath: plan.singleTranscriptPath,
45649
46039
  extraIndexFields,
45650
46040
  projectionIdentity: plan.projectionIdentity,
45651
46041
  duplicatePolicy
@@ -45664,20 +46054,18 @@ async function writeArtifactsFromResults(results, outputDir, options) {
45664
46054
  }
45665
46055
  emittedIdentityIds.add(identityId);
45666
46056
  }
45667
- const timing = buildTimingArtifact(results);
45668
- await writeFile10(timingPath, `${JSON.stringify(timing, null, 2)}
45669
- `, "utf8");
45670
- const plannedTestCount = options?.plannedTestCount ?? await readPlannedTestCount(benchmarkPath);
45671
- const benchmark = buildBenchmarkArtifact(
46057
+ const plannedTestCount = options?.plannedTestCount ?? await readPlannedTestCount(summaryPath);
46058
+ const summary = buildRunSummaryArtifact(
45672
46059
  results,
45673
46060
  options?.evalFile,
45674
46061
  options?.experiment,
45675
- plannedTestCount
46062
+ plannedTestCount,
46063
+ options?.experimentMetadata
45676
46064
  );
45677
- await writeFile10(benchmarkPath, `${JSON.stringify(benchmark, null, 2)}
46065
+ await writeFile10(summaryPath, `${JSON.stringify(summary, null, 2)}
45678
46066
  `, "utf8");
45679
46067
  await writeJsonlFile(indexPath, indexRecords);
45680
- return { testArtifactDir, timingPath, benchmarkPath, indexPath };
46068
+ return { testArtifactDir, summaryPath, indexPath };
45681
46069
  }
45682
46070
  async function evaluate(config2) {
45683
46071
  const startTime = Date.now();
@@ -45724,7 +46112,7 @@ async function evaluate(config2) {
45724
46112
  cliNoCache: false,
45725
46113
  yamlCache: config2.cache === void 0 ? materialized.cache : void 0
45726
46114
  });
45727
- const cache = cacheEnabled ? new ResponseCache(materialized.cachePath ? path50.resolve(materialized.cachePath) : void 0) : void 0;
46115
+ const cache = cacheEnabled ? new ResponseCache(materialized.cachePath ? path49.resolve(materialized.cachePath) : void 0) : void 0;
45728
46116
  const results = await runEvaluation({
45729
46117
  testFilePath,
45730
46118
  repoRoot,
@@ -45747,16 +46135,15 @@ async function evaluate(config2) {
45747
46135
  });
45748
46136
  const allResults = collectedResults.length > 0 ? collectedResults : [...results];
45749
46137
  const durationMs = Date.now() - startTime;
45750
- const outputDir = config2.outputDir ? path50.resolve(config2.outputDir) : void 0;
46138
+ const outputDir = config2.outputDir ? path49.resolve(config2.outputDir) : void 0;
45751
46139
  const artifacts = outputDir ? await writeArtifactsFromResults(allResults, outputDir, {
45752
46140
  evalFile: config2.specFile ? testFilePath : "",
45753
46141
  experiment: config2.experiment,
45754
46142
  sourceTests: materialized.tests
45755
- }).then(({ benchmarkPath, indexPath, timingPath }) => ({
46143
+ }).then(({ summaryPath, indexPath }) => ({
45756
46144
  runDir: outputDir,
45757
- benchmarkPath,
45758
- indexPath,
45759
- timingPath
46145
+ summaryPath,
46146
+ indexPath
45760
46147
  })) : void 0;
45761
46148
  return {
45762
46149
  results: allResults,
@@ -45767,7 +46154,7 @@ async function evaluate(config2) {
45767
46154
  async function materializeEvalConfig(config2, options) {
45768
46155
  const baseDir = options?.baseDir ?? process.cwd();
45769
46156
  const repoRoot = options?.repoRoot ?? await findGitRoot(baseDir) ?? baseDir;
45770
- const testFilePath = config2.specFile ? path50.resolve(baseDir, config2.specFile) : path50.join(baseDir, "__programmatic__.yaml");
46157
+ const testFilePath = config2.specFile ? path49.resolve(baseDir, config2.specFile) : path49.join(baseDir, "__programmatic__.yaml");
45771
46158
  const effectiveFilter = options?.filter ?? config2.filter;
45772
46159
  if (config2.specFile) {
45773
46160
  const suite = await loadTestSuite(testFilePath, repoRoot, {
@@ -45844,7 +46231,7 @@ function convertAssertions(entries) {
45844
46231
  }
45845
46232
  function buildInlineEvalTests(config2, options) {
45846
46233
  const suiteWorkspace = config2.beforeAll ? { hooks: { before_all: toBeforeAllHook(config2.beforeAll) } } : void 0;
45847
- const derivedSuiteName = path50.basename(options.testFilePath).replace(/\.eval\.[cm]?ts$/i, "").replace(/\.[cm]?ts$/i, "");
46234
+ const derivedSuiteName = path49.basename(options.testFilePath).replace(/\.eval\.[cm]?ts$/i, "").replace(/\.[cm]?ts$/i, "");
45848
46235
  const suiteName = config2.metadata?.name ?? (derivedSuiteName || "eval");
45849
46236
  return (config2.tests ?? []).filter((test) => !options.filter || matchesFilter4(test.id, options.filter)).map((test) => {
45850
46237
  const isConversation = test.mode === "conversation" || test.turns && test.turns.length > 0;
@@ -45940,10 +46327,10 @@ function computeSummary(results, durationMs, threshold = DEFAULT_THRESHOLD) {
45940
46327
  var TARGET_FILE_CANDIDATES = [".agentv/targets.yaml", ".agentv/targets.yml"];
45941
46328
  async function discoverDefaultTarget(repoRoot) {
45942
46329
  const cwd = process.cwd();
45943
- const chain = buildDirectoryChain(path50.join(cwd, "_placeholder"), repoRoot);
46330
+ const chain = buildDirectoryChain(path49.join(cwd, "_placeholder"), repoRoot);
45944
46331
  for (const dir of chain) {
45945
46332
  for (const candidate of TARGET_FILE_CANDIDATES) {
45946
- const targetsPath = path50.join(dir, candidate);
46333
+ const targetsPath = path49.join(dir, candidate);
45947
46334
  if (!existsSync7(targetsPath)) continue;
45948
46335
  try {
45949
46336
  const definitions = await readTargetDefinitions(targetsPath);
@@ -45960,7 +46347,7 @@ async function loadEnvHierarchy(repoRoot, startPath) {
45960
46347
  const chain = buildDirectoryChain(startPath, repoRoot);
45961
46348
  const envFiles = [];
45962
46349
  for (const dir of chain) {
45963
- const envPath = path50.join(dir, ".env");
46350
+ const envPath = path49.join(dir, ".env");
45964
46351
  if (existsSync7(envPath)) envFiles.push(envPath);
45965
46352
  }
45966
46353
  for (let i = 0; i < envFiles.length; i++) {
@@ -45988,7 +46375,7 @@ var EXPORT_NAMES = ["default", "config", "evalConfig"];
45988
46375
  var SDK_EVAL_SUITE_SYMBOL = Symbol.for("@agentv/sdk/eval-suite");
45989
46376
  var SDK_TO_EVAL_YAML_OBJECT_SYMBOL = Symbol.for("@agentv/sdk/to-eval-yaml-object");
45990
46377
  async function loadTsEvalFile(filePath) {
45991
- const absolutePath = path51.resolve(filePath);
46378
+ const absolutePath = path50.resolve(filePath);
45992
46379
  const moduleUrl = pathToFileURL2(absolutePath).href;
45993
46380
  const module = await import(moduleUrl);
45994
46381
  let config2;
@@ -46018,7 +46405,7 @@ async function loadTsEvalSuite(filePath, repoRoot, options) {
46018
46405
  }
46019
46406
  const materialized = await materializeEvalConfig(config2, {
46020
46407
  repoRoot,
46021
- baseDir: path51.dirname(absolutePath),
46408
+ baseDir: path50.dirname(absolutePath),
46022
46409
  filter: options?.filter,
46023
46410
  category: options?.category
46024
46411
  });
@@ -46071,6 +46458,14 @@ export {
46071
46458
  isGraderKind,
46072
46459
  RUBRIC_OPERATOR_VALUES,
46073
46460
  parseYamlValue,
46461
+ AGENTV_CONFIG_FILE_NAME,
46462
+ AGENTV_CONFIG_YML_FILE_NAME,
46463
+ AGENTV_LOCAL_CONFIG_FILE_NAME,
46464
+ AGENTV_LOCAL_CONFIG_YML_FILE_NAME,
46465
+ getLocalConfigPath,
46466
+ isAgentVConfigFileName,
46467
+ isPlainConfigObject,
46468
+ mergeConfigObjects,
46074
46469
  getAgentvConfigDir,
46075
46470
  getAgentvHome,
46076
46471
  getAgentvDataDir,
@@ -46098,6 +46493,8 @@ export {
46098
46493
  interpolateEnv,
46099
46494
  loadCasesFromFile,
46100
46495
  loadCasesFromDirectory,
46496
+ buildSearchRoots2,
46497
+ loadPromptMdFallback,
46101
46498
  ResponseCache,
46102
46499
  shouldEnableCache,
46103
46500
  shouldSkipCacheForTemperature,
@@ -46303,10 +46700,10 @@ export {
46303
46700
  extractTargetsFromSuite,
46304
46701
  extractWorkersFromSuite,
46305
46702
  extractTargetsFromTestCase,
46306
- extractTrialsConfig,
46307
46703
  extractCacheConfig,
46308
46704
  extractFailOnError,
46309
46705
  extractThreshold,
46706
+ resolveDefaultExperimentReference,
46310
46707
  resolveResultsConfigForProject,
46311
46708
  detectFormat,
46312
46709
  parseRepoConfig,
@@ -46350,13 +46747,14 @@ export {
46350
46747
  ResultRowSchemaError,
46351
46748
  normalizeResultRow,
46352
46749
  RESULT_INDEX_FILENAME,
46750
+ RUN_SUMMARY_FILENAME,
46353
46751
  buildTestTargetKey,
46354
46752
  deduplicateByTestIdTarget,
46355
46753
  aggregateRunDir,
46356
46754
  buildGradingArtifact,
46357
46755
  buildTimingArtifact,
46358
- buildBenchmarkArtifact,
46359
- writeInitialBenchmarkArtifact,
46756
+ buildRunSummaryArtifact,
46757
+ writeInitialRunSummaryArtifact,
46360
46758
  buildAggregateGradingArtifact,
46361
46759
  buildIndexArtifactEntry,
46362
46760
  buildResultIndexArtifact,
@@ -46368,4 +46766,4 @@ export {
46368
46766
  loadTsEvalFile,
46369
46767
  loadTsEvalSuite
46370
46768
  };
46371
- //# sourceMappingURL=chunk-RFJM2UBD.js.map
46769
+ //# sourceMappingURL=chunk-GZJMODLW.js.map