agentv 4.8.0 → 4.9.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.
@@ -6941,7 +6941,7 @@ function createOpenRouter(options = {}) {
6941
6941
  );
6942
6942
  const createChatModel = (modelId, settings = {}) => new OpenRouterChatLanguageModel(modelId, settings, {
6943
6943
  provider: "openrouter.chat",
6944
- url: ({ path: path50 }) => `${baseURL}${path50}`,
6944
+ url: ({ path: path51 }) => `${baseURL}${path51}`,
6945
6945
  headers: getHeaders,
6946
6946
  compatibility,
6947
6947
  fetch: options.fetch,
@@ -6949,7 +6949,7 @@ function createOpenRouter(options = {}) {
6949
6949
  });
6950
6950
  const createCompletionModel = (modelId, settings = {}) => new OpenRouterCompletionLanguageModel(modelId, settings, {
6951
6951
  provider: "openrouter.completion",
6952
- url: ({ path: path50 }) => `${baseURL}${path50}`,
6952
+ url: ({ path: path51 }) => `${baseURL}${path51}`,
6953
6953
  headers: getHeaders,
6954
6954
  compatibility,
6955
6955
  fetch: options.fetch,
@@ -6957,14 +6957,14 @@ function createOpenRouter(options = {}) {
6957
6957
  });
6958
6958
  const createEmbeddingModel = (modelId, settings = {}) => new OpenRouterEmbeddingModel(modelId, settings, {
6959
6959
  provider: "openrouter.embedding",
6960
- url: ({ path: path50 }) => `${baseURL}${path50}`,
6960
+ url: ({ path: path51 }) => `${baseURL}${path51}`,
6961
6961
  headers: getHeaders,
6962
6962
  fetch: options.fetch,
6963
6963
  extraBody: options.extraBody
6964
6964
  });
6965
6965
  const createImageModel = (modelId, settings = {}) => new OpenRouterImageModel(modelId, settings, {
6966
6966
  provider: "openrouter.image",
6967
- url: ({ path: path50 }) => `${baseURL}${path50}`,
6967
+ url: ({ path: path51 }) => `${baseURL}${path51}`,
6968
6968
  headers: getHeaders,
6969
6969
  fetch: options.fetch,
6970
6970
  extraBody: options.extraBody
@@ -14528,6 +14528,7 @@ import { createServer } from "node:http";
14528
14528
  import fs2 from "node:fs/promises";
14529
14529
  import path35 from "node:path";
14530
14530
  import { createHash as createHash2, randomUUID as randomUUID9 } from "node:crypto";
14531
+ import { existsSync as existsSync5 } from "node:fs";
14531
14532
  import { copyFile as copyFile2, mkdir as mkdir14, readdir as readdir7, stat as stat8 } from "node:fs/promises";
14532
14533
  import path44 from "node:path";
14533
14534
  import micromatch3 from "micromatch";
@@ -14554,20 +14555,23 @@ import path422 from "node:path";
14554
14555
  import { promisify as promisify6 } from "node:util";
14555
14556
  import { readdir as readdir6, stat as stat7 } from "node:fs/promises";
14556
14557
  import path43 from "node:path";
14557
- import { existsSync as existsSync5 } from "node:fs";
14558
+ import { existsSync as existsSync6 } from "node:fs";
14558
14559
  import path45 from "node:path";
14559
- import { mkdir as mkdir15, readFile as readFile13, writeFile as writeFile8 } from "node:fs/promises";
14560
+ import { readFile as readFile13 } from "node:fs/promises";
14560
14561
  import path46 from "node:path";
14561
- import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync2, writeFileSync } from "node:fs";
14562
+ import { parse as parse5 } from "yaml";
14563
+ import { mkdir as mkdir15, readFile as readFile14, writeFile as writeFile8 } from "node:fs/promises";
14562
14564
  import path47 from "node:path";
14565
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync2, writeFileSync } from "node:fs";
14566
+ import path48 from "node:path";
14563
14567
  import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
14564
14568
  import { readdir as readdir8, stat as stat9 } from "node:fs/promises";
14565
14569
  import { homedir as homedir3 } from "node:os";
14566
- import path48 from "node:path";
14570
+ import path49 from "node:path";
14567
14571
  import { readdir as readdir9, stat as stat10 } from "node:fs/promises";
14568
14572
  import { homedir as homedir4 } from "node:os";
14569
- import path49 from "node:path";
14570
- import { readFile as readFile14 } from "node:fs/promises";
14573
+ import path50 from "node:path";
14574
+ import { readFile as readFile15 } from "node:fs/promises";
14571
14575
  function computeTraceSummary(messages) {
14572
14576
  const toolCallCounts = {};
14573
14577
  const toolDurations = {};
@@ -17389,6 +17393,58 @@ function parseMetadata(suite) {
17389
17393
  requires: suite.requires
17390
17394
  });
17391
17395
  }
17396
+ function parseRepoSource(raw) {
17397
+ if (!isJsonObject(raw)) return void 0;
17398
+ const obj = raw;
17399
+ if (obj.type === "git" && typeof obj.url === "string") {
17400
+ return { type: "git", url: obj.url };
17401
+ }
17402
+ if (obj.type === "local" && typeof obj.path === "string") {
17403
+ return { type: "local", path: obj.path };
17404
+ }
17405
+ return void 0;
17406
+ }
17407
+ function parseRepoCheckout(raw) {
17408
+ if (!isJsonObject(raw)) return void 0;
17409
+ const obj = raw;
17410
+ const ref = typeof obj.ref === "string" ? obj.ref : void 0;
17411
+ const resolve2 = obj.resolve === "remote" || obj.resolve === "local" ? obj.resolve : void 0;
17412
+ const ancestor = typeof obj.ancestor === "number" ? obj.ancestor : void 0;
17413
+ if (!ref && !resolve2 && ancestor === void 0) return void 0;
17414
+ return {
17415
+ ...ref !== void 0 && { ref },
17416
+ ...resolve2 !== void 0 && { resolve: resolve2 },
17417
+ ...ancestor !== void 0 && { ancestor }
17418
+ };
17419
+ }
17420
+ function parseRepoClone(raw) {
17421
+ if (!isJsonObject(raw)) return void 0;
17422
+ const obj = raw;
17423
+ const depth = typeof obj.depth === "number" ? obj.depth : void 0;
17424
+ const filter2 = typeof obj.filter === "string" ? obj.filter : void 0;
17425
+ const sparse = Array.isArray(obj.sparse) ? obj.sparse.filter((s) => typeof s === "string") : void 0;
17426
+ if (depth === void 0 && !filter2 && !sparse) return void 0;
17427
+ return {
17428
+ ...depth !== void 0 && { depth },
17429
+ ...filter2 !== void 0 && { filter: filter2 },
17430
+ ...sparse !== void 0 && { sparse }
17431
+ };
17432
+ }
17433
+ function parseRepoConfig(raw) {
17434
+ if (!isJsonObject(raw)) return void 0;
17435
+ const obj = raw;
17436
+ const repoPath = typeof obj.path === "string" ? obj.path : void 0;
17437
+ const source = parseRepoSource(obj.source);
17438
+ if (!repoPath || !source) return void 0;
17439
+ const checkout = parseRepoCheckout(obj.checkout);
17440
+ const clone = parseRepoClone(obj.clone);
17441
+ return {
17442
+ path: repoPath,
17443
+ source,
17444
+ ...checkout !== void 0 && { checkout },
17445
+ ...clone !== void 0 && { clone }
17446
+ };
17447
+ }
17392
17448
  async function buildPromptInputs(testCase, mode = "lm") {
17393
17449
  const segmentsByMessage = testCase.input.map(
17394
17450
  (message) => extractContentSegments(message.content)
@@ -17780,58 +17836,6 @@ function parseWorkspaceScriptConfig(raw, evalFileDir) {
17780
17836
  }
17781
17837
  return cwd ? { ...config, cwd } : config;
17782
17838
  }
17783
- function parseRepoSource(raw) {
17784
- if (!isJsonObject(raw)) return void 0;
17785
- const obj = raw;
17786
- if (obj.type === "git" && typeof obj.url === "string") {
17787
- return { type: "git", url: obj.url };
17788
- }
17789
- if (obj.type === "local" && typeof obj.path === "string") {
17790
- return { type: "local", path: obj.path };
17791
- }
17792
- return void 0;
17793
- }
17794
- function parseRepoCheckout(raw) {
17795
- if (!isJsonObject(raw)) return void 0;
17796
- const obj = raw;
17797
- const ref = typeof obj.ref === "string" ? obj.ref : void 0;
17798
- const resolve2 = obj.resolve === "remote" || obj.resolve === "local" ? obj.resolve : void 0;
17799
- const ancestor = typeof obj.ancestor === "number" ? obj.ancestor : void 0;
17800
- if (!ref && !resolve2 && ancestor === void 0) return void 0;
17801
- return {
17802
- ...ref !== void 0 && { ref },
17803
- ...resolve2 !== void 0 && { resolve: resolve2 },
17804
- ...ancestor !== void 0 && { ancestor }
17805
- };
17806
- }
17807
- function parseRepoClone(raw) {
17808
- if (!isJsonObject(raw)) return void 0;
17809
- const obj = raw;
17810
- const depth = typeof obj.depth === "number" ? obj.depth : void 0;
17811
- const filter2 = typeof obj.filter === "string" ? obj.filter : void 0;
17812
- const sparse = Array.isArray(obj.sparse) ? obj.sparse.filter((s) => typeof s === "string") : void 0;
17813
- if (depth === void 0 && !filter2 && !sparse) return void 0;
17814
- return {
17815
- ...depth !== void 0 && { depth },
17816
- ...filter2 !== void 0 && { filter: filter2 },
17817
- ...sparse !== void 0 && { sparse }
17818
- };
17819
- }
17820
- function parseRepoConfig(raw) {
17821
- if (!isJsonObject(raw)) return void 0;
17822
- const obj = raw;
17823
- const repoPath = typeof obj.path === "string" ? obj.path : void 0;
17824
- const source = parseRepoSource(obj.source);
17825
- if (!repoPath || !source) return void 0;
17826
- const checkout = parseRepoCheckout(obj.checkout);
17827
- const clone = parseRepoClone(obj.clone);
17828
- return {
17829
- path: repoPath,
17830
- source,
17831
- ...checkout !== void 0 && { checkout },
17832
- ...clone !== void 0 && { clone }
17833
- };
17834
- }
17835
17839
  function parseWorkspaceHookConfig(raw, evalFileDir) {
17836
17840
  if (!isJsonObject(raw)) return void 0;
17837
17841
  const script = parseWorkspaceScriptConfig(raw, evalFileDir);
@@ -25076,15 +25080,15 @@ async function execFileWithStdinNode(argv, stdinPayload, options) {
25076
25080
  });
25077
25081
  }
25078
25082
  async function execShellWithStdin(command, stdinPayload, options = {}) {
25079
- const { mkdir: mkdir16, readFile: readFile15, rm: rm6, writeFile: writeFile9 } = await import("node:fs/promises");
25083
+ const { mkdir: mkdir16, readFile: readFile16, rm: rm6, writeFile: writeFile9 } = await import("node:fs/promises");
25080
25084
  const { tmpdir: tmpdir3 } = await import("node:os");
25081
- const path50 = await import("node:path");
25085
+ const path51 = await import("node:path");
25082
25086
  const { randomUUID: randomUUID10 } = await import("node:crypto");
25083
- const dir = path50.join(tmpdir3(), `agentv-exec-${randomUUID10()}`);
25087
+ const dir = path51.join(tmpdir3(), `agentv-exec-${randomUUID10()}`);
25084
25088
  await mkdir16(dir, { recursive: true });
25085
- const stdinPath = path50.join(dir, "stdin.txt");
25086
- const stdoutPath = path50.join(dir, "stdout.txt");
25087
- const stderrPath = path50.join(dir, "stderr.txt");
25089
+ const stdinPath = path51.join(dir, "stdin.txt");
25090
+ const stdoutPath = path51.join(dir, "stdout.txt");
25091
+ const stderrPath = path51.join(dir, "stderr.txt");
25088
25092
  await writeFile9(stdinPath, stdinPayload, "utf8");
25089
25093
  const wrappedCommand = process.platform === "win32" ? `(${command}) < ${shellEscapePath(stdinPath)} > ${shellEscapePath(stdoutPath)} 2> ${shellEscapePath(stderrPath)}` : `(${command}) < ${shellEscapePath(stdinPath)} > ${shellEscapePath(stdoutPath)} 2> ${shellEscapePath(stderrPath)}`;
25090
25094
  const { spawn: spawn5 } = await import("node:child_process");
@@ -25114,8 +25118,8 @@ async function execShellWithStdin(command, stdinPayload, options = {}) {
25114
25118
  resolve2(code ?? 0);
25115
25119
  });
25116
25120
  });
