agentv 4.4.0 → 4.5.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.
@@ -1638,8 +1638,8 @@ function resolveCliConfig(target, env, evalFilePath) {
1638
1638
  const parseResult = CliTargetInputSchema.safeParse(target, { errorMap: cliErrorMap });
1639
1639
  if (!parseResult.success) {
1640
1640
  const firstError = parseResult.error.errors[0];
1641
- const path48 = firstError?.path.join(".") || "";
1642
- const prefix = path48 ? `${target.name} ${path48}: ` : `${target.name}: `;
1641
+ const path49 = firstError?.path.join(".") || "";
1642
+ const prefix = path49 ? `${target.name} ${path49}: ` : `${target.name}: `;
1643
1643
  throw new Error(`${prefix}${firstError?.message}`);
1644
1644
  }
1645
1645
  const normalized = normalizeCliTargetInput(parseResult.data, env, evalFilePath);
@@ -6722,7 +6722,7 @@ function createOpenRouter(options = {}) {
6722
6722
  );
6723
6723
  const createChatModel = (modelId, settings = {}) => new OpenRouterChatLanguageModel(modelId, settings, {
6724
6724
  provider: "openrouter.chat",
6725
- url: ({ path: path48 }) => `${baseURL}${path48}`,
6725
+ url: ({ path: path49 }) => `${baseURL}${path49}`,
6726
6726
  headers: getHeaders,
6727
6727
  compatibility,
6728
6728
  fetch: options.fetch,
@@ -6730,7 +6730,7 @@ function createOpenRouter(options = {}) {
6730
6730
  });
6731
6731
  const createCompletionModel = (modelId, settings = {}) => new OpenRouterCompletionLanguageModel(modelId, settings, {
6732
6732
  provider: "openrouter.completion",
6733
- url: ({ path: path48 }) => `${baseURL}${path48}`,
6733
+ url: ({ path: path49 }) => `${baseURL}${path49}`,
6734
6734
  headers: getHeaders,
6735
6735
  compatibility,
6736
6736
  fetch: options.fetch,
@@ -6738,14 +6738,14 @@ function createOpenRouter(options = {}) {
6738
6738
  });
6739
6739
  const createEmbeddingModel = (modelId, settings = {}) => new OpenRouterEmbeddingModel(modelId, settings, {
6740
6740
  provider: "openrouter.embedding",
6741
- url: ({ path: path48 }) => `${baseURL}${path48}`,
6741
+ url: ({ path: path49 }) => `${baseURL}${path49}`,
6742
6742
  headers: getHeaders,
6743
6743
  fetch: options.fetch,
6744
6744
  extraBody: options.extraBody
6745
6745
  });
6746
6746
  const createImageModel = (modelId, settings = {}) => new OpenRouterImageModel(modelId, settings, {
6747
6747
  provider: "openrouter.image",
6748
- url: ({ path: path48 }) => `${baseURL}${path48}`,
6748
+ url: ({ path: path49 }) => `${baseURL}${path49}`,
6749
6749
  headers: getHeaders,
6750
6750
  fetch: options.fetch,
6751
6751
  extraBody: options.extraBody
@@ -14253,6 +14253,7 @@ import { homedir } from "node:os";
14253
14253
  import path16 from "node:path";
14254
14254
  import { parse as parseYaml22 } from "yaml";
14255
14255
  import { randomUUID as randomUUID6 } from "node:crypto";
14256
+ import { existsSync as existsSync2 } from "node:fs";
14256
14257
  import { mkdir as mkdir5 } from "node:fs/promises";
14257
14258
  import path18 from "node:path";
14258
14259
  import { spawn as spawn3 } from "node:child_process";
@@ -14324,23 +14325,27 @@ import { cp, mkdir as mkdir12, readdir as readdir4, rm as rm4, stat as stat6 } f
14324
14325
  import path40 from "node:path";
14325
14326
  import { execFile } from "node:child_process";
14326
14327
  import { createHash } from "node:crypto";
14327
- import { existsSync as existsSync2 } from "node:fs";
14328
+ import { existsSync as existsSync3 } from "node:fs";
14328
14329
  import { cp as cp2, mkdir as mkdir13, readFile as readFile12, readdir as readdir5, rm as rm5, unlink, writeFile as writeFile7 } from "node:fs/promises";
14329
14330
  import path41 from "node:path";
14330
14331
  import { promisify as promisify5 } from "node:util";
14331
14332
  import { execFile as execFile2 } from "node:child_process";
14332
- import { existsSync as existsSync3 } from "node:fs";
14333
+ import { existsSync as existsSync4 } from "node:fs";
14333
14334
  import path422 from "node:path";
14334
14335
  import { promisify as promisify6 } from "node:util";
14335
14336
  import { readdir as readdir6, stat as stat7 } from "node:fs/promises";
14336
14337
  import path43 from "node:path";
14337
- import { existsSync as existsSync4 } from "node:fs";
14338
+ import { existsSync as existsSync5 } from "node:fs";
14338
14339
  import path45 from "node:path";
14339
14340
  import { mkdir as mkdir15, readFile as readFile13, writeFile as writeFile8 } from "node:fs/promises";
14340
14341
  import path46 from "node:path";
14341
- import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync2, readdirSync as readdirSync3, statSync as statSync2, writeFileSync } from "node:fs";
14342
+ import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync2, readdirSync as readdirSync3, statSync as statSync2, writeFileSync } from "node:fs";
14342
14343
  import path47 from "node:path";
14343
14344
  import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
14345
+ import { readdir as readdir8, stat as stat9 } from "node:fs/promises";
14346
+ import { homedir as homedir3 } from "node:os";
14347
+ import path48 from "node:path";
14348
+ import { readFile as readFile14 } from "node:fs/promises";
14344
14349
  function computeTraceSummary(messages) {
14345
14350
  const toolCallCounts = {};
14346
14351
  const toolDurations = {};
@@ -21069,6 +21074,7 @@ var CopilotSdkProvider = class {
21069
21074
  const cwd = this.resolveCwd(request.cwd);
21070
21075
  if (cwd) {
21071
21076
  sessionOptions.workingDirectory = cwd;
21077
+ sessionOptions.skillDirectories = resolveSkillDirectories(cwd);
21072
21078
  }
21073
21079
  const systemPrompt = this.config.systemPrompt;
21074
21080
  if (systemPrompt) {
@@ -21300,6 +21306,14 @@ var CopilotSdkProvider = class {
21300
21306
  }
21301
21307
  }
21302
21308
  };
21309
+ function resolveSkillDirectories(cwd) {
21310
+ const candidates = [
21311
+ path18.join(cwd, ".claude", "skills"),
21312
+ path18.join(cwd, ".agents", "skills"),
21313
+ path18.join(cwd, ".codex", "skills")
21314
+ ];
21315
+ return candidates.filter((dir) => existsSync2(dir));
21316
+ }
21303
21317
  function summarizeSdkEvent(eventType, data) {
21304
21318
  if (!data || typeof data !== "object") {
21305
21319
  return eventType;
@@ -22303,6 +22317,11 @@ var PiCodingAgentProvider = class {
22303
22317
  const modelId = this.config.model ?? "gemini-2.5-flash";
22304
22318
  this.setApiKeyEnv(providerName);
22305
22319
  const model = sdk.getModel(providerName, modelId);
22320
+ if (!model) {
22321
+ throw new Error(
22322
+ `pi-coding-agent: getModel('${providerName}', '${modelId}') returned undefined. The model '${modelId}' is not registered for provider '${providerName}' in pi-ai. Check that subprovider and model are correct in your target config.`
22323
+ );
22324
+ }
22306
22325
  const tools = this.resolveTools(sdk);
22307
22326
  const { session } = await sdk.createAgentSession({
22308
22327
  cwd,
@@ -22417,6 +22436,15 @@ ${fileList}`;
22417
22436
  await session.prompt(prompt);
22418
22437
  }
22419
22438
  const agentMessages = session.agent.state.messages;
22439
+ const lastAssistant = [...agentMessages].reverse().find(
22440
+ (m) => !!m && typeof m === "object" && m.role === "assistant"
22441
+ );
22442
+ if (lastAssistant?.stopReason === "error") {
22443
+ const errorMsg = typeof lastAssistant.errorMessage === "string" ? lastAssistant.errorMessage : "unknown SDK error";
22444
+ throw new Error(
22445
+ `pi-coding-agent SDK error (provider: ${lastAssistant.provider ?? providerName}, model: ${lastAssistant.model ?? modelId}): ${errorMsg}`
22446
+ );
22447
+ }
22420
22448
  const output = [];
22421
22449
  for (const msg of agentMessages) {
22422
22450
  output.push(convertAgentMessage(msg, toolTrackers, completedToolResults));
@@ -24371,15 +24399,15 @@ async function execFileWithStdinNode(argv, stdinPayload, options) {
24371
24399
  });
24372
24400
  }
24373
24401
  async function execShellWithStdin(command, stdinPayload, options = {}) {
24374
- const { mkdir: mkdir16, readFile: readFile14, rm: rm6, writeFile: writeFile9 } = await import("node:fs/promises");
24402
+ const { mkdir: mkdir16, readFile: readFile15, rm: rm6, writeFile: writeFile9 } = await import("node:fs/promises");
24375
24403
  const { tmpdir: tmpdir3 } = await import("node:os");
24376
- const path48 = await import("node:path");
24404
+ const path49 = await import("node:path");
24377
24405
  const { randomUUID: randomUUID10 } = await import("node:crypto");
24378
- const dir = path48.join(tmpdir3(), `agentv-exec-${randomUUID10()}`);
24406
+ const dir = path49.join(tmpdir3(), `agentv-exec-${randomUUID10()}`);
24379
24407
  await mkdir16(dir, { recursive: true });
24380
- const stdinPath = path48.join(dir, "stdin.txt");
24381
- const stdoutPath = path48.join(dir, "stdout.txt");
24382
- const stderrPath = path48.join(dir, "stderr.txt");
24408
+ const stdinPath = path49.join(dir, "stdin.txt");
24409
+ const stdoutPath = path49.join(dir, "stdout.txt");
24410
+ const stderrPath = path49.join(dir, "stderr.txt");
24383
24411
  await writeFile9(stdinPath, stdinPayload, "utf8");
24384
24412
  const wrappedCommand = process.platform === "win32" ? `(${command}) < ${shellEscapePath(stdinPath)} > ${shellEscapePath(stdoutPath)} 2> ${shellEscapePath(stderrPath)}` : `(${command}) < ${shellEscapePath(stdinPath)} > ${shellEscapePath(stdoutPath)} 2> ${shellEscapePath(stderrPath)}`;
24385
24413
  const { spawn: spawn5 } = await import("node:child_process");
@@ -24409,8 +24437,8 @@ async function execShellWithStdin(command, stdinPayload, options = {}) {
24409
24437
  resolve2(code ?? 0);
24410
24438
  });
24411
24439
  });
24412
- const stdout = (await readFile14(stdoutPath, "utf8")).replace(/\r\n/g, "\n");
24413
- const stderr = (await readFile14(stderrPath, "utf8")).replace(/\r\n/g, "\n");
24440
+ const stdout = (await readFile15(stdoutPath, "utf8")).replace(/\r\n/g, "\n");
24441
+ const stderr = (await readFile15(stderrPath, "utf8")).replace(/\r\n/g, "\n");
24414
24442
  return { stdout, stderr, exitCode };
24415
24443
  } finally {
24416
24444
  await rm6(dir, { recursive: true, force: true });
@@ -25869,11 +25897,11 @@ function createFilesystemTools(workspacePath) {
25869
25897
  execute: async (input) => {
25870
25898
  try {
25871
25899
  const resolved = resolveSandboxed(workspacePath, input.path);
25872
- const stat9 = await fs2.stat(resolved);
25873
- if (stat9.isDirectory()) {
25900
+ const stat10 = await fs2.stat(resolved);
25901
+ if (stat10.isDirectory()) {
25874
25902
  return { error: `'${input.path}' is a directory, not a file` };
25875
25903
  }
25876
- const buffer = Buffer.alloc(Math.min(stat9.size, MAX_FILE_SIZE));
25904
+ const buffer = Buffer.alloc(Math.min(stat10.size, MAX_FILE_SIZE));
25877
25905
  const fd = await fs2.open(resolved, "r");
25878
25906
  try {
25879
25907
  await fd.read(buffer, 0, buffer.length, 0);
@@ -25881,8 +25909,8 @@ function createFilesystemTools(workspacePath) {
25881
25909
  await fd.close();
25882
25910
  }
25883
25911
  const content = buffer.toString("utf-8");
25884
- const truncated = stat9.size > MAX_FILE_SIZE;
25885
- return { content, truncated, size: stat9.size };
25912
+ const truncated = stat10.size > MAX_FILE_SIZE;
25913
+ return { content, truncated, size: stat10.size };
25886
25914
  } catch (error) {
25887
25915
  return { error: error instanceof Error ? error.message : String(error) };
25888
25916
  }
@@ -25933,8 +25961,8 @@ async function searchDirectory(dirPath, workspacePath, regex, matches) {
25933
25961
  const ext = path35.extname(entry.name).toLowerCase();
25934
25962
  if (BINARY_EXTENSIONS.has(ext)) continue;
25935
25963
  try {
25936
- const stat9 = await fs2.stat(fullPath);
25937
- if (stat9.size > MAX_FILE_SIZE) continue;
25964
+ const stat10 = await fs2.stat(fullPath);
25965
+ if (stat10.size > MAX_FILE_SIZE) continue;
25938
25966
  const content = await fs2.readFile(fullPath, "utf-8");
25939
25967
  const lines = content.split("\n");
25940
25968
  for (let i = 0; i < lines.length; i++) {
@@ -26567,115 +26595,115 @@ var FieldAccuracyEvaluator = class {
26567
26595
  * Evaluate a single field against the expected value.
26568
26596
  */
26569
26597
  evaluateField(fieldConfig, candidateData, expectedData) {
26570
- const { path: path48, match, required = true, weight = 1 } = fieldConfig;
26571
- const candidateValue = resolvePath(candidateData, path48);
26572
- const expectedValue = resolvePath(expectedData, path48);
26598
+ const { path: path49, match, required = true, weight = 1 } = fieldConfig;
26599
+ const candidateValue = resolvePath(candidateData, path49);
26600
+ const expectedValue = resolvePath(expectedData, path49);
26573
26601
  if (expectedValue === void 0) {
26574
26602
  return {
26575
- path: path48,
26603
+ path: path49,
26576
26604
  score: 1,
26577
26605
  // No expected value means no comparison needed
26578
26606
  weight,
26579
26607
  hit: true,
26580
- message: `${path48}: no expected value`
26608
+ message: `${path49}: no expected value`
26581
26609
  };
26582
26610
  }
26583
26611
  if (candidateValue === void 0) {
26584
26612
  if (required) {
26585
26613
  return {
26586
- path: path48,
26614
+ path: path49,
26587
26615
  score: 0,
26588
26616
  weight,
26589
26617
  hit: false,
26590
- message: `${path48} (required, missing)`
26618
+ message: `${path49} (required, missing)`
26591
26619
  };
26592
26620
  }
26593
26621
  return {
26594
- path: path48,
26622
+ path: path49,
26595
26623
  score: 1,
26596
26624
  // Don't penalize missing optional fields
26597
26625
  weight: 0,
26598
26626
  // Zero weight means it won't affect the score
26599
26627
  hit: true,
26600
- message: `${path48}: optional field missing`
26628
+ message: `${path49}: optional field missing`
26601
26629
  };
26602
26630
  }
26603
26631
  switch (match) {
26604
26632
  case "exact":
26605
- return this.compareExact(path48, candidateValue, expectedValue, weight);
26633
+ return this.compareExact(path49, candidateValue, expectedValue, weight);
26606
26634
  case "numeric_tolerance":
26607
26635
  return this.compareNumericTolerance(
26608
- path48,
26636
+ path49,
26609
26637
  candidateValue,
26610
26638
  expectedValue,
26611
26639
  fieldConfig,
26612
26640
  weight
26613
26641
  );
26614
26642
  case "date":
26615
- return this.compareDate(path48, candidateValue, expectedValue, fieldConfig, weight);
26643
+ return this.compareDate(path49, candidateValue, expectedValue, fieldConfig, weight);
26616
26644
  default:
26617
26645
  return {
26618
- path: path48,
26646
+ path: path49,
26619
26647
  score: 0,
26620
26648
  weight,
26621
26649
  hit: false,
26622
- message: `${path48}: unknown match type "${match}"`
26650
+ message: `${path49}: unknown match type "${match}"`
26623
26651
  };
26624
26652
  }
26625
26653
  }
26626
26654
  /**
26627
26655
  * Exact equality comparison.
26628
26656
  */
26629
- compareExact(path48, candidateValue, expectedValue, weight) {
26657
+ compareExact(path49, candidateValue, expectedValue, weight) {
26630
26658
  if (deepEqual(candidateValue, expectedValue)) {
26631
26659
  return {
26632
- path: path48,
26660
+ path: path49,
26633
26661
  score: 1,
26634
26662
  weight,
26635
26663
  hit: true,
26636
- message: path48
26664
+ message: path49
26637
26665
  };
26638
26666
  }
26639
26667
  if (typeof candidateValue !== typeof expectedValue) {
26640
26668
  return {
26641
- path: path48,
26669
+ path: path49,
26642
26670
  score: 0,
26643
26671
  weight,
26644
26672
  hit: false,
26645
- message: `${path48} (type mismatch: got ${typeof candidateValue}, expected ${typeof expectedValue})`
26673
+ message: `${path49} (type mismatch: got ${typeof candidateValue}, expected ${typeof expectedValue})`
26646
26674
  };
26647
26675
  }
26648
26676
  return {
26649
- path: path48,
26677
+ path: path49,
26650
26678
  score: 0,
26651
26679
  weight,
26652
26680
  hit: false,
26653
- message: `${path48} (value mismatch)`
26681
+ message: `${path49} (value mismatch)`
26654
26682
  };
26655
26683
  }
26656
26684
  /**
26657
26685
  * Numeric comparison with absolute or relative tolerance.
26658
26686
  */
26659
- compareNumericTolerance(path48, candidateValue, expectedValue, fieldConfig, weight) {
26687
+ compareNumericTolerance(path49, candidateValue, expectedValue, fieldConfig, weight) {
26660
26688
  const { tolerance = 0, relative = false } = fieldConfig;
26661
26689
  const candidateNum = toNumber(candidateValue);
26662
26690
  const expectedNum = toNumber(expectedValue);
26663
26691
  if (candidateNum === null || expectedNum === null) {
26664
26692
  return {
26665
- path: path48,
26693
+ path: path49,
26666
26694
  score: 0,
26667
26695
  weight,
26668
26696
  hit: false,
26669
- message: `${path48} (non-numeric value)`
26697
+ message: `${path49} (non-numeric value)`
26670
26698
  };
26671
26699
  }
26672
26700
  if (!Number.isFinite(candidateNum) || !Number.isFinite(expectedNum)) {
26673
26701
  return {
26674
- path: path48,
26702
+ path: path49,
26675
26703
  score: 0,
26676
26704
  weight,
26677
26705
  hit: false,
26678
- message: `${path48} (invalid numeric value)`
26706
+ message: `${path49} (invalid numeric value)`
26679
26707
  };
26680
26708
  }
26681
26709
  const diff = Math.abs(candidateNum - expectedNum);
@@ -26688,61 +26716,61 @@ var FieldAccuracyEvaluator = class {
26688
26716
  }
26689
26717
  if (withinTolerance) {
26690
26718
  return {
26691
- path: path48,
26719
+ path: path49,
26692
26720
  score: 1,
26693
26721
  weight,
26694
26722
  hit: true,
26695
- message: `${path48} (within tolerance: diff=${diff.toFixed(2)})`
26723
+ message: `${path49} (within tolerance: diff=${diff.toFixed(2)})`
26696
26724
  };
26697
26725
  }
26698
26726
  return {
26699
- path: path48,
26727
+ path: path49,
26700
26728
  score: 0,
26701
26729
  weight,
26702
26730
  hit: false,
26703
- message: `${path48} (outside tolerance: diff=${diff.toFixed(2)}, tolerance=${tolerance})`
26731
+ message: `${path49} (outside tolerance: diff=${diff.toFixed(2)}, tolerance=${tolerance})`
26704
26732
  };
26705
26733
  }
26706
26734
  /**
26707
26735
  * Date comparison with format normalization.
26708
26736
  */
26709
- compareDate(path48, candidateValue, expectedValue, fieldConfig, weight) {
26737
+ compareDate(path49, candidateValue, expectedValue, fieldConfig, weight) {
26710
26738
  const formats = fieldConfig.formats ?? DEFAULT_DATE_FORMATS;
26711
26739
  const candidateDate = parseDate(String(candidateValue), formats);
26712
26740
  const expectedDate = parseDate(String(expectedValue), formats);
26713
26741
  if (candidateDate === null) {
26714
26742
  return {
26715
- path: path48,
26743
+ path: path49,
26716
26744
  score: 0,
26717
26745
  weight,
26718
26746
  hit: false,
26719
- message: `${path48} (unparseable candidate date)`
26747
+ message: `${path49} (unparseable candidate date)`
26720
26748
  };
26721
26749
  }
26722
26750
  if (expectedDate === null) {
26723
26751
  return {
26724
- path: path48,
26752
+ path: path49,
26725
26753
  score: 0,
26726
26754
  weight,
26727
26755
  hit: false,
26728
- message: `${path48} (unparseable expected date)`
26756
+ message: `${path49} (unparseable expected date)`
26729
26757
  };
26730
26758
  }
26731
26759
  if (candidateDate.getFullYear() === expectedDate.getFullYear() && candidateDate.getMonth() === expectedDate.getMonth() && candidateDate.getDate() === expectedDate.getDate()) {
26732
26760
  return {
26733
- path: path48,
26761
+ path: path49,
26734
26762
  score: 1,
26735
26763
  weight,
26736
26764
  hit: true,
26737
- message: path48
26765
+ message: path49
26738
26766
  };
26739
26767
  }
26740
26768
  return {
26741
- path: path48,
26769
+ path: path49,
26742
26770
  score: 0,
26743
26771
  weight,
26744
26772
  hit: false,
26745
- message: `${path48} (date mismatch: got ${formatDateISO(candidateDate)}, expected ${formatDateISO(expectedDate)})`
26773
+ message: `${path49} (date mismatch: got ${formatDateISO(candidateDate)}, expected ${formatDateISO(expectedDate)})`
26746
26774
  };
26747
26775
  }
26748
26776
  /**
@@ -26775,11 +26803,11 @@ var FieldAccuracyEvaluator = class {
26775
26803
  };
26776
26804
  }
26777
26805
  };
26778
- function resolvePath(obj, path48) {
26779
- if (!path48 || !obj) {
26806
+ function resolvePath(obj, path49) {
26807
+ if (!path49 || !obj) {
26780
26808
  return void 0;
26781
26809
  }
26782
- const parts = path48.split(/\.|\[|\]/).filter((p) => p.length > 0);
26810
+ const parts = path49.split(/\.|\[|\]/).filter((p) => p.length > 0);
26783
26811
  let current = obj;
26784
26812
  for (const part of parts) {
26785
26813
  if (current === null || current === void 0) {
@@ -26999,6 +27027,14 @@ var SkillTriggerEvaluator = class {
26999
27027
  evidence = `Read tool loaded skill file via tool name "${toolName}"`;
27000
27028
  break;
27001
27029
  }
27030
+ if (!triggered && toolCall.output != null) {
27031
+ const outputStr = typeof toolCall.output === "string" ? toolCall.output : JSON.stringify(toolCall.output);
27032
+ if (outputStr.includes(`skills/${skillName}/`)) {
27033
+ triggered = true;
27034
+ evidence = `Tool "${toolName}" output referenced skill file for "${skillName}"`;
27035
+ break;
27036
+ }
27037
+ }
27002
27038
  }
27003
27039
  const pass = triggered === shouldTrigger;
27004
27040
  if (pass) {
@@ -27253,8 +27289,8 @@ var TokenUsageEvaluator = class {
27253
27289
  };
27254
27290
  }
27255
27291
  };
27256
- function getNestedValue(obj, path48) {
27257
- const parts = path48.split(".");
27292
+ function getNestedValue(obj, path49) {
27293
+ const parts = path49.split(".");
27258
27294
  let current = obj;
27259
27295
  for (const part of parts) {
27260
27296
  if (current === null || current === void 0 || typeof current !== "object") {
@@ -28846,7 +28882,7 @@ var WorkspacePoolManager = class {
28846
28882
  if (!locked) {
28847
28883
  continue;
28848
28884
  }
28849
- const slotExists = existsSync2(slotPath);
28885
+ const slotExists = existsSync3(slotPath);
28850
28886
  if (slotExists) {
28851
28887
  await this.resetSlot(slotPath, templatePath, repos, poolReset);
28852
28888
  return {
@@ -28952,7 +28988,7 @@ var WorkspacePoolManager = class {
28952
28988
  for (const entry of entries) {
28953
28989
  if (entry.startsWith("slot-") && !entry.endsWith(".lock")) {
28954
28990
  const lockPath = path41.join(poolDir, `${entry}.lock`);
28955
- if (existsSync2(lockPath)) {
28991
+ if (existsSync3(lockPath)) {
28956
28992
  try {
28957
28993
  const pidStr = await readFile12(lockPath, "utf-8");
28958
28994
  const pid = Number.parseInt(pidStr.trim(), 10);
@@ -28983,7 +29019,7 @@ var WorkspacePoolManager = class {
28983
29019
  async resetSlot(slotPath, templatePath, repos, poolReset = "fast") {
28984
29020
  for (const repo of repos) {
28985
29021
  const repoDir = path41.join(slotPath, repo.path);
28986
- if (!existsSync2(repoDir)) {
29022
+ if (!existsSync3(repoDir)) {
28987
29023
  continue;
28988
29024
  }
28989
29025
  if (poolReset === "none") {
@@ -29054,7 +29090,7 @@ var RepoManager = class {
29054
29090
  resolvedSourcePath: sourcePath ?? "",
29055
29091
  reason: "empty_path"
29056
29092
  });
29057
- } else if (!existsSync3(sourcePath)) {
29093
+ } else if (!existsSync4(sourcePath)) {
29058
29094
  errors.push({
29059
29095
  repoPath: repo.path,
29060
29096
  resolvedSourcePath: sourcePath,
@@ -29273,8 +29309,8 @@ async function executeWorkspaceScript(config, context2, failureMode = "fatal") {
29273
29309
  }
29274
29310
  return result.stdout;
29275
29311
  }
29276
- function classifyQualityStatus(score) {
29277
- return score >= PASS_THRESHOLD ? "ok" : "quality_failure";
29312
+ function classifyQualityStatus(score, threshold = PASS_THRESHOLD) {
29313
+ return score >= threshold ? "ok" : "quality_failure";
29278
29314
  }
29279
29315
  function buildSkippedEvaluatorError(scores) {
29280
29316
  const skippedScores = scores?.filter((score) => score.verdict === "skip") ?? [];
@@ -29350,7 +29386,8 @@ async function runEvaluation(options) {
29350
29386
  retainOnSuccess,
29351
29387
  retainOnFailure,
29352
29388
  graderTarget: cliGraderTarget,
29353
- model: cliModel
29389
+ model: cliModel,
29390
+ threshold: scoreThreshold
29354
29391
  } = options;
29355
29392
  let useCache = options.useCache;
29356
29393
  if (trials && trials.count > 1 && useCache) {
@@ -29479,7 +29516,8 @@ async function runEvaluation(options) {
29479
29516
  resolveGraderProvider,
29480
29517
  agentTimeoutMs,
29481
29518
  targetResolver,
29482
- availableTargets
29519
+ availableTargets,
29520
+ threshold: scoreThreshold
29483
29521
  });
29484
29522
  } catch (error) {
29485
29523
  if (verbose) {
@@ -29848,7 +29886,8 @@ async function runEvaluation(options) {
29848
29886
  typeRegistry,
29849
29887
  repoManager,
29850
29888
  evalDir,
29851
- verbose
29889
+ verbose,
29890
+ threshold: scoreThreshold
29852
29891
  };
29853
29892
  let result = trials && trials.count > 1 ? await runEvalCaseWithTrials(runCaseOptions, trials) : await runEvalCase(runCaseOptions);
29854
29893
  if (totalBudgetUsd !== void 0) {
@@ -30006,7 +30045,8 @@ async function runBatchEvaluation(options) {
30006
30045
  resolveGraderProvider,
30007
30046
  agentTimeoutMs,
30008
30047
  targetResolver,
30009
- availableTargets
30048
+ availableTargets,
30049
+ threshold: batchThreshold
30010
30050
  } = options;
30011
30051
  const promptInputsList = [];
30012
30052
  const formattingMode = usesFileReferencePrompt(provider) ? "agent" : "lm";
@@ -30091,7 +30131,8 @@ async function runBatchEvaluation(options) {
30091
30131
  endTime,
30092
30132
  targetResolver,
30093
30133
  availableTargets,
30094
- verbose
30134
+ verbose,
30135
+ threshold: batchThreshold
30095
30136
  });
30096
30137
  if (providerError) {
30097
30138
  result = {
@@ -30177,7 +30218,8 @@ async function runEvalCase(options) {
30177
30218
  typeRegistry: providedTypeRegistry,
30178
30219
  repoManager,
30179
30220
  evalDir,
30180
- verbose
30221
+ verbose,
30222
+ threshold: caseThreshold
30181
30223
  } = options;
30182
30224
  const setupDebug = process.env.AGENTV_SETUP_DEBUG === "1";
30183
30225
  const formattingMode = usesFileReferencePrompt(provider) ? "agent" : "lm";
@@ -30540,7 +30582,8 @@ async function runEvalCase(options) {
30540
30582
  availableTargets,
30541
30583
  fileChanges,
30542
30584
  workspacePath,
30543
- verbose
30585
+ verbose,
30586
+ threshold: caseThreshold
30544
30587
  });
30545
30588
  const totalDurationMs = Date.now() - caseStartMs;
30546
30589
  const graderTokens = aggregateEvaluatorTokenUsage(result.scores);
@@ -30555,7 +30598,7 @@ async function runEvalCase(options) {
30555
30598
  ...evalRunTokenUsage ? { tokenUsage: evalRunTokenUsage } : {}
30556
30599
  };
30557
30600
  const skippedEvaluatorError = buildSkippedEvaluatorError(result.scores);
30558
- const executionStatus = providerError || skippedEvaluatorError ? "execution_error" : classifyQualityStatus(result.score);
30601
+ const executionStatus = providerError || skippedEvaluatorError ? "execution_error" : classifyQualityStatus(result.score, caseThreshold);
30559
30602
  const finalResult = providerError ? {
30560
30603
  ...result,
30561
30604
  evalRun,
@@ -30726,7 +30769,8 @@ async function evaluateCandidate(options) {
30726
30769
  targetResolver,
30727
30770
  availableTargets,
30728
30771
  fileChanges,
30729
- workspacePath
30772
+ workspacePath,
30773
+ threshold: evalThreshold
30730
30774
  } = options;
30731
30775
  const gradeTimestamp = nowFn();
30732
30776
  const { score, scores } = await runEvaluatorsForCase({
@@ -30799,7 +30843,7 @@ async function evaluateCandidate(options) {
30799
30843
  scores,
30800
30844
  trace: trace2,
30801
30845
  fileChanges,
30802
- executionStatus: classifyQualityStatus(score.score)
30846
+ executionStatus: classifyQualityStatus(score.score, evalThreshold)
30803
30847
  };
30804
30848
  }
30805
30849
  async function runEvaluatorsForCase(options) {
@@ -31412,7 +31456,7 @@ async function discoverDefaultTarget(repoRoot) {
31412
31456
  for (const dir of chain) {
31413
31457
  for (const candidate of TARGET_FILE_CANDIDATES) {
31414
31458
  const targetsPath = path45.join(dir, candidate);
31415
- if (!existsSync4(targetsPath)) continue;
31459
+ if (!existsSync5(targetsPath)) continue;
31416
31460
  try {
31417
31461
  const definitions = await readTargetDefinitions(targetsPath);
31418
31462
  const defaultTarget = definitions.find((d) => d.name === "default");
@@ -31429,7 +31473,7 @@ async function loadEnvHierarchy(repoRoot, startPath) {
31429
31473
  const envFiles = [];
31430
31474
  for (const dir of chain) {
31431
31475
  const envPath = path45.join(dir, ".env");
31432
- if (existsSync4(envPath)) envFiles.push(envPath);
31476
+ if (existsSync5(envPath)) envFiles.push(envPath);
31433
31477
  }
31434
31478
  for (let i = 0; i < envFiles.length; i++) {
31435
31479
  try {
@@ -31502,12 +31546,12 @@ var CONFIG_FILE_NAMES = [
31502
31546
  ".agentv/config.js"
31503
31547
  ];
31504
31548
  async function loadTsConfig(projectRoot) {
31505
- const { existsSync: existsSync6 } = await import("node:fs");
31549
+ const { existsSync: existsSync7 } = await import("node:fs");
31506
31550
  const { pathToFileURL } = await import("node:url");
31507
31551
  const { join: join2 } = await import("node:path");
31508
31552
  for (const fileName of CONFIG_FILE_NAMES) {
31509
31553
  const filePath = join2(projectRoot, fileName);
31510
- if (!existsSync6(filePath)) {
31554
+ if (!existsSync7(filePath)) {
31511
31555
  continue;
31512
31556
  }
31513
31557
  try {
@@ -31640,7 +31684,7 @@ function getProjectsRegistryPath() {
31640
31684
  }
31641
31685
  function loadProjectRegistry() {
31642
31686
  const registryPath = getProjectsRegistryPath();
31643
- if (!existsSync5(registryPath)) {
31687
+ if (!existsSync6(registryPath)) {
31644
31688
  return { projects: [] };
31645
31689
  }
31646
31690
  try {
@@ -31657,7 +31701,7 @@ function loadProjectRegistry() {
31657
31701
  function saveProjectRegistry(registry) {
31658
31702
  const registryPath = getProjectsRegistryPath();
31659
31703
  const dir = path47.dirname(registryPath);
31660
- if (!existsSync5(dir)) {
31704
+ if (!existsSync6(dir)) {
31661
31705
  mkdirSync(dir, { recursive: true });
31662
31706
  }
31663
31707
  writeFileSync(registryPath, stringifyYaml(registry), "utf-8");
@@ -31674,10 +31718,10 @@ function deriveProjectId(dirPath, existingIds) {
31674
31718
  }
31675
31719
  function addProject(projectPath) {
31676
31720
  const absPath = path47.resolve(projectPath);
31677
- if (!existsSync5(absPath)) {
31721
+ if (!existsSync6(absPath)) {
31678
31722
  throw new Error(`Directory not found: ${absPath}`);
31679
31723
  }
31680
- if (!existsSync5(path47.join(absPath, ".agentv"))) {
31724
+ if (!existsSync6(path47.join(absPath, ".agentv"))) {
31681
31725
  throw new Error(`No .agentv/ directory found in ${absPath}. Run an evaluation first.`);
31682
31726
  }
31683
31727
  const registry = loadProjectRegistry();
@@ -31721,13 +31765,13 @@ function touchProject(projectId) {
31721
31765
  }
31722
31766
  function discoverProjects(rootDir, maxDepth = 2) {
31723
31767
  const absRoot = path47.resolve(rootDir);
31724
- if (!existsSync5(absRoot) || !statSync2(absRoot).isDirectory()) {
31768
+ if (!existsSync6(absRoot) || !statSync2(absRoot).isDirectory()) {
31725
31769
  return [];
31726
31770
  }
31727
31771
  const results = [];
31728
31772
  function scan(dir, depth) {
31729
31773
  if (depth > maxDepth) return;
31730
- if (existsSync5(path47.join(dir, ".agentv"))) {
31774
+ if (existsSync6(path47.join(dir, ".agentv"))) {
31731
31775
  results.push(dir);
31732
31776
  return;
31733
31777
  }
@@ -32293,6 +32337,238 @@ function toHrTime(iso) {
32293
32337
  if (!iso) return void 0;
32294
32338
  return new Date(iso).getTime();
32295
32339
  }
32340
+ var SKIPPED_TYPES = /* @__PURE__ */ new Set(["progress", "system", "file-history-snapshot"]);
32341
+ function parseClaudeSession(jsonl) {
32342
+ const messages = [];
32343
+ let sessionId = "";
32344
+ let projectPath;
32345
+ let model;
32346
+ let startTimestamp;
32347
+ let endTimestamp;
32348
+ const usageByRequestId = /* @__PURE__ */ new Map();
32349
+ let lastAssistantRequestId;
32350
+ let lastAssistantIdx = -1;
32351
+ const pendingToolCalls = /* @__PURE__ */ new Map();
32352
+ const lines = jsonl.split("\n").filter((l) => l.trim().length > 0);
32353
+ for (const line of lines) {
32354
+ let event;
32355
+ try {
32356
+ event = JSON.parse(line);
32357
+ } catch {
32358
+ continue;
32359
+ }
32360
+ if (!event.type) continue;
32361
+ if (event.timestamp) {
32362
+ if (!startTimestamp) startTimestamp = event.timestamp;
32363
+ endTimestamp = event.timestamp;
32364
+ }
32365
+ if (SKIPPED_TYPES.has(event.type)) continue;
32366
+ if (event.isSidechain) continue;
32367
+ if (!sessionId && event.sessionId) {
32368
+ sessionId = event.sessionId;
32369
+ }
32370
+ if (!projectPath && event.cwd) {
32371
+ projectPath = event.cwd;
32372
+ }
32373
+ switch (event.type) {
32374
+ case "user": {
32375
+ const msg = event.message;
32376
+ if (!msg) break;
32377
+ const contentArr = msg.content;
32378
+ if (Array.isArray(contentArr)) {
32379
+ for (const block of contentArr) {
32380
+ if (block.type === "tool_result" && block.tool_use_id) {
32381
+ const pending = pendingToolCalls.get(block.tool_use_id);
32382
+ if (pending) {
32383
+ const existingMsg = messages[pending.msgIdx];
32384
+ const existingCalls = [...existingMsg.toolCalls ?? []];
32385
+ existingCalls[pending.toolIdx] = {
32386
+ ...existingCalls[pending.toolIdx],
32387
+ output: extractToolResultContent(block.content)
32388
+ };
32389
+ messages[pending.msgIdx] = { ...existingMsg, toolCalls: existingCalls };
32390
+ pendingToolCalls.delete(block.tool_use_id);
32391
+ }
32392
+ }
32393
+ }
32394
+ }
32395
+ const text2 = extractTextContent22(contentArr);
32396
+ if (text2 !== void 0) {
32397
+ messages.push({ role: "user", content: text2 });
32398
+ }
32399
+ break;
32400
+ }
32401
+ case "assistant": {
32402
+ const msg = event.message;
32403
+ if (!msg) break;
32404
+ if (!model && msg.model) {
32405
+ model = msg.model;
32406
+ }
32407
+ if (msg.usage && event.requestId) {
32408
+ usageByRequestId.set(event.requestId, msg.usage);
32409
+ }
32410
+ const { text: text2, toolCalls } = extractAssistantContent(msg.content);
32411
+ if (event.requestId && event.requestId === lastAssistantRequestId && lastAssistantIdx >= 0) {
32412
+ messages[lastAssistantIdx] = {
32413
+ role: "assistant",
32414
+ content: text2 || void 0,
32415
+ toolCalls: toolCalls.length > 0 ? toolCalls : void 0
32416
+ };
32417
+ registerPendingToolCalls(toolCalls, lastAssistantIdx, pendingToolCalls);
32418
+ } else {
32419
+ if (text2 || toolCalls.length > 0) {
32420
+ lastAssistantIdx = messages.length;
32421
+ messages.push({
32422
+ role: "assistant",
32423
+ content: text2 || void 0,
32424
+ toolCalls: toolCalls.length > 0 ? toolCalls : void 0
32425
+ });
32426
+ registerPendingToolCalls(toolCalls, lastAssistantIdx, pendingToolCalls);
32427
+ }
32428
+ }
32429
+ lastAssistantRequestId = event.requestId;
32430
+ break;
32431
+ }
32432
+ }
32433
+ }
32434
+ let totalInputTokens = 0;
32435
+ let totalOutputTokens = 0;
32436
+ for (const usage of usageByRequestId.values()) {
32437
+ totalInputTokens += Number(usage.input_tokens ?? 0);
32438
+ totalOutputTokens += Number(usage.output_tokens ?? 0);
32439
+ }
32440
+ const hasUsage = usageByRequestId.size > 0;
32441
+ let durationMs;
32442
+ if (startTimestamp && endTimestamp) {
32443
+ durationMs = new Date(endTimestamp).getTime() - new Date(startTimestamp).getTime();
32444
+ }
32445
+ const source = {
32446
+ provider: "claude",
32447
+ sessionId,
32448
+ projectPath,
32449
+ startedAt: startTimestamp,
32450
+ model
32451
+ };
32452
+ return {
32453
+ messages,
32454
+ source,
32455
+ tokenUsage: hasUsage ? { input: totalInputTokens, output: totalOutputTokens } : void 0,
32456
+ durationMs,
32457
+ costUsd: null
32458
+ };
32459
+ }
32460
+ function registerPendingToolCalls(toolCalls, msgIdx, pending) {
32461
+ for (let i = 0; i < toolCalls.length; i++) {
32462
+ const id = toolCalls[i].id;
32463
+ if (id) {
32464
+ pending.set(id, { msgIdx, toolIdx: i });
32465
+ }
32466
+ }
32467
+ }
32468
+ function extractTextContent22(content) {
32469
+ if (content === void 0 || content === null) return void 0;
32470
+ if (typeof content === "string") return content;
32471
+ const textParts = [];
32472
+ for (const block of content) {
32473
+ if (block.type === "text" && block.text) {
32474
+ textParts.push(block.text);
32475
+ }
32476
+ }
32477
+ return textParts.length > 0 ? textParts.join("") : void 0;
32478
+ }
32479
+ function extractAssistantContent(content) {
32480
+ if (content === void 0 || content === null) {
32481
+ return { text: void 0, toolCalls: [] };
32482
+ }
32483
+ if (typeof content === "string") {
32484
+ return { text: content, toolCalls: [] };
32485
+ }
32486
+ const textParts = [];
32487
+ const toolCalls = [];
32488
+ for (const block of content) {
32489
+ switch (block.type) {
32490
+ case "text":
32491
+ if (block.text) textParts.push(block.text);
32492
+ break;
32493
+ case "tool_use":
32494
+ if (block.name) {
32495
+ toolCalls.push({
32496
+ tool: block.name,
32497
+ input: block.input,
32498
+ id: block.id
32499
+ });
32500
+ }
32501
+ break;
32502
+ }
32503
+ }
32504
+ return {
32505
+ text: textParts.length > 0 ? textParts.join("") : void 0,
32506
+ toolCalls
32507
+ };
32508
+ }
32509
+ function extractToolResultContent(content) {
32510
+ if (content === void 0 || content === null) return void 0;
32511
+ if (typeof content === "string") return content;
32512
+ const parts = [];
32513
+ for (const block of content) {
32514
+ if (block.type === "text" && block.text) {
32515
+ parts.push(block.text);
32516
+ }
32517
+ }
32518
+ return parts.length > 0 ? parts.join("") : void 0;
32519
+ }
32520
+ var DEFAULT_PROJECTS_DIR = () => path48.join(homedir3(), ".claude", "projects");
32521
+ function encodeProjectPath(projectPath) {
32522
+ return projectPath.replace(/\//g, "-");
32523
+ }
32524
+ async function discoverClaudeSessions(opts) {
32525
+ const projectsDir = opts?.projectsDir ?? DEFAULT_PROJECTS_DIR();
32526
+ const limit = opts?.latest ? 1 : opts?.limit ?? 10;
32527
+ let projectDirs;
32528
+ try {
32529
+ projectDirs = await readdir8(projectsDir);
32530
+ } catch {
32531
+ return [];
32532
+ }
32533
+ if (opts?.projectPath) {
32534
+ const encoded = encodeProjectPath(opts.projectPath);
32535
+ projectDirs = projectDirs.filter((dir) => dir === encoded || dir.includes(encoded));
32536
+ }
32537
+ const sessions = [];
32538
+ for (const projectDir of projectDirs) {
32539
+ const dirPath = path48.join(projectsDir, projectDir);
32540
+ let entries;
32541
+ try {
32542
+ entries = await readdir8(dirPath);
32543
+ } catch {
32544
+ continue;
32545
+ }
32546
+ for (const entry of entries) {
32547
+ if (!entry.endsWith(".jsonl")) continue;
32548
+ const sessionId = entry.replace(/\.jsonl$/, "");
32549
+ if (opts?.sessionId && sessionId !== opts.sessionId) continue;
32550
+ const filePath = path48.join(dirPath, entry);
32551
+ let updatedAt;
32552
+ try {
32553
+ const fileStat = await stat9(filePath);
32554
+ updatedAt = fileStat.mtime;
32555
+ } catch {
32556
+ updatedAt = /* @__PURE__ */ new Date(0);
32557
+ }
32558
+ sessions.push({
32559
+ sessionId,
32560
+ filePath,
32561
+ projectDir,
32562
+ updatedAt
32563
+ });
32564
+ }
32565
+ }
32566
+ sessions.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
32567
+ return sessions.slice(0, limit);
32568
+ }
32569
+ async function readTranscriptFile(filePath) {
32570
+ return readFile14(filePath, "utf8");
32571
+ }
32296
32572
  function createAgentKernel() {
32297
32573
  return { status: "stub" };
32298
32574
  }
@@ -32463,6 +32739,9 @@ export {
32463
32739
  OTEL_BACKEND_PRESETS,
32464
32740
  OtelTraceExporter,
32465
32741
  OtelStreamingObserver,
32742
+ parseClaudeSession,
32743
+ discoverClaudeSessions,
32744
+ readTranscriptFile,
32466
32745
  createAgentKernel
32467
32746
  };
32468
- //# sourceMappingURL=chunk-63NDZ6UC.js.map
32747
+ //# sourceMappingURL=chunk-TEPYEYPG.js.map