agentv 4.5.2 → 4.6.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.
@@ -301,7 +301,7 @@ var require_dist = __commonJS({
301
301
  }
302
302
  });
303
303
 
304
- // ../../packages/core/dist/chunk-M65PVDQ5.js
304
+ // ../../packages/core/dist/chunk-ZK4GG7PR.js
305
305
  import { constants } from "node:fs";
306
306
  import { access, readFile } from "node:fs/promises";
307
307
  import path from "node:path";
@@ -419,7 +419,7 @@ __export(external_exports2, {
419
419
  void: () => voidType
420
420
  });
421
421
 
422
- // ../../packages/core/dist/chunk-M65PVDQ5.js
422
+ // ../../packages/core/dist/chunk-ZK4GG7PR.js
423
423
  import { readFile as readFile2 } from "node:fs/promises";
424
424
  import path3 from "node:path";
425
425
  import fg from "fast-glob";
@@ -798,21 +798,28 @@ var CLI_PLACEHOLDERS = /* @__PURE__ */ new Set([
798
798
  "OUTPUT_FILE"
799
799
  ]);
800
800
  var COMMON_TARGET_SETTINGS = [
801
+ "use_target",
801
802
  "provider_batching",
802
803
  "providerBatching",
803
804
  "subagent_mode_allowed",
804
- "subagentModeAllowed"
805
+ "subagentModeAllowed",
806
+ "fallback_targets",
807
+ "fallbackTargets"
805
808
  ];
809
+ var USE_TARGET_ENV_PATTERN = /^\$\{\{\s*([A-Z0-9_]+)\s*\}\}$/i;
806
810
  var BASE_TARGET_SCHEMA = external_exports2.object({
807
811
  name: external_exports2.string().min(1, "target name is required"),
808
- provider: external_exports2.string().min(1, "provider is required"),
812
+ provider: external_exports2.string().optional(),
813
+ use_target: external_exports2.string().optional(),
809
814
  grader_target: external_exports2.string().optional(),
810
815
  judge_target: external_exports2.string().optional(),
811
816
  // backward compat
812
817
  workers: external_exports2.number().int().min(1).optional(),
813
818
  workspace_template: external_exports2.string().optional(),
814
819
  workspaceTemplate: external_exports2.string().optional(),
815
- subagent_mode_allowed: external_exports2.boolean().optional()
820
+ subagent_mode_allowed: external_exports2.boolean().optional(),
821
+ fallback_targets: external_exports2.array(external_exports2.string().min(1)).optional(),
822
+ fallbackTargets: external_exports2.array(external_exports2.string().min(1)).optional()
816
823
  }).passthrough();
817
824
  var DEFAULT_AZURE_API_VERSION = "2024-12-01-preview";
818
825
  var DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
@@ -859,6 +866,52 @@ function resolveRetryConfig(target) {
859
866
  retryableStatusCodes
860
867
  };
861
868
  }
