@agentv/core 4.7.0 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1355,13 +1355,13 @@ function serializeAttributeValue(value) {
1355
1355
  if (Array.isArray(value)) return { arrayValue: { values: value.map(serializeAttributeValue) } };
1356
1356
  return { stringValue: String(value) };
1357
1357
  }
1358
- var import_promises35, import_node_path52, OtlpJsonFileExporter;
1358
+ var import_promises36, import_node_path53, OtlpJsonFileExporter;
1359
1359
  var init_otlp_json_file_exporter = __esm({
1360
1360
  "src/observability/otlp-json-file-exporter.ts"() {
1361
1361
  "use strict";
1362
1362
  init_cjs_shims();
1363
- import_promises35 = require("fs/promises");
1364
- import_node_path52 = require("path");
1363
+ import_promises36 = require("fs/promises");
1364
+ import_node_path53 = require("path");
1365
1365
  OtlpJsonFileExporter = class {
1366
1366
  // biome-ignore lint/suspicious/noExplicitAny: serialized span data
1367
1367
  spans = [];
@@ -1400,7 +1400,7 @@ var init_otlp_json_file_exporter = __esm({
1400
1400
  }
1401
1401
  async flush() {
1402
1402
  if (this.spans.length === 0) return;
1403
- await (0, import_promises35.mkdir)((0, import_node_path52.dirname)(this.filePath), { recursive: true });
1403
+ await (0, import_promises36.mkdir)((0, import_node_path53.dirname)(this.filePath), { recursive: true });
1404
1404
  const otlpJson = {
1405
1405
  resourceSpans: [
1406
1406
  {
@@ -1583,6 +1583,7 @@ __export(index_exports, {
1583
1583
  runRegexAssertion: () => runRegexAssertion,
1584
1584
  runStartsWithAssertion: () => runStartsWithAssertion,
1585
1585
  saveProjectRegistry: () => saveProjectRegistry,
1586
+ scanRepoDeps: () => scanRepoDeps,
1586
1587
  scoreToVerdict: () => scoreToVerdict,
1587
1588
  shouldEnableCache: () => shouldEnableCache,
1588
1589
  shouldSkipCacheForTemperature: () => shouldSkipCacheForTemperature,
@@ -4741,6 +4742,61 @@ function parseMetadata(suite) {
4741
4742
  });
4742
4743
  }
4743
4744
 
4745
+ // src/evaluation/workspace/repo-config-parser.ts
4746
+ init_cjs_shims();
4747
+ function parseRepoSource(raw) {
4748
+ if (!isJsonObject(raw)) return void 0;
4749
+ const obj = raw;
4750
+ if (obj.type === "git" && typeof obj.url === "string") {
4751
+ return { type: "git", url: obj.url };
4752
+ }
4753
+ if (obj.type === "local" && typeof obj.path === "string") {
4754
+ return { type: "local", path: obj.path };
4755
+ }
4756
+ return void 0;
4757
+ }
4758
+ function parseRepoCheckout(raw) {
4759
+ if (!isJsonObject(raw)) return void 0;
4760
+ const obj = raw;
4761
+ const ref = typeof obj.ref === "string" ? obj.ref : void 0;
4762
+ const resolve = obj.resolve === "remote" || obj.resolve === "local" ? obj.resolve : void 0;
4763
+ const ancestor = typeof obj.ancestor === "number" ? obj.ancestor : void 0;
4764
+ if (!ref && !resolve && ancestor === void 0) return void 0;
4765
+ return {
4766
+ ...ref !== void 0 && { ref },
4767
+ ...resolve !== void 0 && { resolve },
4768
+ ...ancestor !== void 0 && { ancestor }
4769
+ };
4770
+ }
4771
+ function parseRepoClone(raw) {
4772
+ if (!isJsonObject(raw)) return void 0;
4773
+ const obj = raw;
4774
+ const depth = typeof obj.depth === "number" ? obj.depth : void 0;
4775
+ const filter = typeof obj.filter === "string" ? obj.filter : void 0;
4776
+ const sparse = Array.isArray(obj.sparse) ? obj.sparse.filter((s) => typeof s === "string") : void 0;
4777
+ if (depth === void 0 && !filter && !sparse) return void 0;
4778
+ return {
4779
+ ...depth !== void 0 && { depth },
4780
+ ...filter !== void 0 && { filter },
4781
+ ...sparse !== void 0 && { sparse }
4782
+ };
4783
+ }
4784
+ function parseRepoConfig(raw) {
4785
+ if (!isJsonObject(raw)) return void 0;
4786
+ const obj = raw;
4787
+ const repoPath = typeof obj.path === "string" ? obj.path : void 0;
4788
+ const source = parseRepoSource(obj.source);
4789
+ if (!repoPath || !source) return void 0;
4790
+ const checkout = parseRepoCheckout(obj.checkout);
4791
+ const clone = parseRepoClone(obj.clone);
4792
+ return {
4793
+ path: repoPath,
4794
+ source,
4795
+ ...checkout !== void 0 && { checkout },
4796
+ ...clone !== void 0 && { clone }
4797
+ };
4798
+ }
4799
+
4744
4800
  // src/evaluation/formatting/prompt-builder.ts
4745
4801
  init_cjs_shims();
4746
4802
  async function buildPromptInputs(testCase, mode = "lm") {
@@ -5136,58 +5192,6 @@ function parseWorkspaceScriptConfig(raw, evalFileDir) {
5136
5192
  }
5137
5193
  return cwd ? { ...config, cwd } : config;
5138
5194
  }
5139
- function parseRepoSource(raw) {
5140
- if (!isJsonObject(raw)) return void 0;
5141
- const obj = raw;
5142
- if (obj.type === "git" && typeof obj.url === "string") {
5143
- return { type: "git", url: obj.url };
5144
- }
5145
- if (obj.type === "local" && typeof obj.path === "string") {
5146
- return { type: "local", path: obj.path };
5147
- }
5148
- return void 0;
5149
- }
5150
- function parseRepoCheckout(raw) {
5151
- if (!isJsonObject(raw)) return void 0;
5152
- const obj = raw;
5153
- const ref = typeof obj.ref === "string" ? obj.ref : void 0;
5154
- const resolve = obj.resolve === "remote" || obj.resolve === "local" ? obj.resolve : void 0;
5155
- const ancestor = typeof obj.ancestor === "number" ? obj.ancestor : void 0;
5156
- if (!ref && !resolve && ancestor === void 0) return void 0;
5157
- return {
5158
- ...ref !== void 0 && { ref },
5159
- ...resolve !== void 0 && { resolve },
5160
- ...ancestor !== void 0 && { ancestor }
5161
- };
5162
- }
5163
- function parseRepoClone(raw) {
5164
- if (!isJsonObject(raw)) return void 0;
5165
- const obj = raw;
5166
- const depth = typeof obj.depth === "number" ? obj.depth : void 0;
5167
- const filter = typeof obj.filter === "string" ? obj.filter : void 0;
5168
- const sparse = Array.isArray(obj.sparse) ? obj.sparse.filter((s) => typeof s === "string") : void 0;
5169
- if (depth === void 0 && !filter && !sparse) return void 0;
5170
- return {
5171
- ...depth !== void 0 && { depth },
5172
- ...filter !== void 0 && { filter },
5173
- ...sparse !== void 0 && { sparse }
5174
- };
5175
- }
5176
- function parseRepoConfig(raw) {
5177
- if (!isJsonObject(raw)) return void 0;
5178
- const obj = raw;
5179
- const repoPath = typeof obj.path === "string" ? obj.path : void 0;
5180
- const source = parseRepoSource(obj.source);
5181
- if (!repoPath || !source) return void 0;
5182
- const checkout = parseRepoCheckout(obj.checkout);
5183
- const clone = parseRepoClone(obj.clone);
5184
- return {
5185
- path: repoPath,
5186
- source,
5187
- ...checkout !== void 0 && { checkout },
5188
- ...clone !== void 0 && { clone }
5189
- };
5190
- }
5191
5195
  function parseWorkspaceHookConfig(raw, evalFileDir) {
5192
5196
  if (!isJsonObject(raw)) return void 0;
5193
5197
  const script = parseWorkspaceScriptConfig(raw, evalFileDir);
@@ -9101,6 +9105,25 @@ var CopilotSdkProvider = class {
9101
9105
  content: systemPrompt
9102
9106
  };
9103
9107
  }
9108
+ if (this.config.byokBaseUrl) {
9109
+ const byokType = this.config.byokType ?? "openai";
9110
+ const provider = {
9111
+ type: byokType,
9112
+ baseUrl: normalizeByokBaseUrl(this.config.byokBaseUrl, byokType)
9113
+ };
9114
+ if (this.config.byokBearerToken) {
9115
+ provider.bearerToken = this.config.byokBearerToken;
9116
+ } else if (this.config.byokApiKey) {
9117
+ provider.apiKey = this.config.byokApiKey;
9118
+ }
9119
+ if (this.config.byokWireApi) {
9120
+ provider.wireApi = this.config.byokWireApi;
9121
+ }
9122
+ if (this.config.byokType === "azure" && this.config.byokApiVersion) {
9123
+ provider.azure = { apiVersion: this.config.byokApiVersion };
9124
+ }
9125
+ sessionOptions.provider = provider;
9126
+ }
9104
9127
  let session;
9105
9128
  try {
9106
9129
  session = await client.createSession(sessionOptions);
@@ -9332,6 +9355,16 @@ function resolveSkillDirectories(cwd) {
9332
9355
  ];
9333
9356
  return candidates.filter((dir) => (0, import_node_fs8.existsSync)(dir));
9334
9357
  }
9358
+ function normalizeByokBaseUrl(baseUrl, type) {
9359
+ const trimmed = baseUrl.trim().replace(/\/+$/, "");
9360
+ if (/^https?:\/\//i.test(trimmed)) {
9361
+ return trimmed;
9362
+ }
9363
+ if (type === "azure") {
9364
+ return `https://${trimmed}.openai.azure.com`;
9365
+ }
9366
+ return trimmed;
9367
+ }
9335
9368
  function summarizeSdkEvent(eventType, data) {
9336
9369
  if (!data || typeof data !== "object") {
9337
9370
  return eventType;
@@ -11831,6 +11864,52 @@ function resolveCopilotSdkConfig(target, env, evalFilePath) {
11831
11864
  );
11832
11865
  const logFormat = normalizeCopilotLogFormat(logFormatSource);
11833
11866
  const systemPrompt = typeof systemPromptSource === "string" && systemPromptSource.trim().length > 0 ? systemPromptSource.trim() : void 0;
11867
+ const byok = target.byok;
11868
+ let byokType;
11869
+ let byokBaseUrl;
11870
+ let byokApiKey;
11871
+ let byokBearerToken;
11872
+ let byokApiVersion;
11873
+ let byokWireApi;
11874
+ if (byok && typeof byok === "object") {
11875
+ byokType = resolveOptionalString(byok.type, env, `${target.name} byok type`, {
11876
+ allowLiteral: true,
11877
+ optionalEnv: true
11878
+ });
11879
+ byokBaseUrl = resolveOptionalString(byok.base_url, env, `${target.name} byok base URL`, {
11880
+ allowLiteral: true,
11881
+ optionalEnv: true
11882
+ });
11883
+ byokApiKey = resolveOptionalString(byok.api_key, env, `${target.name} byok API key`, {
11884
+ allowLiteral: false,
11885
+ optionalEnv: true
11886
+ });
11887
+ byokBearerToken = resolveOptionalString(
11888
+ byok.bearer_token,
11889
+ env,
11890
+ `${target.name} byok bearer token`,
11891
+ {
11892
+ allowLiteral: false,
11893
+ optionalEnv: true
11894
+ }
11895
+ );
11896
+ byokApiVersion = resolveOptionalString(
11897
+ byok.api_version,
11898
+ env,
11899
+ `${target.name} byok API version`,
11900
+ {
11901
+ allowLiteral: true,
11902
+ optionalEnv: true
11903
+ }
11904
+ );
11905
+ byokWireApi = resolveOptionalString(byok.wire_api, env, `${target.name} byok wire API`, {
11906
+ allowLiteral: true,
11907
+ optionalEnv: true
11908
+ });
11909
+ if (!byokBaseUrl) {
11910
+ throw new Error(`${target.name}: 'byok.base_url' is required when 'byok' is specified`);
11911
+ }
11912
+ }
11834
11913
  return {
11835
11914
  cliUrl,
11836
11915
  cliPath,
@@ -11841,7 +11920,13 @@ function resolveCopilotSdkConfig(target, env, evalFilePath) {
11841
11920
  timeoutMs,
11842
11921
  logDir,
11843
11922
  logFormat,
11844
- systemPrompt
11923
+ systemPrompt,
11924
+ byokType,
11925
+ byokBaseUrl,
11926
+ byokApiKey,
11927
+ byokBearerToken,
11928
+ byokApiVersion,
11929
+ byokWireApi
11845
11930
  };
11846
11931
  }
11847
11932
  function resolveCopilotCliConfig(target, env, evalFilePath) {
@@ -12210,8 +12295,8 @@ function resolveCliConfig(target, env, evalFilePath) {
12210
12295
  const parseResult = CliTargetInputSchema.safeParse(target, { errorMap: cliErrorMap });
12211
12296
  if (!parseResult.success) {
12212
12297
  const firstError = parseResult.error.errors[0];
12213
- const path53 = firstError?.path.join(".") || "";
12214
- const prefix = path53 ? `${target.name} ${path53}: ` : `${target.name}: `;
12298
+ const path54 = firstError?.path.join(".") || "";
12299
+ const prefix = path54 ? `${target.name} ${path54}: ` : `${target.name}: `;
12215
12300
  throw new Error(`${prefix}${firstError?.message}`);
12216
12301
  }
12217
12302
  const normalized = normalizeCliTargetInput(parseResult.data, env, evalFilePath);
@@ -14256,15 +14341,15 @@ async function execFileWithStdinNode(argv, stdinPayload, options) {
14256
14341
  });
14257
14342
  }
14258
14343
  async function execShellWithStdin(command, stdinPayload, options = {}) {
14259
- const { mkdir: mkdir17, readFile: readFile17, rm: rm6, writeFile: writeFile9 } = await import("fs/promises");
14344
+ const { mkdir: mkdir17, readFile: readFile18, rm: rm6, writeFile: writeFile9 } = await import("fs/promises");
14260
14345
  const { tmpdir: tmpdir3 } = await import("os");
14261
- const path53 = await import("path");
14346
+ const path54 = await import("path");
14262
14347
  const { randomUUID: randomUUID10 } = await import("crypto");
14263
- const dir = path53.join(tmpdir3(), `agentv-exec-${randomUUID10()}`);
14348
+ const dir = path54.join(tmpdir3(), `agentv-exec-${randomUUID10()}`);
14264
14349
  await mkdir17(dir, { recursive: true });
14265
- const stdinPath = path53.join(dir, "stdin.txt");
14266
- const stdoutPath = path53.join(dir, "stdout.txt");
14267
- const stderrPath = path53.join(dir, "stderr.txt");
14350
+ const stdinPath = path54.join(dir, "stdin.txt");
14351
+ const stdoutPath = path54.join(dir, "stdout.txt");
14352
+ const stderrPath = path54.join(dir, "stderr.txt");
14268
14353
  await writeFile9(stdinPath, stdinPayload, "utf8");
14269
14354
  const wrappedCommand = process.platform === "win32" ? `(${command}) < ${shellEscapePath(stdinPath)} > ${shellEscapePath(stdoutPath)} 2> ${shellEscapePath(stderrPath)}` : `(${command}) < ${shellEscapePath(stdinPath)} > ${shellEscapePath(stdoutPath)} 2> ${shellEscapePath(stderrPath)}`;
14270
14355
  const { spawn: spawn5 } = await import("child_process");
@@ -14294,8 +14379,8 @@ async function execShellWithStdin(command, stdinPayload, options = {}) {
14294
14379
  resolve(code ?? 0);
14295
14380
  });
14296
14381
  });
14297
- const stdout = (await readFile17(stdoutPath, "utf8")).replace(/\r\n/g, "\n");
14298
- const stderr = (await readFile17(stderrPath, "utf8")).replace(/\r\n/g, "\n");
14382
+ const stdout = (await readFile18(stdoutPath, "utf8")).replace(/\r\n/g, "\n");
14383
+ const stderr = (await readFile18(stderrPath, "utf8")).replace(/\r\n/g, "\n");
14299
14384
  return { stdout, stderr, exitCode };
14300
14385
  } finally {
14301
14386
  await rm6(dir, { recursive: true, force: true });
@@ -16561,115 +16646,115 @@ var FieldAccuracyEvaluator = class {
16561
16646
  * Evaluate a single field against the expected value.
16562
16647
  */
16563
16648
  evaluateField(fieldConfig, candidateData, expectedData) {
16564
- const { path: path53, match, required = true, weight = 1 } = fieldConfig;
16565
- const candidateValue = resolvePath(candidateData, path53);
16566
- const expectedValue = resolvePath(expectedData, path53);
16649
+ const { path: path54, match, required = true, weight = 1 } = fieldConfig;
16650
+ const candidateValue = resolvePath(candidateData, path54);
16651
+ const expectedValue = resolvePath(expectedData, path54);
16567
16652
  if (expectedValue === void 0) {
16568
16653
  return {
16569
- path: path53,
16654
+ path: path54,
16570
16655
  score: 1,
16571
16656
  // No expected value means no comparison needed
16572
16657
  weight,
16573
16658
  hit: true,
16574
- message: `${path53}: no expected value`
16659
+ message: `${path54}: no expected value`
16575
16660
  };
16576
16661
  }
16577
16662
  if (candidateValue === void 0) {
16578
16663
  if (required) {
16579
16664
  return {
16580
- path: path53,
16665
+ path: path54,
16581
16666
  score: 0,
16582
16667
  weight,
16583
16668
  hit: false,
16584
- message: `${path53} (required, missing)`
16669
+ message: `${path54} (required, missing)`
16585
16670
  };
16586
16671
  }
16587
16672
  return {
16588
- path: path53,
16673
+ path: path54,
16589
16674
  score: 1,
16590
16675
  // Don't penalize missing optional fields
16591
16676
  weight: 0,
16592
16677
  // Zero weight means it won't affect the score
16593
16678
  hit: true,
16594
- message: `${path53}: optional field missing`
16679
+ message: `${path54}: optional field missing`
16595
16680
  };
16596
16681
  }
16597
16682
  switch (match) {
16598
16683
  case "exact":
16599
- return this.compareExact(path53, candidateValue, expectedValue, weight);
16684
+ return this.compareExact(path54, candidateValue, expectedValue, weight);
16600
16685
  case "numeric_tolerance":
16601
16686
  return this.compareNumericTolerance(
16602
- path53,
16687
+ path54,
16603
16688
  candidateValue,
16604
16689
  expectedValue,
16605
16690
  fieldConfig,
16606
16691
  weight
16607
16692
  );
16608
16693
  case "date":
16609
- return this.compareDate(path53, candidateValue, expectedValue, fieldConfig, weight);
16694
+ return this.compareDate(path54, candidateValue, expectedValue, fieldConfig, weight);
16610
16695
  default:
16611
16696
  return {
16612
- path: path53,
16697
+ path: path54,
16613
16698
  score: 0,
16614
16699
  weight,
16615
16700
  hit: false,
16616
- message: `${path53}: unknown match type "${match}"`
16701
+ message: `${path54}: unknown match type "${match}"`
16617
16702
  };
16618
16703
  }
16619
16704
  }
16620
16705
  /**
16621
16706
  * Exact equality comparison.
16622
16707
  */
16623
- compareExact(path53, candidateValue, expectedValue, weight) {
16708
+ compareExact(path54, candidateValue, expectedValue, weight) {
16624
16709
  if (deepEqual(candidateValue, expectedValue)) {
16625
16710
  return {
16626
- path: path53,
16711
+ path: path54,
16627
16712
  score: 1,
16628
16713
  weight,
16629
16714
  hit: true,
16630
- message: path53
16715
+ message: path54
16631
16716
  };
16632
16717
  }
16633
16718
  if (typeof candidateValue !== typeof expectedValue) {
16634
16719
  return {
16635
- path: path53,
16720
+ path: path54,
16636
16721
  score: 0,
16637
16722
  weight,
16638
16723
  hit: false,
16639
- message: `${path53} (type mismatch: got ${typeof candidateValue}, expected ${typeof expectedValue})`
16724
+ message: `${path54} (type mismatch: got ${typeof candidateValue}, expected ${typeof expectedValue})`
16640
16725
  };
16641
16726
  }
16642
16727
  return {
16643
- path: path53,
16728
+ path: path54,
16644
16729
  score: 0,
16645
16730
  weight,
16646
16731
  hit: false,
16647
- message: `${path53} (value mismatch)`
16732
+ message: `${path54} (value mismatch)`
16648
16733
  };
16649
16734
  }
16650
16735
  /**
16651
16736
  * Numeric comparison with absolute or relative tolerance.
16652
16737
  */
16653
- compareNumericTolerance(path53, candidateValue, expectedValue, fieldConfig, weight) {
16738
+ compareNumericTolerance(path54, candidateValue, expectedValue, fieldConfig, weight) {
16654
16739
  const { tolerance = 0, relative = false } = fieldConfig;
16655
16740
  const candidateNum = toNumber(candidateValue);
16656
16741
  const expectedNum = toNumber(expectedValue);
16657
16742
  if (candidateNum === null || expectedNum === null) {
16658
16743
  return {
16659
- path: path53,
16744
+ path: path54,
16660
16745
  score: 0,
16661
16746
  weight,
16662
16747
  hit: false,
16663
- message: `${path53} (non-numeric value)`
16748
+ message: `${path54} (non-numeric value)`
16664
16749
  };
16665
16750
  }
16666
16751
  if (!Number.isFinite(candidateNum) || !Number.isFinite(expectedNum)) {
16667
16752
  return {
16668
- path: path53,
16753
+ path: path54,
16669
16754
  score: 0,
16670
16755
  weight,
16671
16756
  hit: false,
16672
- message: `${path53} (invalid numeric value)`
16757
+ message: `${path54} (invalid numeric value)`
16673
16758
  };
16674
16759
  }
16675
16760
  const diff = Math.abs(candidateNum - expectedNum);
@@ -16682,61 +16767,61 @@ var FieldAccuracyEvaluator = class {
16682
16767
  }
16683
16768
  if (withinTolerance) {
16684
16769
  return {
16685
- path: path53,
16770
+ path: path54,
16686
16771
  score: 1,
16687
16772
  weight,
16688
16773
  hit: true,
16689
- message: `${path53} (within tolerance: diff=${diff.toFixed(2)})`
16774
+ message: `${path54} (within tolerance: diff=${diff.toFixed(2)})`
16690
16775
  };
16691
16776
  }
16692
16777
  return {
16693
- path: path53,
16778
+ path: path54,
16694
16779
  score: 0,
16695
16780
  weight,
16696
16781
  hit: false,
16697
- message: `${path53} (outside tolerance: diff=${diff.toFixed(2)}, tolerance=${tolerance})`
16782
+ message: `${path54} (outside tolerance: diff=${diff.toFixed(2)}, tolerance=${tolerance})`
16698
16783
  };
16699
16784
  }
16700
16785
  /**
16701
16786
  * Date comparison with format normalization.
16702
16787
  */
16703
- compareDate(path53, candidateValue, expectedValue, fieldConfig, weight) {
16788
+ compareDate(path54, candidateValue, expectedValue, fieldConfig, weight) {
16704
16789
  const formats = fieldConfig.formats ?? DEFAULT_DATE_FORMATS;
16705
16790
  const candidateDate = parseDate(String(candidateValue), formats);
16706
16791
  const expectedDate = parseDate(String(expectedValue), formats);
16707
16792
  if (candidateDate === null) {
16708
16793
  return {
16709
- path: path53,
16794
+ path: path54,
16710
16795
  score: 0,
16711
16796
  weight,
16712
16797
  hit: false,
16713
- message: `${path53} (unparseable candidate date)`
16798
+ message: `${path54} (unparseable candidate date)`
16714
16799
  };
16715
16800
  }
16716
16801
  if (expectedDate === null) {
16717
16802
  return {
16718
- path: path53,
16803
+ path: path54,
16719
16804
  score: 0,
16720
16805
  weight,
16721
16806
  hit: false,
16722
- message: `${path53} (unparseable expected date)`
16807
+ message: `${path54} (unparseable expected date)`
16723
16808
  };
16724
16809
  }
16725
16810
  if (candidateDate.getFullYear() === expectedDate.getFullYear() && candidateDate.getMonth() === expectedDate.getMonth() && candidateDate.getDate() === expectedDate.getDate()) {
16726
16811
  return {
16727
- path: path53,
16812
+ path: path54,
16728
16813
  score: 1,
16729
16814
  weight,
16730
16815
  hit: true,
16731
- message: path53
16816
+ message: path54
16732
16817
  };
16733
16818
  }
16734
16819
  return {
16735
- path: path53,
16820
+ path: path54,
16736
16821
  score: 0,
16737
16822
  weight,
16738
16823
  hit: false,
16739
- message: `${path53} (date mismatch: got ${formatDateISO(candidateDate)}, expected ${formatDateISO(expectedDate)})`
16824
+ message: `${path54} (date mismatch: got ${formatDateISO(candidateDate)}, expected ${formatDateISO(expectedDate)})`
16740
16825
  };
16741
16826
  }
16742
16827
  /**
@@ -16769,11 +16854,11 @@ var FieldAccuracyEvaluator = class {
16769
16854
  };
16770
16855
  }
16771
16856
  };
16772
- function resolvePath(obj, path53) {
16773
- if (!path53 || !obj) {
16857
+ function resolvePath(obj, path54) {
16858
+ if (!path54 || !obj) {
16774
16859
  return void 0;
16775
16860
  }
16776
- const parts = path53.split(/\.|\[|\]/).filter((p) => p.length > 0);
16861
+ const parts = path54.split(/\.|\[|\]/).filter((p) => p.length > 0);
16777
16862
  let current = obj;
16778
16863
  for (const part of parts) {
16779
16864
  if (current === null || current === void 0) {
@@ -17270,8 +17355,8 @@ var TokenUsageEvaluator = class {
17270
17355
 
17271
17356
  // src/evaluation/evaluators/tool-trajectory.ts
17272
17357
  init_cjs_shims();
17273
- function getNestedValue(obj, path53) {
17274
- const parts = path53.split(".");
17358
+ function getNestedValue(obj, path54) {
17359
+ const parts = path54.split(".");
17275
17360
  let current = obj;
17276
17361
  for (const part of parts) {
17277
17362
  if (current === null || current === void 0 || typeof current !== "object") {
@@ -21803,10 +21888,108 @@ function buildPrompt(criteria, question, referenceAnswer) {
21803
21888
  // src/evaluation/workspace/index.ts
21804
21889
  init_cjs_shims();
21805
21890
 
21806
- // src/evaluation/cache/response-cache.ts
21891
+ // src/evaluation/workspace/deps-scanner.ts
21807
21892
  init_cjs_shims();
21808
21893
  var import_promises34 = require("fs/promises");
21809
21894
  var import_node_path50 = __toESM(require("path"), 1);
21895
+ var import_yaml8 = require("yaml");
21896
+ function normalizeGitUrl(url) {
21897
+ let normalized = url.replace(/\.git$/, "");
21898
+ try {
21899
+ const parsed = new URL(normalized);
21900
+ parsed.hostname = parsed.hostname.toLowerCase();
21901
+ normalized = parsed.toString().replace(/\/$/, "");
21902
+ } catch {
21903
+ }
21904
+ return normalized;
21905
+ }
21906
+ async function scanRepoDeps(evalFilePaths) {
21907
+ const seen = /* @__PURE__ */ new Map();
21908
+ const errors = [];
21909
+ for (const filePath of evalFilePaths) {
21910
+ try {
21911
+ const repos = await extractReposFromEvalFile(filePath);
21912
+ for (const repo of repos) {
21913
+ if (repo.source.type !== "git") continue;
21914
+ const ref = repo.checkout?.ref;
21915
+ const key = `${normalizeGitUrl(repo.source.url)}\0${ref ?? ""}`;
21916
+ const existing = seen.get(key);
21917
+ if (existing) {
21918
+ existing.usedBy.push(filePath);
21919
+ } else {
21920
+ const { ref: _ref, ...checkoutRest } = repo.checkout ?? {};
21921
+ const hasCheckout = Object.keys(checkoutRest).length > 0;
21922
+ seen.set(key, {
21923
+ url: repo.source.url,
21924
+ ref,
21925
+ clone: repo.clone,
21926
+ checkout: hasCheckout ? checkoutRest : void 0,
21927
+ usedBy: [filePath]
21928
+ });
21929
+ }
21930
+ }
21931
+ } catch (err) {
21932
+ errors.push({
21933
+ file: filePath,
21934
+ message: err instanceof Error ? err.message : String(err)
21935
+ });
21936
+ }
21937
+ }
21938
+ return { repos: [...seen.values()], errors };
21939
+ }
21940
+ async function extractReposFromEvalFile(filePath) {
21941
+ const content = await (0, import_promises34.readFile)(filePath, "utf8");
21942
+ const parsed = interpolateEnv((0, import_yaml8.parse)(content), process.env);
21943
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return [];
21944
+ const obj = parsed;
21945
+ const evalFileDir = import_node_path50.default.dirname(import_node_path50.default.resolve(filePath));
21946
+ const repos = [];
21947
+ const suiteRepos = await extractReposFromWorkspaceRaw(obj.workspace, evalFileDir);
21948
+ repos.push(...suiteRepos);
21949
+ const tests = Array.isArray(obj.tests) ? obj.tests : [];
21950
+ for (const test of tests) {
21951
+ if (test && typeof test === "object" && !Array.isArray(test)) {
21952
+ const testObj = test;
21953
+ const testRepos = await extractReposFromWorkspaceRaw(testObj.workspace, evalFileDir);
21954
+ repos.push(...testRepos);
21955
+ }
21956
+ }
21957
+ return repos;
21958
+ }
21959
+ async function extractReposFromWorkspaceRaw(raw, evalFileDir) {
21960
+ if (typeof raw === "string") {
21961
+ const workspaceFilePath = import_node_path50.default.resolve(evalFileDir, raw);
21962
+ const content = await (0, import_promises34.readFile)(workspaceFilePath, "utf8");
21963
+ const parsed = interpolateEnv((0, import_yaml8.parse)(content), process.env);
21964
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return [];
21965
+ return extractReposFromObject(parsed);
21966
+ }
21967
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
21968
+ return extractReposFromObject(raw);
21969
+ }
21970
+ return [];
21971
+ }
21972
+ function extractReposFromObject(obj) {
21973
+ const rawRepos = Array.isArray(obj.repos) ? obj.repos : [];
21974
+ const result = [];
21975
+ for (const r of rawRepos) {
21976
+ if (!r || typeof r !== "object" || Array.isArray(r)) continue;
21977
+ const repo = r;
21978
+ const source = parseRepoSource(repo.source);
21979
+ if (!source) continue;
21980
+ result.push({
21981
+ source,
21982
+ checkout: parseRepoCheckout(repo.checkout),
21983
+ clone: parseRepoClone(repo.clone)
21984
+ });
21985
+ }
21986
+ return result;
21987
+ }
21988
+
21989
+ // src/evaluation/cache/response-cache.ts
21990
+ init_cjs_shims();
21991
+ var import_promises35 = require("fs/promises");
21992
+ var import_node_path51 = __toESM(require("path"), 1);
21810
21993
  var DEFAULT_CACHE_PATH = ".agentv/cache";
21811
21994
  var ResponseCache = class {
21812
21995
  cachePath;
@@ -21816,7 +21999,7 @@ var ResponseCache = class {
21816
21999
  async get(key) {
21817
22000
  const filePath = this.keyToPath(key);
21818
22001
  try {
21819
- const data = await (0, import_promises34.readFile)(filePath, "utf8");
22002
+ const data = await (0, import_promises35.readFile)(filePath, "utf8");
21820
22003
  return JSON.parse(data);
21821
22004
  } catch {
21822
22005
  return void 0;
@@ -21824,13 +22007,13 @@ var ResponseCache = class {
21824
22007
  }
21825
22008
  async set(key, value) {
21826
22009
  const filePath = this.keyToPath(key);
21827
- const dir = import_node_path50.default.dirname(filePath);
21828
- await (0, import_promises34.mkdir)(dir, { recursive: true });
21829
- await (0, import_promises34.writeFile)(filePath, JSON.stringify(value, null, 2), "utf8");
22010
+ const dir = import_node_path51.default.dirname(filePath);
22011
+ await (0, import_promises35.mkdir)(dir, { recursive: true });
22012
+ await (0, import_promises35.writeFile)(filePath, JSON.stringify(value, null, 2), "utf8");
21830
22013
  }
21831
22014
  keyToPath(key) {
21832
22015
  const prefix = key.slice(0, 2);
21833
- return import_node_path50.default.join(this.cachePath, prefix, `${key}.json`);
22016
+ return import_node_path51.default.join(this.cachePath, prefix, `${key}.json`);
21834
22017
  }
21835
22018
  };
21836
22019
  function shouldEnableCache(params) {
@@ -21848,10 +22031,10 @@ function shouldSkipCacheForTemperature(targetConfig) {
21848
22031
  // src/projects.ts
21849
22032
  init_cjs_shims();
21850
22033
  var import_node_fs17 = require("fs");
21851
- var import_node_path51 = __toESM(require("path"), 1);
21852
- var import_yaml8 = require("yaml");
22034
+ var import_node_path52 = __toESM(require("path"), 1);
22035
+ var import_yaml9 = require("yaml");
21853
22036
  function getProjectsRegistryPath() {
21854
- return import_node_path51.default.join(getAgentvHome(), "projects.yaml");
22037
+ return import_node_path52.default.join(getAgentvHome(), "projects.yaml");
21855
22038
  }
21856
22039
  function loadProjectRegistry() {
21857
22040
  const registryPath = getProjectsRegistryPath();
@@ -21860,7 +22043,7 @@ function loadProjectRegistry() {
21860
22043
  }
21861
22044
  try {
21862
22045
  const raw = (0, import_node_fs17.readFileSync)(registryPath, "utf-8");
21863
- const parsed = (0, import_yaml8.parse)(raw);
22046
+ const parsed = (0, import_yaml9.parse)(raw);
21864
22047
  if (!parsed || !Array.isArray(parsed.projects)) {
21865
22048
  return { projects: [] };
21866
22049
  }
@@ -21871,14 +22054,14 @@ function loadProjectRegistry() {
21871
22054
  }
21872
22055
  function saveProjectRegistry(registry) {
21873
22056
  const registryPath = getProjectsRegistryPath();
21874
- const dir = import_node_path51.default.dirname(registryPath);
22057
+ const dir = import_node_path52.default.dirname(registryPath);
21875
22058
  if (!(0, import_node_fs17.existsSync)(dir)) {
21876
22059
  (0, import_node_fs17.mkdirSync)(dir, { recursive: true });
21877
22060
  }
21878
- (0, import_node_fs17.writeFileSync)(registryPath, (0, import_yaml8.stringify)(registry), "utf-8");
22061
+ (0, import_node_fs17.writeFileSync)(registryPath, (0, import_yaml9.stringify)(registry), "utf-8");
21879
22062
  }
21880
22063
  function deriveProjectId(dirPath, existingIds) {
21881
- const base = import_node_path51.default.basename(dirPath).toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
22064
+ const base = import_node_path52.default.basename(dirPath).toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
21882
22065
  let candidate = base || "project";
21883
22066
  let suffix = 2;
21884
22067
  while (existingIds.includes(candidate)) {
@@ -21888,11 +22071,11 @@ function deriveProjectId(dirPath, existingIds) {
21888
22071
  return candidate;
21889
22072
  }
21890
22073
  function addProject(projectPath) {
21891
- const absPath = import_node_path51.default.resolve(projectPath);
22074
+ const absPath = import_node_path52.default.resolve(projectPath);
21892
22075
  if (!(0, import_node_fs17.existsSync)(absPath)) {
21893
22076
  throw new Error(`Directory not found: ${absPath}`);
21894
22077
  }
21895
- if (!(0, import_node_fs17.existsSync)(import_node_path51.default.join(absPath, ".agentv"))) {
22078
+ if (!(0, import_node_fs17.existsSync)(import_node_path52.default.join(absPath, ".agentv"))) {
21896
22079
  throw new Error(`No .agentv/ directory found in ${absPath}. Run an evaluation first.`);
21897
22080
  }
21898
22081
  const registry = loadProjectRegistry();
@@ -21906,7 +22089,7 @@ function addProject(projectPath) {
21906
22089
  absPath,
21907
22090
  registry.projects.map((p) => p.id)
21908
22091
  ),
21909
- name: import_node_path51.default.basename(absPath),
22092
+ name: import_node_path52.default.basename(absPath),
21910
22093
  path: absPath,
21911
22094
  addedAt: now,
21912
22095
  lastOpenedAt: now
@@ -21935,14 +22118,14 @@ function touchProject(projectId) {
21935
22118
  }
21936
22119
  }
21937
22120
  function discoverProjects(rootDir, maxDepth = 2) {
21938
- const absRoot = import_node_path51.default.resolve(rootDir);
22121
+ const absRoot = import_node_path52.default.resolve(rootDir);
21939
22122
  if (!(0, import_node_fs17.existsSync)(absRoot) || !(0, import_node_fs17.statSync)(absRoot).isDirectory()) {
21940
22123
  return [];
21941
22124
  }
21942
22125
  const results = [];
21943
22126
  function scan(dir, depth) {
21944
22127
  if (depth > maxDepth) return;
21945
- if ((0, import_node_fs17.existsSync)(import_node_path51.default.join(dir, ".agentv"))) {
22128
+ if ((0, import_node_fs17.existsSync)(import_node_path52.default.join(dir, ".agentv"))) {
21946
22129
  results.push(dir);
21947
22130
  return;
21948
22131
  }
@@ -21952,7 +22135,7 @@ function discoverProjects(rootDir, maxDepth = 2) {
21952
22135
  for (const entry of entries) {
21953
22136
  if (!entry.isDirectory()) continue;
21954
22137
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
21955
- scan(import_node_path51.default.join(dir, entry.name), depth + 1);
22138
+ scan(import_node_path52.default.join(dir, entry.name), depth + 1);
21956
22139
  }
21957
22140
  } catch {
21958
22141
  }
@@ -22878,33 +23061,33 @@ function extractResponseItemContent(content) {
22878
23061
 
22879
23062
  // src/import/codex-session-discovery.ts
22880
23063
  init_cjs_shims();
22881
- var import_promises36 = require("fs/promises");
23064
+ var import_promises37 = require("fs/promises");
22882
23065
  var import_node_os8 = require("os");
22883
- var import_node_path53 = __toESM(require("path"), 1);
22884
- var DEFAULT_SESSIONS_DIR = () => import_node_path53.default.join((0, import_node_os8.homedir)(), ".codex", "sessions");
23066
+ var import_node_path54 = __toESM(require("path"), 1);
23067
+ var DEFAULT_SESSIONS_DIR = () => import_node_path54.default.join((0, import_node_os8.homedir)(), ".codex", "sessions");
22885
23068
  async function discoverCodexSessions(opts) {
22886
23069
  const sessionsDir = opts?.sessionsDir ?? DEFAULT_SESSIONS_DIR();
22887
23070
  const limit = opts?.latest ? 1 : opts?.limit ?? 10;
22888
23071
  const sessions = [];
22889
23072
  let yearDirs;
22890
23073
  try {
22891
- yearDirs = await (0, import_promises36.readdir)(sessionsDir);
23074
+ yearDirs = await (0, import_promises37.readdir)(sessionsDir);
22892
23075
  } catch {
22893
23076
  return [];
22894
23077
  }
22895
23078
  for (const year of yearDirs) {
22896
- const yearPath = import_node_path53.default.join(sessionsDir, year);
23079
+ const yearPath = import_node_path54.default.join(sessionsDir, year);
22897
23080
  let monthDirs;
22898
23081
  try {
22899
- monthDirs = await (0, import_promises36.readdir)(yearPath);
23082
+ monthDirs = await (0, import_promises37.readdir)(yearPath);
22900
23083
  } catch {
22901
23084
  continue;
22902
23085
  }
22903
23086
  for (const month of monthDirs) {
22904
- const monthPath = import_node_path53.default.join(yearPath, month);
23087
+ const monthPath = import_node_path54.default.join(yearPath, month);
22905
23088
  let dayDirs;
22906
23089
  try {
22907
- dayDirs = await (0, import_promises36.readdir)(monthPath);
23090
+ dayDirs = await (0, import_promises37.readdir)(monthPath);
22908
23091
  } catch {
22909
23092
  continue;
22910
23093
  }
@@ -22913,22 +23096,22 @@ async function discoverCodexSessions(opts) {
22913
23096
  const dirDate = `${year}-${month}-${day}`;
22914
23097
  if (dirDate !== opts.date) continue;
22915
23098
  }
22916
- const dayPath = import_node_path53.default.join(monthPath, day);
23099
+ const dayPath = import_node_path54.default.join(monthPath, day);
22917
23100
  let files;
22918
23101
  try {
22919
- files = await (0, import_promises36.readdir)(dayPath);
23102
+ files = await (0, import_promises37.readdir)(dayPath);
22920
23103
  } catch {
22921
23104
  continue;
22922
23105
  }
22923
23106
  for (const file of files) {
22924
23107
  if (!file.startsWith("rollout-") || !file.endsWith(".jsonl")) continue;
22925
- const filePath = import_node_path53.default.join(dayPath, file);
23108
+ const filePath = import_node_path54.default.join(dayPath, file);
22926
23109
  const nameWithoutExt = file.replace(/\.jsonl$/, "");
22927
23110
  const parts = nameWithoutExt.split("-");
22928
23111
  const sessionId = parts.length >= 6 ? parts.slice(-5).join("-") : nameWithoutExt;
22929
23112
  let updatedAt;
22930
23113
  try {
22931
- const fileStat = await (0, import_promises36.stat)(filePath);
23114
+ const fileStat = await (0, import_promises37.stat)(filePath);
22932
23115
  updatedAt = fileStat.mtime;
22933
23116
  } catch {
22934
23117
  updatedAt = /* @__PURE__ */ new Date(0);
@@ -22944,10 +23127,10 @@ async function discoverCodexSessions(opts) {
22944
23127
 
22945
23128
  // src/import/session-discovery.ts
22946
23129
  init_cjs_shims();
22947
- var import_promises37 = require("fs/promises");
23130
+ var import_promises38 = require("fs/promises");
22948
23131
  var import_node_os9 = require("os");
22949
- var import_node_path54 = __toESM(require("path"), 1);
22950
- var DEFAULT_PROJECTS_DIR = () => import_node_path54.default.join((0, import_node_os9.homedir)(), ".claude", "projects");
23132
+ var import_node_path55 = __toESM(require("path"), 1);
23133
+ var DEFAULT_PROJECTS_DIR = () => import_node_path55.default.join((0, import_node_os9.homedir)(), ".claude", "projects");
22951
23134
  function encodeProjectPath(projectPath) {
22952
23135
  return projectPath.replace(/\//g, "-");
22953
23136
  }
@@ -22956,7 +23139,7 @@ async function discoverClaudeSessions(opts) {
22956
23139
  const limit = opts?.latest ? 1 : opts?.limit ?? 10;
22957
23140
  let projectDirs;
22958
23141
  try {
22959
- projectDirs = await (0, import_promises37.readdir)(projectsDir);
23142
+ projectDirs = await (0, import_promises38.readdir)(projectsDir);
22960
23143
  } catch {
22961
23144
  return [];
22962
23145
  }
@@ -22966,10 +23149,10 @@ async function discoverClaudeSessions(opts) {
22966
23149
  }
22967
23150
  const sessions = [];
22968
23151
  for (const projectDir of projectDirs) {
22969
- const dirPath = import_node_path54.default.join(projectsDir, projectDir);
23152
+ const dirPath = import_node_path55.default.join(projectsDir, projectDir);
22970
23153
  let entries;
22971
23154
  try {
22972
- entries = await (0, import_promises37.readdir)(dirPath);
23155
+ entries = await (0, import_promises38.readdir)(dirPath);
22973
23156
  } catch {
22974
23157
  continue;
22975
23158
  }
@@ -22977,10 +23160,10 @@ async function discoverClaudeSessions(opts) {
22977
23160
  if (!entry.endsWith(".jsonl")) continue;
22978
23161
  const sessionId = entry.replace(/\.jsonl$/, "");
22979
23162
  if (opts?.sessionId && sessionId !== opts.sessionId) continue;
22980
- const filePath = import_node_path54.default.join(dirPath, entry);
23163
+ const filePath = import_node_path55.default.join(dirPath, entry);
22981
23164
  let updatedAt;
22982
23165
  try {
22983
- const fileStat = await (0, import_promises37.stat)(filePath);
23166
+ const fileStat = await (0, import_promises38.stat)(filePath);
22984
23167
  updatedAt = fileStat.mtime;
22985
23168
  } catch {
22986
23169
  updatedAt = /* @__PURE__ */ new Date(0);
@@ -23002,7 +23185,7 @@ init_cjs_shims();
23002
23185
 
23003
23186
  // src/import/types.ts
23004
23187
  init_cjs_shims();
23005
- var import_promises38 = require("fs/promises");
23188
+ var import_promises39 = require("fs/promises");
23006
23189
  function toTranscriptJsonLine(entry) {
23007
23190
  const firstUserMessage = entry.messages.find((m) => m.role === "user");
23008
23191
  const input = typeof firstUserMessage?.content === "string" ? firstUserMessage.content : "";
@@ -23028,11 +23211,11 @@ function toTranscriptJsonLine(entry) {
23028
23211
  };
23029
23212
  }
23030
23213
  async function readTranscriptJsonl(filePath) {
23031
- const text = await (0, import_promises38.readFile)(filePath, "utf8");
23214
+ const text = await (0, import_promises39.readFile)(filePath, "utf8");
23032
23215
  return text.split("\n").filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
23033
23216
  }
23034
23217
  async function readTranscriptFile(filePath) {
23035
- return (0, import_promises38.readFile)(filePath, "utf8");
23218
+ return (0, import_promises39.readFile)(filePath, "utf8");
23036
23219
  }
23037
23220
 
23038
23221
  // src/import/transcript-provider.ts
@@ -23247,6 +23430,7 @@ function createAgentKernel() {
23247
23430
  runRegexAssertion,
23248
23431
  runStartsWithAssertion,
23249
23432
  saveProjectRegistry,
23433
+ scanRepoDeps,
23250
23434
  scoreToVerdict,
23251
23435
  shouldEnableCache,
23252
23436
  shouldSkipCacheForTemperature,