25117
- const stdout = (await readFile15(stdoutPath, "utf8")).replace(/\r\n/g, "\n");
25118
- const stderr = (await readFile15(stderrPath, "utf8")).replace(/\r\n/g, "\n");
25121
+ const stdout = (await readFile16(stdoutPath, "utf8")).replace(/\r\n/g, "\n");
25122
+ const stderr = (await readFile16(stderrPath, "utf8")).replace(/\r\n/g, "\n");
25119
25123
  return { stdout, stderr, exitCode };
25120
25124
  } finally {
25121
25125
  await rm6(dir, { recursive: true, force: true });
@@ -27349,115 +27353,115 @@ var FieldAccuracyEvaluator = class {
27349
27353
  * Evaluate a single field against the expected value.
27350
27354
  */
27351
27355
  evaluateField(fieldConfig, candidateData, expectedData) {
27352
- const { path: path50, match, required = true, weight = 1 } = fieldConfig;
27353
- const candidateValue = resolvePath(candidateData, path50);
27354
- const expectedValue = resolvePath(expectedData, path50);
27356
+ const { path: path51, match, required = true, weight = 1 } = fieldConfig;
27357
+ const candidateValue = resolvePath(candidateData, path51);
27358
+ const expectedValue = resolvePath(expectedData, path51);
27355
27359
  if (expectedValue === void 0) {
27356
27360
  return {
27357
- path: path50,
27361
+ path: path51,
27358
27362
  score: 1,
27359
27363
  // No expected value means no comparison needed
27360
27364
  weight,
27361
27365
  hit: true,
27362
- message: `${path50}: no expected value`
27366
+ message: `${path51}: no expected value`
27363
27367
  };
27364
27368
  }
27365
27369
  if (candidateValue === void 0) {
27366
27370
  if (required) {
27367
27371
  return {
27368
- path: path50,
27372
+ path: path51,
27369
27373
  score: 0,
27370
27374
  weight,
27371
27375
  hit: false,
27372
- message: `${path50} (required, missing)`
27376
+ message: `${path51} (required, missing)`
27373
27377
  };
27374
27378
  }
27375
27379
  return {
27376
- path: path50,
27380
+ path: path51,
27377
27381
  score: 1,
27378
27382
  // Don't penalize missing optional fields
27379
27383
  weight: 0,
27380
27384
  // Zero weight means it won't affect the score
27381
27385
  hit: true,
27382
- message: `${path50}: optional field missing`
27386
+ message: `${path51}: optional field missing`
27383
27387
  };
27384
27388
  }
27385
27389
  switch (match) {
27386
27390
  case "exact":
27387
- return this.compareExact(path50, candidateValue, expectedValue, weight);
27391
+ return this.compareExact(path51, candidateValue, expectedValue, weight);
27388
27392
  case "numeric_tolerance":
27389
27393
  return this.compareNumericTolerance(
27390
- path50,
27394
+ path51,
27391
27395
  candidateValue,
27392
27396
  expectedValue,
27393
27397
  fieldConfig,
27394
27398
  weight
27395
27399
  );
27396
27400
  case "date":
27397
- return this.compareDate(path50, candidateValue, expectedValue, fieldConfig, weight);
27401
+ return this.compareDate(path51, candidateValue, expectedValue, fieldConfig, weight);
27398
27402
  default:
27399
27403
  return {
27400
- path: path50,
27404
+ path: path51,
27401
27405
  score: 0,
27402
27406
  weight,
27403
27407
  hit: false,
27404
- message: `${path50}: unknown match type "${match}"`
27408
+ message: `${path51}: unknown match type "${match}"`
27405
27409
  };
27406
27410
  }
27407
27411
  }
27408
27412
  /**
27409
27413
  * Exact equality comparison.
27410
27414
  */
27411
- compareExact(path50, candidateValue, expectedValue, weight) {
27415
+ compareExact(path51, candidateValue, expectedValue, weight) {
27412
27416
  if (deepEqual(candidateValue, expectedValue)) {
27413
27417
  return {
27414
- path: path50,
27418
+ path: path51,
27415
27419
  score: 1,
27416
27420
  weight,
27417
27421
  hit: true,
27418
- message: path50
27422
+ message: path51
27419
27423
  };
27420
27424
  }
27421
27425
  if (typeof candidateValue !== typeof expectedValue) {
27422
27426
  return {
27423
- path: path50,
27427
+ path: path51,
27424
27428
  score: 0,
27425
27429
  weight,
27426
27430
  hit: false,
27427
- message: `${path50} (type mismatch: got ${typeof candidateValue}, expected ${typeof expectedValue})`
27431
+ message: `${path51} (type mismatch: got ${typeof candidateValue}, expected ${typeof expectedValue})`
27428
27432
  };
27429
27433
  }
27430
27434
  return {
27431
- path: path50,
27435
+ path: path51,
27432
27436
  score: 0,
27433
27437
  weight,
27434
27438
  hit: false,
27435
- message: `${path50} (value mismatch)`
27439
+ message: `${path51} (value mismatch)`
27436
27440
  };
27437
27441
  }
27438
27442
  /**
27439
27443
  * Numeric comparison with absolute or relative tolerance.
27440
27444
  */
27441
- compareNumericTolerance(path50, candidateValue, expectedValue, fieldConfig, weight) {
27445
+ compareNumericTolerance(path51, candidateValue, expectedValue, fieldConfig, weight) {
27442
27446
  const { tolerance = 0, relative = false } = fieldConfig;
27443
27447
  const candidateNum = toNumber(candidateValue);
27444
27448
  const expectedNum = toNumber(expectedValue);
27445
27449
  if (candidateNum === null || expectedNum === null) {
27446
27450
  return {
27447
- path: path50,
27451
+ path: path51,
27448
27452
  score: 0,
27449
27453
  weight,
27450
27454
  hit: false,
27451
- message: `${path50} (non-numeric value)`
27455
+ message: `${path51} (non-numeric value)`
27452
27456
  };
27453
27457
  }
27454
27458
  if (!Number.isFinite(candidateNum) || !Number.isFinite(expectedNum)) {
27455
27459
  return {
27456
- path: path50,
27460
+ path: path51,
27457
27461
  score: 0,
27458
27462
  weight,
27459
27463
  hit: false,
27460
- message: `${path50} (invalid numeric value)`
27464
+ message: `${path51} (invalid numeric value)`
27461
27465
  };
27462
27466
  }
27463
27467
  const diff = Math.abs(candidateNum - expectedNum);
@@ -27470,61 +27474,61 @@ var FieldAccuracyEvaluator = class {
27470
27474
  }
27471
27475
  if (withinTolerance) {
27472
27476
  return {
27473
- path: path50,
27477
+ path: path51,
27474
27478
  score: 1,
27475
27479
  weight,
27476
27480
  hit: true,
27477
- message: `${path50} (within tolerance: diff=${diff.toFixed(2)})`
27481
+ message: `${path51} (within tolerance: diff=${diff.toFixed(2)})`
27478
27482
  };
27479
27483
  }
27480
27484
  return {
27481
- path: path50,
27485
+ path: path51,
27482
27486
  score: 0,
27483
27487
  weight,
27484
27488
  hit: false,
27485
- message: `${path50} (outside tolerance: diff=${diff.toFixed(2)}, tolerance=${tolerance})`
27489
+ message: `${path51} (outside tolerance: diff=${diff.toFixed(2)}, tolerance=${tolerance})`
27486
27490
  };
27487
27491
  }
27488
27492
  /**
27489
27493
  * Date comparison with format normalization.
27490
27494
  */
27491
- compareDate(path50, candidateValue, expectedValue, fieldConfig, weight) {
27495
+ compareDate(path51, candidateValue, expectedValue, fieldConfig, weight) {
27492
27496
  const formats = fieldConfig.formats ?? DEFAULT_DATE_FORMATS;
27493
27497
  const candidateDate = parseDate(String(candidateValue), formats);
27494
27498
  const expectedDate = parseDate(String(expectedValue), formats);
27495
27499
  if (candidateDate === null) {
27496
27500
  return {
27497
- path: path50,
27501
+ path: path51,
27498
27502
  score: 0,
27499
27503
  weight,
27500
27504
  hit: false,
27501
- message: `${path50} (unparseable candidate date)`
27505
+ message: `${path51} (unparseable candidate date)`
27502
27506
  };
27503
27507
  }
27504
27508
  if (expectedDate === null) {
27505
27509
  return {
27506
- path: path50,
27510
+ path: path51,
27507
27511
  score: 0,
27508
27512
  weight,
27509
27513
  hit: false,
27510
- message: `${path50} (unparseable expected date)`
27514
+ message: `${path51} (unparseable expected date)`
27511
27515
  };
27512
27516
  }
27513
27517
  if (candidateDate.getFullYear() === expectedDate.getFullYear() && candidateDate.getMonth() === expectedDate.getMonth() && candidateDate.getDate() === expectedDate.getDate()) {
27514
27518
  return {
27515
- path: path50,
27519
+ path: path51,
27516
27520
  score: 1,
27517
27521
  weight,
27518
27522
  hit: true,
27519
- message: path50
27523
+ message: path51
27520
27524
  };
27521
27525
  }
27522
27526
  return {
27523
- path: path50,
27527
+ path: path51,
27524
27528
  score: 0,
27525
27529
  weight,
27526
27530
  hit: false,
27527
- message: `${path50} (date mismatch: got ${formatDateISO(candidateDate)}, expected ${formatDateISO(expectedDate)})`
27531
+ message: `${path51} (date mismatch: got ${formatDateISO(candidateDate)}, expected ${formatDateISO(expectedDate)})`
27528
27532
  };
27529
27533
  }
27530
27534
  /**
@@ -27557,11 +27561,11 @@ var FieldAccuracyEvaluator = class {
27557
27561
  };
27558
27562
  }
27559
27563
  };
27560
- function resolvePath(obj, path50) {
27561
- if (!path50 || !obj) {
27564
+ function resolvePath(obj, path51) {
27565
+ if (!path51 || !obj) {
27562
27566
  return void 0;
27563
27567
  }
27564
- const parts = path50.split(/\.|\[|\]/).filter((p) => p.length > 0);
27568
+ const parts = path51.split(/\.|\[|\]/).filter((p) => p.length > 0);
27565
27569
  let current = obj;
27566
27570
  for (const part of parts) {
27567
27571
  if (current === null || current === void 0) {
@@ -28043,8 +28047,8 @@ var TokenUsageEvaluator = class {
28043
28047
  };
28044
28048
  }
28045
28049
  };
28046
- function getNestedValue(obj, path50) {
28047
- const parts = path50.split(".");
28050
+ function getNestedValue(obj, path51) {
28051
+ const parts = path51.split(".");
28048
28052
  let current = obj;
28049
28053
  for (const part of parts) {
28050
28054
  if (current === null || current === void 0 || typeof current !== "object") {
@@ -30381,8 +30385,8 @@ async function runEvaluation(options) {
30381
30385
  const poolSlotBaselines = /* @__PURE__ */ new Map();
30382
30386
  const poolMaxSlots = Math.min(configPoolMaxSlots ?? 10, 50);
30383
30387
  let staticMaterialised = false;
30388
+ const isYamlConfiguredPath = !cliWorkspacePath && !!yamlWorkspacePath;
30384
30389
  if (useStaticWorkspace && configuredStaticPath) {
30385
- const isYamlConfiguredPath = !cliWorkspacePath && !!yamlWorkspacePath;
30386
30390
  const dirExists = await stat8(configuredStaticPath).then(
30387
30391
  (s) => s.isDirectory(),
30388
30392
  () => false
@@ -30447,14 +30451,28 @@ async function runEvaluation(options) {
30447
30451
  } catch {
30448
30452
  }
30449
30453
  }
30450
- const needsRepoMaterialisation = !!suiteWorkspace?.repos?.length && !usePool && (!useStaticWorkspace || staticMaterialised);
30451
- const repoManager = needsRepoMaterialisation ? new RepoManager(verbose) : void 0;
30452
- if (repoManager && sharedWorkspacePath && suiteWorkspace?.repos && !isPerTestIsolation) {
30453
- setupLog(
30454
- `materializing ${suiteWorkspace.repos.length} shared repo(s) into ${sharedWorkspacePath}`
30455
- );
30454
+ const hasReposToMaterialize = !!suiteWorkspace?.repos?.length && !usePool && !isPerTestIsolation;
30455
+ const needsRepoMaterialisation = hasReposToMaterialize && (!useStaticWorkspace || staticMaterialised);
30456
+ const needsPerRepoCheck = hasReposToMaterialize && useStaticWorkspace && !staticMaterialised && isYamlConfiguredPath;
30457
+ const repoManager = needsRepoMaterialisation || needsPerRepoCheck ? new RepoManager(verbose) : void 0;
30458
+ if (repoManager && sharedWorkspacePath && suiteWorkspace?.repos) {
30456
30459
  try {
30457
- await repoManager.materializeAll(suiteWorkspace.repos, sharedWorkspacePath);
30460
+ if (needsPerRepoCheck) {
30461
+ for (const repo of suiteWorkspace.repos) {
30462
+ const targetDir = path44.join(sharedWorkspacePath, repo.path);
30463
+ if (existsSync5(targetDir)) {
30464
+ setupLog(`reusing existing repo at: ${targetDir}`);
30465
+ continue;
30466
+ }
30467
+ setupLog(`materializing missing repo: ${repo.path}`);
30468
+ await repoManager.materialize(repo, sharedWorkspacePath);
30469
+ }
30470
+ } else {
30471
+ setupLog(
30472
+ `materializing ${suiteWorkspace.repos.length} shared repo(s) into ${sharedWorkspacePath}`
30473
+ );
30474
+ await repoManager.materializeAll(suiteWorkspace.repos, sharedWorkspacePath);
30475
+ }
30458
30476
  setupLog("shared repo materialization complete");
30459
30477
  } catch (error) {
30460
30478
  const message = error instanceof Error ? error.message : String(error);
@@ -32277,7 +32295,7 @@ async function discoverDefaultTarget(repoRoot) {
32277
32295
  for (const dir of chain) {
32278
32296
  for (const candidate of TARGET_FILE_CANDIDATES) {
32279
32297
  const targetsPath = path45.join(dir, candidate);
32280
- if (!existsSync5(targetsPath)) continue;
32298
+ if (!existsSync6(targetsPath)) continue;
32281
32299
  try {
32282
32300
  const definitions = await readTargetDefinitions(targetsPath);
32283
32301
  const defaultTarget = definitions.find((d) => d.name === "default");
@@ -32294,7 +32312,7 @@ async function loadEnvHierarchy(repoRoot, startPath) {
32294
32312
  const envFiles = [];
32295
32313
  for (const dir of chain) {
32296
32314
  const envPath = path45.join(dir, ".env");
32297
- if (existsSync5(envPath)) envFiles.push(envPath);
32315
+ if (existsSync6(envPath)) envFiles.push(envPath);
32298
32316
  }
32299
32317
  for (let i = 0; i < envFiles.length; i++) {
32300
32318
  try {
@@ -32367,12 +32385,12 @@ var CONFIG_FILE_NAMES = [
32367
32385
  ".agentv/config.js"
32368
32386
  ];
32369
32387
  async function loadTsConfig(projectRoot) {
32370
- const { existsSync: existsSync7 } = await import("node:fs");
32388
+ const { existsSync: existsSync8 } = await import("node:fs");
32371
32389
  const { pathToFileURL: pathToFileURL2 } = await import("node:url");
32372
32390
  const { join: join2 } = await import("node:path");
32373
32391
  for (const fileName of CONFIG_FILE_NAMES) {
32374
32392
  const filePath = join2(projectRoot, fileName);
32375
- if (!existsSync7(filePath)) {
32393
+ if (!existsSync8(filePath)) {
32376
32394
  continue;
32377
32395
  }
32378
32396
  try {
@@ -32463,6 +32481,98 @@ function buildPrompt(criteria, question, referenceAnswer) {
32463
32481
  }
32464
32482
  return parts.join("\n");
32465
32483
  }
32484
+ function normalizeGitUrl(url) {
32485
+ let normalized = url.replace(/\.git$/, "");
32486
+ try {
32487
+ const parsed = new URL(normalized);
32488
+ parsed.hostname = parsed.hostname.toLowerCase();
32489
+ normalized = parsed.toString().replace(/\/$/, "");
32490
+ } catch {
32491
+ }
32492
+ return normalized;
32493
+ }
32494
+ async function scanRepoDeps(evalFilePaths) {
32495
+ const seen = /* @__PURE__ */ new Map();
32496
+ const errors = [];
32497
+ for (const filePath of evalFilePaths) {
32498
+ try {
32499
+ const repos = await extractReposFromEvalFile(filePath);
32500
+ for (const repo of repos) {
32501
+ if (repo.source.type !== "git") continue;
32502
+ const ref = repo.checkout?.ref;
32503
+ const key = `${normalizeGitUrl(repo.source.url)}\0${ref ?? ""}`;
32504
+ const existing = seen.get(key);
32505
+ if (existing) {
32506
+ existing.usedBy.push(filePath);
32507
+ } else {
32508
+ const { ref: _ref, ...checkoutRest } = repo.checkout ?? {};
32509
+ const hasCheckout = Object.keys(checkoutRest).length > 0;
32510
+ seen.set(key, {
32511
+ url: repo.source.url,
32512
+ ref,
32513
+ clone: repo.clone,
32514
+ checkout: hasCheckout ? checkoutRest : void 0,
32515
+ usedBy: [filePath]
32516
+ });
32517
+ }
32518
+ }
32519
+ } catch (err) {
32520
+ errors.push({
32521
+ file: filePath,
32522
+ message: err instanceof Error ? err.message : String(err)
32523
+ });
32524
+ }
32525
+ }
32526
+ return { repos: [...seen.values()], errors };
32527
+ }
32528
+ async function extractReposFromEvalFile(filePath) {
32529
+ const content = await readFile13(filePath, "utf8");
32530
+ const parsed = interpolateEnv(parse5(content), process.env);
32531
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return [];
32532
+ const obj = parsed;
32533
+ const evalFileDir = path46.dirname(path46.resolve(filePath));
32534
+ const repos = [];
32535
+ const suiteRepos = await extractReposFromWorkspaceRaw(obj.workspace, evalFileDir);
32536
+ repos.push(...suiteRepos);
32537
+ const tests = Array.isArray(obj.tests) ? obj.tests : [];
32538
+ for (const test of tests) {
32539
+ if (test && typeof test === "object" && !Array.isArray(test)) {
32540
+ const testObj = test;
32541
+ const testRepos = await extractReposFromWorkspaceRaw(testObj.workspace, evalFileDir);
32542
+ repos.push(...testRepos);
32543
+ }
32544
+ }
32545
+ return repos;
32546
+ }
32547
+ async function extractReposFromWorkspaceRaw(raw, evalFileDir) {
32548
+ if (typeof raw === "string") {
32549
+ const workspaceFilePath = path46.resolve(evalFileDir, raw);
32550
+ const content = await readFile13(workspaceFilePath, "utf8");
32551
+ const parsed = interpolateEnv(parse5(content), process.env);
32552
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return [];
32553
+ return extractReposFromObject(parsed);
32554
+ }
32555
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
32556
+ return extractReposFromObject(raw);
32557
+ }
32558
+ return [];
32559
+ }
32560
+ function extractReposFromObject(obj) {
32561
+ const rawRepos = Array.isArray(obj.repos) ? obj.repos : [];
32562
+ const result = [];
32563
+ for (const r of rawRepos) {
32564
+ if (!r || typeof r !== "object" || Array.isArray(r)) continue;
32565
+ const repo = r;
32566
+ const source = parseRepoSource(repo.source);
32567
+ if (!source) continue;
32568
+ result.push({
32569
+ source,
32570
+ checkout: parseRepoCheckout(repo.checkout),
32571
+ clone: parseRepoClone(repo.clone)
32572
+ });
32573
+ }
32574
+ return result;
32575
+ }
32466
32576
  var DEFAULT_CACHE_PATH = ".agentv/cache";
32467
32577
  var ResponseCache = class {
32468
32578
  cachePath;
@@ -32472,7 +32582,7 @@ var ResponseCache = class {
32472
32582
  async get(key) {
32473
32583
  const filePath = this.keyToPath(key);
32474
32584
  try {
32475
- const data = await readFile13(filePath, "utf8");
32585
+ const data = await readFile14(filePath, "utf8");
32476
32586
  return JSON.parse(data);
32477
32587
  } catch {
32478
32588
  return void 0;
@@ -32480,13 +32590,13 @@ var ResponseCache = class {
32480
32590
  }
32481
32591
  async set(key, value) {
32482
32592
  const filePath = this.keyToPath(key);
32483
- const dir = path46.dirname(filePath);
32593
+ const dir = path47.dirname(filePath);
32484
32594
  await mkdir15(dir, { recursive: true });
32485
32595
  await writeFile8(filePath, JSON.stringify(value, null, 2), "utf8");
32486
32596
  }
32487
32597
  keyToPath(key) {
32488
32598
  const prefix = key.slice(0, 2);
32489
- return path46.join(this.cachePath, prefix, `${key}.json`);
32599
+ return path47.join(this.cachePath, prefix, `${key}.json`);
32490
32600
  }
32491
32601
  };
32492
32602
  function shouldEnableCache(params) {
@@ -32501,11 +32611,11 @@ function shouldSkipCacheForTemperature(targetConfig) {
32501
32611
  return false;
32502
32612
  }
32503
32613
  function getProjectsRegistryPath() {
32504
- return path47.join(getAgentvHome(), "projects.yaml");
32614
+ return path48.join(getAgentvHome(), "projects.yaml");
32505
32615
  }
32506
32616
  function loadProjectRegistry() {
32507
32617
  const registryPath = getProjectsRegistryPath();
32508
- if (!existsSync6(registryPath)) {
32618
+ if (!existsSync7(registryPath)) {
32509
32619
  return { projects: [] };
32510
32620
  }
32511
32621
  try {
@@ -32521,14 +32631,14 @@ function loadProjectRegistry() {
32521
32631
  }
32522
32632
  function saveProjectRegistry(registry) {
32523
32633
  const registryPath = getProjectsRegistryPath();
32524
- const dir = path47.dirname(registryPath);
32525
- if (!existsSync6(dir)) {
32634
+ const dir = path48.dirname(registryPath);
32635
+ if (!existsSync7(dir)) {
32526
32636
  mkdirSync2(dir, { recursive: true });
32527
32637
  }
32528
32638
  writeFileSync(registryPath, stringifyYaml(registry), "utf-8");
32529
32639
  }
32530
32640
  function deriveProjectId(dirPath, existingIds) {
32531
- const base = path47.basename(dirPath).toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
32641
+ const base = path48.basename(dirPath).toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
32532
32642
  let candidate = base || "project";
32533
32643
  let suffix = 2;
32534
32644
  while (existingIds.includes(candidate)) {
@@ -32538,11 +32648,11 @@ function deriveProjectId(dirPath, existingIds) {
32538
32648
  return candidate;
32539
32649
  }
32540
32650
  function addProject(projectPath) {
32541
- const absPath = path47.resolve(projectPath);
32542
- if (!existsSync6(absPath)) {
32651
+ const absPath = path48.resolve(projectPath);
32652
+ if (!existsSync7(absPath)) {
32543
32653
  throw new Error(`Directory not found: ${absPath}`);
32544
32654
  }
32545
- if (!existsSync6(path47.join(absPath, ".agentv"))) {
32655
+ if (!existsSync7(path48.join(absPath, ".agentv"))) {
32546
32656
  throw new Error(`No .agentv/ directory found in ${absPath}. Run an evaluation first.`);
32547
32657
  }
32548
32658
  const registry = loadProjectRegistry();
@@ -32556,7 +32666,7 @@ function addProject(projectPath) {
32556
32666
  absPath,
32557
32667
  registry.projects.map((p) => p.id)
32558
32668
  ),
32559
- name: path47.basename(absPath),
32669
+ name: path48.basename(absPath),
32560
32670
  path: absPath,
32561
32671
  addedAt: now2,
32562
32672
  lastOpenedAt: now2
@@ -32585,14 +32695,14 @@ function touchProject(projectId) {
32585
32695
  }
32586
32696
  }
32587
32697
  function discoverProjects(rootDir, maxDepth = 2) {
32588
- const absRoot = path47.resolve(rootDir);
32589
- if (!existsSync6(absRoot) || !statSync2(absRoot).isDirectory()) {
32698
+ const absRoot = path48.resolve(rootDir);
32699
+ if (!existsSync7(absRoot) || !statSync2(absRoot).isDirectory()) {
32590
32700
  return [];
32591
32701
  }
32592
32702
  const results = [];
32593
32703
  function scan(dir, depth) {
32594
32704
  if (depth > maxDepth) return;
32595
- if (existsSync6(path47.join(dir, ".agentv"))) {
32705
+ if (existsSync7(path48.join(dir, ".agentv"))) {
32596
32706
  results.push(dir);
32597
32707
  return;
32598
32708
  }
@@ -32602,7 +32712,7 @@ function discoverProjects(rootDir, maxDepth = 2) {
32602
32712
  for (const entry of entries) {
32603
32713
  if (!entry.isDirectory()) continue;
32604
32714
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
32605
- scan(path47.join(dir, entry.name), depth + 1);
32715
+ scan(path48.join(dir, entry.name), depth + 1);
32606
32716
  }
32607
32717
  } catch {
32608
32718
  }
@@ -33501,7 +33611,7 @@ function extractResponseItemContent(content) {
33501
33611
  }
33502
33612
  return parts.length > 0 ? parts.join("") : void 0;
33503
33613
  }
33504
- var DEFAULT_SESSIONS_DIR = () => path48.join(homedir3(), ".codex", "sessions");
33614
+ var DEFAULT_SESSIONS_DIR = () => path49.join(homedir3(), ".codex", "sessions");
33505
33615
  async function discoverCodexSessions(opts) {
33506
33616
  const sessionsDir = opts?.sessionsDir ?? DEFAULT_SESSIONS_DIR();
33507
33617
  const limit = opts?.latest ? 1 : opts?.limit ?? 10;
@@ -33513,7 +33623,7 @@ async function discoverCodexSessions(opts) {
33513
33623
  return [];
33514
33624
  }
33515
33625
  for (const year of yearDirs) {
33516
- const yearPath = path48.join(sessionsDir, year);
33626
+ const yearPath = path49.join(sessionsDir, year);
33517
33627
  let monthDirs;
33518
33628
  try {
33519
33629
  monthDirs = await readdir8(yearPath);
@@ -33521,7 +33631,7 @@ async function discoverCodexSessions(opts) {
33521
33631
  continue;
33522
33632
  }
33523
33633
  for (const month of monthDirs) {
33524
- const monthPath = path48.join(yearPath, month);
33634
+ const monthPath = path49.join(yearPath, month);
33525
33635
  let dayDirs;
33526
33636
  try {
33527
33637
  dayDirs = await readdir8(monthPath);
@@ -33533,7 +33643,7 @@ async function discoverCodexSessions(opts) {
33533
33643
  const dirDate = `${year}-${month}-${day}`;
33534
33644
  if (dirDate !== opts.date) continue;
33535
33645
  }
33536
- const dayPath = path48.join(monthPath, day);
33646
+ const dayPath = path49.join(monthPath, day);
33537
33647
  let files;
33538
33648
  try {
33539
33649
  files = await readdir8(dayPath);
@@ -33542,7 +33652,7 @@ async function discoverCodexSessions(opts) {
33542
33652
  }
33543
33653
  for (const file of files) {
33544
33654
  if (!file.startsWith("rollout-") || !file.endsWith(".jsonl")) continue;
33545
- const filePath = path48.join(dayPath, file);
33655
+ const filePath = path49.join(dayPath, file);
33546
33656
  const nameWithoutExt = file.replace(/\.jsonl$/, "");
33547
33657
  const parts = nameWithoutExt.split("-");
33548
33658
  const sessionId = parts.length >= 6 ? parts.slice(-5).join("-") : nameWithoutExt;
@@ -33561,7 +33671,7 @@ async function discoverCodexSessions(opts) {
33561
33671
  sessions.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
33562
33672
  return sessions.slice(0, limit);
33563
33673
  }
33564
- var DEFAULT_PROJECTS_DIR = () => path49.join(homedir4(), ".claude", "projects");
33674
+ var DEFAULT_PROJECTS_DIR = () => path50.join(homedir4(), ".claude", "projects");
33565
33675
  function encodeProjectPath(projectPath) {
33566
33676
  return projectPath.replace(/\//g, "-");
33567
33677
  }
@@ -33580,7 +33690,7 @@ async function discoverClaudeSessions(opts) {
33580
33690
  }
33581
33691
  const sessions = [];
33582
33692
  for (const projectDir of projectDirs) {
33583
- const dirPath = path49.join(projectsDir, projectDir);
33693
+ const dirPath = path50.join(projectsDir, projectDir);
33584
33694
  let entries;
33585
33695
  try {
33586
33696
  entries = await readdir9(dirPath);
@@ -33591,7 +33701,7 @@ async function discoverClaudeSessions(opts) {
33591
33701
  if (!entry.endsWith(".jsonl")) continue;
33592
33702
  const sessionId = entry.replace(/\.jsonl$/, "");
33593
33703
  if (opts?.sessionId && sessionId !== opts.sessionId) continue;
33594
- const filePath = path49.join(dirPath, entry);
33704
+ const filePath = path50.join(dirPath, entry);
33595
33705
  let updatedAt;
33596
33706
  try {
33597
33707
  const fileStat = await stat10(filePath);
@@ -33635,11 +33745,11 @@ function toTranscriptJsonLine(entry) {
33635
33745
  };
33636
33746
  }
33637
33747
  async function readTranscriptJsonl(filePath) {
33638
- const text2 = await readFile14(filePath, "utf8");
33748
+ const text2 = await readFile15(filePath, "utf8");
33639
33749
  return text2.split("\n").filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
33640
33750
  }
33641
33751
  async function readTranscriptFile(filePath) {
33642
- return readFile14(filePath, "utf8");
33752
+ return readFile15(filePath, "utf8");
33643
33753
  }
33644
33754
  var TranscriptProvider = class _TranscriptProvider {
33645
33755
  id;
@@ -33842,6 +33952,7 @@ export {
33842
33952
  defineConfig,
33843
33953
  loadTsConfig,
33844
33954
  generateRubrics,
33955
+ scanRepoDeps,
33845
33956
  ResponseCache,
33846
33957
  shouldEnableCache,
33847
33958
  shouldSkipCacheForTemperature,
@@ -33870,4 +33981,4 @@ export {
33870
33981
  TranscriptProvider,
33871
33982
  createAgentKernel
33872
33983
  };
33873
- //# sourceMappingURL=chunk-H4GQXK5M.js.map
33984
+ //# sourceMappingURL=chunk-RHAXSXIY.js.map