869
+ function resolveDelegatedTargetDefinition(name21, definitions, env = process.env) {
870
+ let definition = definitions.get(name21);
871
+ if (!definition) {
872
+ return void 0;
873
+ }
874
+ const visited = [definition.name];
875
+ for (let depth = 0; depth < 10; depth++) {
876
+ const rawUseTarget = typeof definition.use_target === "string" ? definition.use_target.trim() : void 0;
877
+ if (!rawUseTarget) {
878
+ return definition;
879
+ }
880
+ const envMatch = rawUseTarget.match(USE_TARGET_ENV_PATTERN);
881
+ const envVarName = envMatch?.[1];
882
+ const resolvedName = envVarName ? env[envVarName]?.trim() ?? "" : rawUseTarget;
883
+ if (resolvedName.length === 0) {
884
+ if (envVarName) {
885
+ throw new Error(
886
+ `Target "${definition.name}" uses use_target: \${{ ${envVarName} }}, but ${envVarName} is not set. Set ${envVarName} to the name of a concrete target (for example, "azure") before running the eval.`
887
+ );
888
+ }
889
+ throw new Error(
890
+ `Target "${definition.name}" has an empty use_target value. Point it at a concrete target name before running the eval.`
891
+ );
892
+ }
893
+ const next = definitions.get(resolvedName);
894
+ if (!next) {
895
+ if (envVarName) {
896
+ throw new Error(
897
+ `Target "${definition.name}" uses use_target: \${{ ${envVarName} }}, which resolved to "${resolvedName}", but no target named "${resolvedName}" exists.`
898
+ );
899
+ }
900
+ throw new Error(
901
+ `Target "${definition.name}" uses use_target: "${resolvedName}", but no target named "${resolvedName}" exists.`
902
+ );
903
+ }
904
+ if (visited.includes(next.name)) {
905
+ const chain = [...visited, next.name].join(" -> ");
906
+ throw new Error(`Circular use_target reference detected: ${chain}`);
907
+ }
908
+ definition = next;
909
+ visited.push(definition.name);
910
+ }
911
+ throw new Error(
912
+ `Target "${name21}" exceeded the maximum use_target resolution depth (10). Check for a delegation loop or overly deep alias chain.`
913
+ );
914
+ }
862
915
  function resolveTargetDefinition(definition, env = process.env, evalFilePath) {
863
916
  const parsed = BASE_TARGET_SCHEMA.parse(definition);
864
917
  if (parsed.workspace_template !== void 0 || parsed.workspaceTemplate !== void 0) {
@@ -866,6 +919,11 @@ function resolveTargetDefinition(definition, env = process.env, evalFilePath) {
866
919
  `${parsed.name}: target-level workspace_template has been removed. Use eval-level workspace.template.`
867
920
  );
868
921
  }
922
+ if (!parsed.provider) {
923
+ throw new Error(
924
+ `${parsed.name}: 'provider' is required (targets with use_target must be resolved before calling resolveTargetDefinition)`
925
+ );
926
+ }
869
927
  const provider = resolveString(
870
928
  parsed.provider,
871
929
  env,
@@ -878,12 +936,14 @@ function resolveTargetDefinition(definition, env = process.env, evalFilePath) {
878
936
  const subagentModeAllowed = resolveOptionalBoolean(
879
937
  parsed.subagent_mode_allowed ?? parsed.subagentModeAllowed
880
938
  );
939
+ const fallbackTargets = parsed.fallback_targets ?? parsed.fallbackTargets;
881
940
  const base = {
882
941
  name: parsed.name,
883
942
  graderTarget: parsed.grader_target ?? parsed.judge_target,
884
943
  workers: parsed.workers,
885
944
  providerBatching,
886
- subagentModeAllowed
945
+ subagentModeAllowed,
946
+ ...fallbackTargets ? { fallbackTargets } : {}
887
947
  };
888
948
  switch (provider) {
889
949
  case "openai":
@@ -1057,6 +1117,14 @@ function resolveAzureConfig(target, env) {
1057
1117
  retry
1058
1118
  };
1059
1119
  }
1120
+ function resolveApiFormat(target, targetName) {
1121
+ const raw = target.api_format ?? target.apiFormat;
1122
+ if (raw === void 0) return void 0;
1123
+ if (raw === "chat" || raw === "responses") return raw;
1124
+ throw new Error(
1125
+ `Invalid api_format '${raw}' for target '${targetName}'. Must be 'chat' or 'responses'.`
1126
+ );
1127
+ }
1060
1128
  function resolveOpenAIConfig(target, env) {
1061
1129
  const endpointSource = target.endpoint ?? target.base_url ?? target.baseUrl;
1062
1130
  const apiKeySource = target.api_key ?? target.apiKey;
@@ -1076,6 +1144,7 @@ function resolveOpenAIConfig(target, env) {
1076
1144
  baseURL,
1077
1145
  apiKey,
1078
1146
  model,
1147
+ apiFormat: resolveApiFormat(target, target.name),
1079
1148
  temperature: resolveOptionalNumber(temperatureSource, `${target.name} temperature`),
1080
1149
  maxOutputTokens: resolveOptionalNumber(maxTokensSource, `${target.name} max output tokens`),
1081
1150
  retry
@@ -1382,6 +1451,11 @@ function resolvePiCodingAgentConfig(target, env, evalFilePath) {
1382
1451
  allowLiteral: false,
1383
1452
  optionalEnv: true
1384
1453
  });
1454
+ const baseUrlSource = target.base_url ?? target.baseUrl ?? target.endpoint;
1455
+ const baseUrl = resolveOptionalString(baseUrlSource, env, `${target.name} pi base url`, {
1456
+ allowLiteral: true,
1457
+ optionalEnv: true
1458
+ });
1385
1459
  const tools = resolveOptionalString(toolsSource, env, `${target.name} pi tools`, {
1386
1460
  allowLiteral: true,
1387
1461
  optionalEnv: true
@@ -1422,6 +1496,7 @@ function resolvePiCodingAgentConfig(target, env, evalFilePath) {
1422
1496
  subprovider,
1423
1497
  model,
1424
1498
  apiKey,
1499
+ baseUrl,
1425
1500
  tools,
1426
1501
  thinking,
1427
1502
  cwd,
@@ -1463,6 +1538,11 @@ function resolvePiCliConfig(target, env, evalFilePath) {
1463
1538
  allowLiteral: false,
1464
1539
  optionalEnv: true
1465
1540
  });
1541
+ const baseUrlSource = target.base_url ?? target.baseUrl ?? target.endpoint;
1542
+ const baseUrl = resolveOptionalString(baseUrlSource, env, `${target.name} pi-cli base url`, {
1543
+ allowLiteral: true,
1544
+ optionalEnv: true
1545
+ });
1466
1546
  const tools = resolveOptionalString(toolsSource, env, `${target.name} pi-cli tools`, {
1467
1547
  allowLiteral: true,
1468
1548
  optionalEnv: true
@@ -1501,6 +1581,7 @@ function resolvePiCliConfig(target, env, evalFilePath) {
1501
1581
  subprovider,
1502
1582
  model,
1503
1583
  apiKey,
1584
+ baseUrl,
1504
1585
  tools,
1505
1586
  thinking,
1506
1587
  args,
@@ -14256,15 +14337,15 @@ import { randomUUID as randomUUID6 } from "node:crypto";
14256
14337
  import { existsSync as existsSync2 } from "node:fs";
14257
14338
  import { mkdir as mkdir5 } from "node:fs/promises";
14258
14339
  import path18 from "node:path";
14259
- import { spawn as spawn3 } from "node:child_process";
14340
+ import { execSync, spawn as spawn3 } from "node:child_process";
14260
14341
  import { randomUUID as randomUUID7 } from "node:crypto";
14261
- import { createWriteStream as createWriteStream5 } from "node:fs";
14342
+ import { accessSync, createWriteStream as createWriteStream5, readFileSync as readFileSync2 } from "node:fs";
14262
14343
  import { mkdir as mkdir6, mkdtemp, rm, writeFile } from "node:fs/promises";
14263
14344
  import { tmpdir } from "node:os";
14264
14345
  import path19 from "node:path";
14265
- import { execSync } from "node:child_process";
14346
+ import { execSync as execSync2 } from "node:child_process";
14266
14347
  import { randomUUID as randomUUID8 } from "node:crypto";
14267
- import { accessSync, createWriteStream as createWriteStream6 } from "node:fs";
14348
+ import { accessSync as accessSync2, createWriteStream as createWriteStream6 } from "node:fs";
14268
14349
  import { mkdir as mkdir7 } from "node:fs/promises";
14269
14350
  import path20 from "node:path";
14270
14351
  import { createInterface } from "node:readline";
@@ -14339,7 +14420,7 @@ import { existsSync as existsSync5 } from "node:fs";
14339
14420
  import path45 from "node:path";
14340
14421
  import { mkdir as mkdir15, readFile as readFile13, writeFile as writeFile8 } from "node:fs/promises";
14341
14422
  import path46 from "node:path";
14342
- import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync2, readdirSync as readdirSync3, statSync as statSync2, writeFileSync } from "node:fs";
14423
+ import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync2, writeFileSync } from "node:fs";
14343
14424
  import path47 from "node:path";
14344
14425
  import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
14345
14426
  import { readdir as readdir8, stat as stat9 } from "node:fs/promises";
@@ -15043,6 +15124,7 @@ function validateTemplateVariables(content, source) {
15043
15124
  }
15044
15125
  var ANSI_YELLOW3 = "\x1B[33m";
15045
15126
  var ANSI_RESET4 = "\x1B[0m";
15127
+ var PROMPT_FILE_PREFIX = "file://";
15046
15128
  function normalizeEvaluatorType(type) {
15047
15129
  return type.replace(/_/g, "-");
15048
15130
  }
@@ -15341,12 +15423,23 @@ async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
15341
15423
  threshold: thresholdValue
15342
15424
  };
15343
15425
  } else {
15344
- const aggregatorPrompt = asString(rawAggregator.prompt);
15426
+ const rawAggPrompt = asString(rawAggregator.prompt);
15427
+ let aggregatorPrompt;
15345
15428
  let promptPath2;
15346
- if (aggregatorPrompt) {
15347
- const resolved = await resolveFileReference22(aggregatorPrompt, searchRoots);
15348
- if (resolved.resolvedPath) {
15349
- promptPath2 = path42.resolve(resolved.resolvedPath);
15429
+ if (rawAggPrompt) {
15430
+ if (rawAggPrompt.startsWith(PROMPT_FILE_PREFIX)) {
15431
+ const fileRef = rawAggPrompt.slice(PROMPT_FILE_PREFIX.length);
15432
+ aggregatorPrompt = fileRef;
15433
+ const resolved = await resolveFileReference22(fileRef, searchRoots);
15434
+ if (resolved.resolvedPath) {
15435
+ promptPath2 = path42.resolve(resolved.resolvedPath);
15436
+ } else {
15437
+ throw new Error(
15438
+ `Composite aggregator in '${evalId}': prompt file not found: ${resolved.displayPath}`
15439
+ );
15440
+ }
15441
+ } else {
15442
+ aggregatorPrompt = rawAggPrompt;
15350
15443
  }
15351
15444
  }
15352
15445
  aggregator = {
@@ -15926,21 +16019,25 @@ async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
15926
16019
  promptScriptConfig = rawPrompt.config;
15927
16020
  }
15928
16021
  } else if (typeof rawPrompt === "string") {
15929
- prompt = rawPrompt;
15930
- const resolved = await resolveFileReference22(prompt, searchRoots);
15931
- if (resolved.resolvedPath) {
15932
- promptPath = path42.resolve(resolved.resolvedPath);
15933
- try {
15934
- await validateCustomPromptContent(promptPath);
15935
- } catch (error) {
15936
- const message = error instanceof Error ? error.message : String(error);
15937
- throw new Error(`Evaluator '${name21}' template (${promptPath}): ${message}`);
16022
+ if (rawPrompt.startsWith(PROMPT_FILE_PREFIX)) {
16023
+ const fileRef = rawPrompt.slice(PROMPT_FILE_PREFIX.length);
16024
+ prompt = fileRef;
16025
+ const resolved = await resolveFileReference22(fileRef, searchRoots);
16026
+ if (resolved.resolvedPath) {
16027
+ promptPath = path42.resolve(resolved.resolvedPath);
16028
+ try {
16029
+ await validateCustomPromptContent(promptPath);
16030
+ } catch (error) {
16031
+ const message = error instanceof Error ? error.message : String(error);
16032
+ throw new Error(`Evaluator '${name21}' template (${promptPath}): ${message}`);
16033
+ }
16034
+ } else {
16035
+ throw new Error(
16036
+ `Evaluator '${name21}' in '${evalId}': prompt file not found: ${resolved.displayPath}`
16037
+ );
15938
16038
  }
15939
16039
  } else {
15940
- logWarning2(
15941
- `Inline prompt used for evaluator '${name21}' in '${evalId}' (file not found: ${resolved.displayPath})`,
15942
- resolved.attempted.length > 0 ? resolved.attempted.map((attempt) => ` Tried: ${attempt}`) : void 0
15943
- );
16040
+ prompt = rawPrompt;
15944
16041
  }
15945
16042
  }
15946
16043
  const _model = asString(rawEvaluator.model);
@@ -17811,7 +17908,7 @@ var OpenAIProvider = class {
17811
17908
  apiKey: config.apiKey,
17812
17909
  baseURL: config.baseURL
17813
17910
  });
17814
- this.model = openai(config.model);
17911
+ this.model = config.apiFormat === "responses" ? openai(config.model) : openai.chat(config.model);
17815
17912
  }
17816
17913
  id;
17817
17914
  kind = "openai";
@@ -19409,15 +19506,16 @@ var CliProvider = class {
19409
19506
  outputFilePath
19410
19507
  );
19411
19508
  const renderedCommand = renderTemplate(this.config.command, templateValues);
19509
+ const effectiveCwd = requests[0]?.cwd ?? this.config.cwd;
19412
19510
  if (this.verbose) {
19413
19511
  console.log(
19414
- `[cli-provider:${this.targetName}] (batch size=${requests.length}) cwd=${this.config.cwd ?? ""} command=${renderedCommand}`
19512
+ `[cli-provider:${this.targetName}] (batch size=${requests.length}) cwd=${effectiveCwd ?? ""} command=${renderedCommand}`
19415
19513
  );
19416
19514
  }
19417
19515
  try {
19418
19516
  const startTime = Date.now();
19419
19517
  const result = await this.runCommand(renderedCommand, {
19420
- cwd: this.config.cwd,
19518
+ cwd: effectiveCwd,
19421
19519
  env: process.env,
19422
19520
  timeoutMs: this.config.timeoutMs,
19423
19521
  signal: controller.signal
@@ -19450,7 +19548,7 @@ var CliProvider = class {
19450
19548
  command: renderedCommand,
19451
19549
  stderr: result.stderr,
19452
19550
  exitCode: result.exitCode ?? 0,
19453
- cwd: this.config.cwd,
19551
+ cwd: effectiveCwd,
19454
19552
  outputFile: outputFilePath
19455
19553
  }
19456
19554
  };
@@ -19468,7 +19566,7 @@ var CliProvider = class {
19468
19566
  command: renderedCommand,
19469
19567
  stderr: result.stderr,
19470
19568
  exitCode: result.exitCode ?? 0,
19471
- cwd: this.config.cwd,
19569
+ cwd: effectiveCwd,
19472
19570
  outputFile: outputFilePath,
19473
19571
  error: errorMessage
19474
19572
  }
@@ -19483,7 +19581,7 @@ var CliProvider = class {
19483
19581
  command: renderedCommand,
19484
19582
  stderr: result.stderr,
19485
19583
  exitCode: result.exitCode ?? 0,
19486
- cwd: this.config.cwd,
19584
+ cwd: effectiveCwd,
19487
19585
  outputFile: outputFilePath,
19488
19586
  recordId: evalCaseId
19489
19587
  }
@@ -21426,6 +21524,57 @@ function subscribeToPiLogEntries(listener) {
21426
21524
  store.delete(listener);
21427
21525
  };
21428
21526
  }
21527
+ var SUBPROVIDER_ALIASES = {
21528
+ azure: "azure-openai-responses"
21529
+ };
21530
+ var SUBPROVIDER_ALIASES_WITH_BASE_URL = {
21531
+ // Azure v1 endpoints are OpenAI-compatible; use the standard client
21532
+ // to avoid AzureOpenAI adding api-version query params.
21533
+ azure: "openai-responses"
21534
+ };
21535
+ var ENV_KEY_MAP = {
21536
+ google: "GEMINI_API_KEY",
21537
+ gemini: "GEMINI_API_KEY",
21538
+ anthropic: "ANTHROPIC_API_KEY",
21539
+ openai: "OPENAI_API_KEY",
21540
+ groq: "GROQ_API_KEY",
21541
+ xai: "XAI_API_KEY",
21542
+ openrouter: "OPENROUTER_API_KEY",
21543
+ azure: "AZURE_OPENAI_API_KEY"
21544
+ };
21545
+ var ENV_BASE_URL_MAP = {
21546
+ openai: "OPENAI_BASE_URL",
21547
+ azure: "AZURE_OPENAI_BASE_URL",
21548
+ openrouter: "OPENROUTER_BASE_URL"
21549
+ };
21550
+ function resolveSubprovider(name21, hasBaseUrl = false) {
21551
+ const lower = name21.toLowerCase();
21552
+ if (hasBaseUrl) {
21553
+ const alias = SUBPROVIDER_ALIASES_WITH_BASE_URL[lower];
21554
+ if (alias) return alias;
21555
+ }
21556
+ return SUBPROVIDER_ALIASES[lower] ?? name21;
21557
+ }
21558
+ function resolveCliProvider(name21) {
21559
+ const lower = name21.toLowerCase();
21560
+ if (lower === "azure") return "azure-openai-responses";
21561
+ return name21;
21562
+ }
21563
+ function resolveEnvKeyName(provider, hasBaseUrl = false) {
21564
+ const lower = provider.toLowerCase();
21565
+ if (hasBaseUrl && lower === "azure") return "OPENAI_API_KEY";
21566
+ return ENV_KEY_MAP[lower];
21567
+ }
21568
+ function resolveEnvBaseUrlName(provider, hasBaseUrl = false) {
21569
+ const lower = provider.toLowerCase();
21570
+ if (hasBaseUrl && lower === "azure") return "OPENAI_BASE_URL";
21571
+ return ENV_BASE_URL_MAP[lower];
21572
+ }
21573
+ function extractAzureResourceName(baseUrl) {
21574
+ const urlMatch = baseUrl.match(/^https?:\/\/([^./]+)/);
21575
+ if (urlMatch) return urlMatch[1];
21576
+ return baseUrl;
21577
+ }
21429
21578
  function extractPiTextContent(content) {
21430
21579
  if (typeof content === "string") {
21431
21580
  return content;
@@ -21581,12 +21730,12 @@ var PiCliProvider = class {
21581
21730
  buildPiArgs(prompt, inputFiles) {
21582
21731
  const args = [];
21583
21732
  if (this.config.subprovider) {
21584
- args.push("--provider", this.config.subprovider);
21733
+ args.push("--provider", resolveCliProvider(this.config.subprovider));
21585
21734
  }
21586
21735
  if (this.config.model) {
21587
21736
  args.push("--model", this.config.model);
21588
21737
  }
21589
- if (this.config.apiKey) {
21738
+ if (this.config.apiKey && this.config.subprovider?.toLowerCase() !== "azure") {
21590
21739
  args.push("--api-key", this.config.apiKey);
21591
21740
  }
21592
21741
  args.push("--mode", "json");
@@ -21638,35 +21787,35 @@ ${prompt}` : prompt;
21638
21787
  }
21639
21788
  buildEnv() {
21640
21789
  const env = { ...process.env };
21641
- if (this.config.apiKey) {
21642
- const provider = this.config.subprovider?.toLowerCase() ?? "google";
21643
- const ENV_KEY_MAP = {
21644
- google: "GEMINI_API_KEY",
21645
- gemini: "GEMINI_API_KEY",
21646
- anthropic: "ANTHROPIC_API_KEY",
21647
- openai: "OPENAI_API_KEY",
21648
- groq: "GROQ_API_KEY",
21649
- xai: "XAI_API_KEY",
21650
- openrouter: "OPENROUTER_API_KEY"
21651
- };
21652
- const envKey = ENV_KEY_MAP[provider];
21653
- if (envKey) {
21654
- env[envKey] = this.config.apiKey;
21790
+ const provider = this.config.subprovider?.toLowerCase() ?? "google";
21791
+ if (provider === "azure") {
21792
+ if (this.config.apiKey) {
21793
+ env.AZURE_OPENAI_API_KEY = this.config.apiKey;
21794
+ }
21795
+ if (this.config.baseUrl) {
21796
+ env.AZURE_OPENAI_RESOURCE_NAME = extractAzureResourceName(this.config.baseUrl);
21797
+ }
21798
+ } else {
21799
+ if (this.config.apiKey) {
21800
+ const envKey = resolveEnvKeyName(provider);
21801
+ if (envKey) {
21802
+ env[envKey] = this.config.apiKey;
21803
+ }
21655
21804
  }
21656
21805
  }
21657
21806
  if (this.config.subprovider) {
21658
- const provider = this.config.subprovider.toLowerCase();
21807
+ const resolvedProvider = resolveCliProvider(this.config.subprovider);
21659
21808
  const PROVIDER_OWN_PREFIXES = {
21660
21809
  openrouter: ["OPENROUTER_"],
21661
21810
  anthropic: ["ANTHROPIC_"],
21662
21811
  openai: ["OPENAI_"],
21663
- azure: ["AZURE_OPENAI_"],
21812
+ "azure-openai-responses": ["AZURE_OPENAI_"],
21664
21813
  google: ["GEMINI_", "GOOGLE_GENERATIVE_AI_"],
21665
21814
  gemini: ["GEMINI_", "GOOGLE_GENERATIVE_AI_"],
21666
21815
  groq: ["GROQ_"],
21667
21816
  xai: ["XAI_"]
21668
21817
  };
21669
- const ownPrefixes = PROVIDER_OWN_PREFIXES[provider] ?? [];
21818
+ const ownPrefixes = PROVIDER_OWN_PREFIXES[resolvedProvider] ?? [];
21670
21819
  const allOtherPrefixes = Object.entries(PROVIDER_OWN_PREFIXES).filter(([key]) => key !== provider).flatMap(([, prefixes]) => prefixes);
21671
21820
  for (const key of Object.keys(env)) {
21672
21821
  if (allOtherPrefixes.some((prefix) => key.startsWith(prefix)) && !ownPrefixes.some((prefix) => key.startsWith(prefix))) {
@@ -21957,6 +22106,24 @@ function extractMessages(events) {
21957
22106
  }
21958
22107
  }
21959
22108
  }
22109
+ if (messages) {
22110
+ for (let i = messages.length - 1; i >= 0; i--) {
22111
+ if (messages[i].role === "assistant" && !messages[i].content) {
22112
+ for (let j = events.length - 1; j >= 0; j--) {
22113
+ const evt = events[j];
22114
+ if (!evt || evt.type !== "message_end") continue;
22115
+ const msg = evt.message;
22116
+ if (msg?.role !== "assistant") continue;
22117
+ const text2 = extractPiTextContent(msg.content);
22118
+ if (text2) {
22119
+ messages[i] = { ...messages[i], content: text2 };
22120
+ break;
22121
+ }
22122
+ }
22123
+ break;
22124
+ }
22125
+ }
22126
+ }
21960
22127
  const eventToolCalls = extractToolCallsFromEvents(events);
21961
22128
  if (eventToolCalls.length > 0) {
21962
22129
  injectEventToolCalls(messages, eventToolCalls);
@@ -22141,17 +22308,43 @@ function formatTimeoutSuffix3(timeoutMs) {
22141
22308
  if (!timeoutMs || timeoutMs <= 0) return "";
22142
22309
  return ` after ${Math.ceil(timeoutMs / 1e3)}s`;
22143
22310
  }
22311
+ function resolveWindowsCmd(executable) {
22312
+ if (process.platform !== "win32") return [executable, []];
22313
+ const lower = executable.toLowerCase();
22314
+ if (lower.endsWith(".js") || lower.endsWith(".exe")) return [executable, []];
22315
+ let fullPath;
22316
+ try {
22317
+ fullPath = execSync(`where ${executable}`, { encoding: "utf-8" }).trim().split(/\r?\n/)[0].trim();
22318
+ } catch {
22319
+ return [executable, []];
22320
+ }
22321
+ const cmdPath = fullPath.endsWith(".cmd") ? fullPath : `${fullPath}.cmd`;
22322
+ try {
22323
+ const content = readFileSync2(cmdPath, "utf-8");
22324
+ const match = content.match(/"?%_prog%"?\s+"([^"]+\.js)"/);
22325
+ if (match) {
22326
+ const dp0 = path19.dirname(path19.resolve(cmdPath));
22327
+ const scriptPath = match[1].replace(/%dp0%[/\\]?/gi, `${dp0}${path19.sep}`);
22328
+ try {
22329
+ accessSync(scriptPath);
22330
+ return ["node", [scriptPath]];
22331
+ } catch {
22332
+ }
22333
+ }
22334
+ } catch {
22335
+ }
22336
+ return [executable, []];
22337
+ }
22144
22338
  async function defaultPiRunner(options) {
22145
22339
  return await new Promise((resolve2, reject) => {
22146
22340
  const parts = options.executable.split(/\s+/);
22147
- const executable = parts[0];
22148
- const executableArgs = parts.slice(1);
22341
+ const [resolvedExe, prefixArgs] = resolveWindowsCmd(parts[0]);
22342
+ const executableArgs = [...prefixArgs, ...parts.slice(1)];
22149
22343
  const allArgs = [...executableArgs, ...options.args];
22150
- const child = spawn3(executable, allArgs, {
22344
+ const child = spawn3(resolvedExe, allArgs, {
22151
22345
  cwd: options.cwd,
22152
22346
  env: options.env,
22153
- stdio: ["pipe", "pipe", "pipe"],
22154
- shell: false
22347
+ stdio: ["pipe", "pipe", "pipe"]
22155
22348
  });
22156
22349
  let stdout = "";
22157
22350
  let stderr = "";
@@ -22227,7 +22420,7 @@ function findAgentvRoot() {
22227
22420
  for (let i = 0; i < 10; i++) {
22228
22421
  try {
22229
22422
  const pkg = path20.join(dir, "package.json");
22230
- accessSync(pkg);
22423
+ accessSync2(pkg);
22231
22424
  return dir;
22232
22425
  } catch {
22233
22426
  const parent = path20.dirname(dir);
@@ -22247,7 +22440,7 @@ async function doLoadSdkModules() {
22247
22440
  if (await promptInstall()) {
22248
22441
  const installDir = findAgentvRoot();
22249
22442
  console.error(`Installing @mariozechner/pi-coding-agent into ${installDir}...`);
22250
- execSync("bun add @mariozechner/pi-coding-agent", {
22443
+ execSync2("bun add @mariozechner/pi-coding-agent", {
22251
22444
  cwd: installDir,
22252
22445
  stdio: "inherit"
22253
22446
  });
@@ -22288,7 +22481,9 @@ async function loadSdkModules() {
22288
22481
  codingTools: piSdk.codingTools,
22289
22482
  toolMap,
22290
22483
  SessionManager: piSdk.SessionManager,
22291
- getModel: piAi.getModel
22484
+ getModel: piAi.getModel,
22485
+ // biome-ignore lint/suspicious/noExplicitAny: registerBuiltInApiProviders exists at runtime but not in type defs
22486
+ registerBuiltInApiProviders: piAi.registerBuiltInApiProviders
22292
22487
  };
22293
22488
  }
22294
22489
  var PiCodingAgentProvider = class {
@@ -22310,17 +22505,31 @@ var PiCodingAgentProvider = class {
22310
22505
  const startTime = (/* @__PURE__ */ new Date()).toISOString();
22311
22506
  const startMs = Date.now();
22312
22507
  const sdk = await loadSdkModules();
22508
+ sdk.registerBuiltInApiProviders();
22313
22509
  const logger = await this.createStreamLogger(request).catch(() => void 0);
22314
22510
  try {
22315
22511
  const cwd = this.resolveCwd(request.cwd);
22316
- const providerName = this.config.subprovider ?? "google";
22512
+ const rawProvider = this.config.subprovider ?? "google";
22513
+ const hasBaseUrl = !!this.config.baseUrl;
22514
+ const providerName = resolveSubprovider(rawProvider, hasBaseUrl);
22317
22515
  const modelId = this.config.model ?? "gemini-2.5-flash";
22318
- this.setApiKeyEnv(providerName);
22319
- const model = sdk.getModel(providerName, modelId);
22516
+ this.setApiKeyEnv(rawProvider, hasBaseUrl);
22517
+ this.setBaseUrlEnv(rawProvider, hasBaseUrl);
22518
+ let model = sdk.getModel(providerName, modelId);
22320
22519
  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
- );
22520
+ const envProvider = providerName.replace(/-responses$/, "");
22521
+ model = {
22522
+ id: modelId,
22523
+ name: modelId,
22524
+ api: providerName,
22525
+ provider: envProvider,
22526
+ baseUrl: this.config.baseUrl ?? "",
22527
+ reasoning: false,
22528
+ input: ["text"],
22529
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
22530
+ contextWindow: 128e3,
22531
+ maxTokens: 16384
22532
+ };
22324
22533
  }
22325
22534
  const tools = this.resolveTools(sdk);
22326
22535
  const { session } = await sdk.createAgentSession({
@@ -22473,22 +22682,21 @@ ${fileList}`;
22473
22682
  }
22474
22683
  }
22475
22684
  /** Maps config apiKey to the provider-specific env var the SDK reads. */
22476
- setApiKeyEnv(providerName) {
22685
+ setApiKeyEnv(providerName, hasBaseUrl = false) {
22477
22686
  if (!this.config.apiKey) return;
22478
- const ENV_KEY_MAP = {
22479
- google: "GEMINI_API_KEY",
22480
- gemini: "GEMINI_API_KEY",
22481
- anthropic: "ANTHROPIC_API_KEY",
22482
- openai: "OPENAI_API_KEY",
22483
- groq: "GROQ_API_KEY",
22484
- xai: "XAI_API_KEY",
22485
- openrouter: "OPENROUTER_API_KEY"
22486
- };
22487
- const envKey = ENV_KEY_MAP[providerName.toLowerCase()];
22687
+ const envKey = resolveEnvKeyName(providerName, hasBaseUrl);
22488
22688
  if (envKey) {
22489
22689
  process.env[envKey] = this.config.apiKey;
22490
22690
  }
22491
22691
  }
22692
+ /** Maps config baseUrl to the provider-specific env var the SDK reads. */
22693
+ setBaseUrlEnv(providerName, hasBaseUrl = false) {
22694
+ if (!this.config.baseUrl) return;
22695
+ const envKey = resolveEnvBaseUrlName(providerName, hasBaseUrl);
22696
+ if (envKey) {
22697
+ process.env[envKey] = this.config.baseUrl;
22698
+ }
22699
+ }
22492
22700
  resolveCwd(cwdOverride) {
22493
22701
  if (cwdOverride) {
22494
22702
  return path20.resolve(cwdOverride);
@@ -24132,8 +24340,11 @@ function assertTargetDefinition(value, index, filePath) {
24132
24340
  `targets.yaml entry at index ${index} in ${filePath} is missing a valid 'name'`
24133
24341
  );
24134
24342
  }
24135
- if (typeof provider !== "string" || provider.trim().length === 0) {
24136
- throw new Error(`targets.yaml entry '${name21}' in ${filePath} is missing a valid 'provider'`);
24343
+ const hasUseTarget = typeof value.use_target === "string" && value.use_target.trim().length > 0;
24344
+ if (!hasUseTarget && (typeof provider !== "string" || provider.trim().length === 0)) {
24345
+ throw new Error(
24346
+ `targets.yaml entry '${name21}' in ${filePath} is missing a valid 'provider' (or use use_target for delegation)`
24347
+ );
24137
24348
  }
24138
24349
  return value;
24139
24350
  }
@@ -29427,7 +29638,7 @@ async function runEvaluation(options) {
29427
29638
  if (resolvedTargetsByName.has(name21)) {
29428
29639
  return resolvedTargetsByName.get(name21);
29429
29640
  }
29430
- const definition = targetDefinitions.get(name21);
29641
+ const definition = resolveDelegatedTargetDefinition(name21, targetDefinitions, envLookup);
29431
29642
  if (!definition) {
29432
29643
  return void 0;
29433
29644
  }
@@ -30435,6 +30646,7 @@ async function runEvalCase(options) {
30435
30646
  let attempt = 0;
30436
30647
  let providerResponse = cachedResponse;
30437
30648
  let lastError;
30649
+ let targetUsed;
30438
30650
  while (!providerResponse && attempt < attemptBudget) {
30439
30651
  try {
30440
30652
  providerResponse = await invokeProvider(provider, {
@@ -30457,25 +30669,33 @@ async function runEvalCase(options) {
30457
30669
  attempt += 1;
30458
30670
  continue;
30459
30671
  }
30460
- const errorResult = buildErrorResult(
30461
- evalCase,
30462
- target.name,
30463
- nowFn(),
30464
- error,
30465
- promptInputs,
30466
- provider,
30467
- "agent",
30468
- "provider_error",
30469
- verbose
30470
- );
30471
- if (workspacePath) {
30472
- if (forceCleanup) {
30473
- await cleanupWorkspace(workspacePath).catch(() => {
30474
- });
30475
- }
30476
- return { ...errorResult, workspacePath };
30672
+ break;
30673
+ }
30674
+ }
30675
+ if (!providerResponse && target.fallbackTargets?.length && targetResolver) {
30676
+ for (const fallbackName of target.fallbackTargets) {
30677
+ const fallbackProvider = targetResolver(fallbackName);
30678
+ if (!fallbackProvider) {
30679
+ continue;
30680
+ }
30681
+ try {
30682
+ providerResponse = await invokeProvider(fallbackProvider, {
30683
+ evalCase,
30684
+ target,
30685
+ promptInputs,
30686
+ attempt: 0,
30687
+ agentTimeoutMs,
30688
+ signal,
30689
+ cwd: workspacePath,
30690
+ workspaceFile: caseWorkspaceFile ?? suiteWorkspaceFile,
30691
+ captureFileChanges: !!baselineCommit,
30692
+ streamCallbacks: options.streamCallbacks
30693
+ });
30694
+ targetUsed = fallbackName;
30695
+ break;
30696
+ } catch (error) {
30697
+ lastError = error;
30477
30698
  }
30478
- return errorResult;
30479
30699
  }
30480
30700
  }
30481
30701
  if (!providerResponse) {
@@ -30601,8 +30821,10 @@ async function runEvalCase(options) {
30601
30821
  };
30602
30822
  const skippedEvaluatorError = buildSkippedEvaluatorError(result.scores);
30603
30823
  const executionStatus = providerError || skippedEvaluatorError ? "execution_error" : classifyQualityStatus(result.score, caseThreshold);
30824
+ const targetUsedField = targetUsed ? { targetUsed } : {};
30604
30825
  const finalResult = providerError ? {
30605
30826
  ...result,
30827
+ ...targetUsedField,
30606
30828
  evalRun,
30607
30829
  error: providerError,
30608
30830
  executionStatus,
@@ -30614,6 +30836,7 @@ async function runEvalCase(options) {
30614
30836
  afterEachOutput
30615
30837
  } : skippedEvaluatorError ? {
30616
30838
  ...result,
30839
+ ...targetUsedField,
30617
30840
  score: 0,
30618
30841
  evalRun,
30619
30842
  error: skippedEvaluatorError,
@@ -30626,6 +30849,7 @@ async function runEvalCase(options) {
30626
30849
  afterEachOutput
30627
30850
  } : {
30628
30851
  ...result,
30852
+ ...targetUsedField,
30629
30853
  evalRun,
30630
30854
  executionStatus,
30631
30855
  beforeAllOutput,
@@ -31495,7 +31719,7 @@ async function discoverDefaultTarget(repoRoot) {
31495
31719
  return null;
31496
31720
  }
31497
31721
  async function loadEnvHierarchy(repoRoot, startPath) {
31498
- const { readFileSync: readFileSync3 } = await import("node:fs");
31722
+ const { readFileSync: readFileSync4 } = await import("node:fs");
31499
31723
  const chain = buildDirectoryChain(startPath, repoRoot);
31500
31724
  const envFiles = [];
31501
31725
  for (const dir of chain) {
@@ -31504,7 +31728,7 @@ async function loadEnvHierarchy(repoRoot, startPath) {
31504
31728
  }
31505
31729
  for (let i = 0; i < envFiles.length; i++) {
31506
31730
  try {
31507
- const content = readFileSync3(envFiles[i], "utf8");
31731
+ const content = readFileSync4(envFiles[i], "utf8");
31508
31732
  for (const line of content.split("\n")) {
31509
31733
  const trimmed = line.trim();
31510
31734
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -31715,7 +31939,7 @@ function loadProjectRegistry() {
31715
31939
  return { projects: [] };
31716
31940
  }
31717
31941
  try {
31718
- const raw = readFileSync2(registryPath, "utf-8");
31942
+ const raw = readFileSync3(registryPath, "utf-8");
31719
31943
  const parsed = parseYaml3(raw);
31720
31944
  if (!parsed || !Array.isArray(parsed.projects)) {
31721
31945
  return { projects: [] };
@@ -32620,6 +32844,7 @@ export {
32620
32844
  resolveFileReference,
32621
32845
  CLI_PLACEHOLDERS,
32622
32846
  COMMON_TARGET_SETTINGS,
32847
+ resolveDelegatedTargetDefinition,
32623
32848
  resolveTargetDefinition,
32624
32849
  KNOWN_PROVIDERS,
32625
32850
  PROVIDER_ALIASES,
@@ -32771,4 +32996,4 @@ export {
32771
32996
  readTranscriptFile,
32772
32997
  createAgentKernel
32773
32998
  };
32774
- //# sourceMappingURL=chunk-7DRAXDVC.js.map
32999
+ //# sourceMappingURL=chunk-YXXD27OK.js.map