agentv 2.16.0 → 2.17.1-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,7 +11,7 @@ import {
11
11
  validateEvalFile,
12
12
  validateFileReferences,
13
13
  validateTargetsFile
14
- } from "./chunk-QLCVA3ZS.js";
14
+ } from "./chunk-5YQVVRZH.js";
15
15
  import {
16
16
  assembleLlmJudgePrompt,
17
17
  buildPromptInputs,
@@ -27,7 +27,7 @@ import {
27
27
  toCamelCaseDeep,
28
28
  toSnakeCaseDeep as toSnakeCaseDeep2,
29
29
  trimBaselineResult
30
- } from "./chunk-LZ5MPQFM.js";
30
+ } from "./chunk-SO4O4O2B.js";
31
31
  import {
32
32
  __commonJS,
33
33
  __esm,
@@ -4042,7 +4042,7 @@ var evalRunCommand = command({
4042
4042
  },
4043
4043
  handler: async (args) => {
4044
4044
  if (args.evalPaths.length === 0 && process.stdin.isTTY) {
4045
- const { launchInteractiveWizard } = await import("./interactive-ZXYNPRCT.js");
4045
+ const { launchInteractiveWizard } = await import("./interactive-MKS2F23Q.js");
4046
4046
  await launchInteractiveWizard();
4047
4047
  return;
4048
4048
  }
@@ -5929,4 +5929,4 @@ export {
5929
5929
  preprocessArgv,
5930
5930
  runCli
5931
5931
  };
5932
- //# sourceMappingURL=chunk-JZ62HLUC.js.map
5932
+ //# sourceMappingURL=chunk-RJTSVXRA.js.map
@@ -148,7 +148,7 @@ var require_dist = __commonJS({
148
148
  }
149
149
  });
150
150
 
151
- // ../../packages/core/dist/chunk-E6AJPAXM.js
151
+ // ../../packages/core/dist/chunk-PSYFRPNT.js
152
152
  import { constants } from "node:fs";
153
153
  import { access, readFile } from "node:fs/promises";
154
154
  import path from "node:path";
@@ -4195,7 +4195,7 @@ var coerce = {
4195
4195
  };
4196
4196
  var NEVER = INVALID;
4197
4197
 
4198
- // ../../packages/core/dist/chunk-E6AJPAXM.js
4198
+ // ../../packages/core/dist/chunk-PSYFRPNT.js
4199
4199
  var TEST_MESSAGE_ROLE_VALUES = ["system", "user", "assistant", "tool"];
4200
4200
  var TEST_MESSAGE_ROLES = TEST_MESSAGE_ROLE_VALUES;
4201
4201
  var TEST_MESSAGE_ROLE_SET = new Set(TEST_MESSAGE_ROLE_VALUES);
@@ -34107,6 +34107,23 @@ function mergeExecutionMetrics(computed, metrics) {
34107
34107
  endTime: metrics.endTime ?? computed.endTime
34108
34108
  };
34109
34109
  }
34110
+ var ENV_VAR_PATTERN = /\$\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g;
34111
+ function interpolateEnv(value, env) {
34112
+ if (typeof value === "string") {
34113
+ return value.replace(ENV_VAR_PATTERN, (_, varName) => env[varName] ?? "");
34114
+ }
34115
+ if (Array.isArray(value)) {
34116
+ return value.map((item) => interpolateEnv(item, env));
34117
+ }
34118
+ if (value !== null && typeof value === "object") {
34119
+ const result = {};
34120
+ for (const [key, val] of Object.entries(value)) {
34121
+ result[key] = interpolateEnv(val, env);
34122
+ }
34123
+ return result;
34124
+ }
34125
+ return value;
34126
+ }
34110
34127
  var ANSI_YELLOW = "\x1B[33m";
34111
34128
  var ANSI_RESET = "\x1B[0m";
34112
34129
  var FILE_PROTOCOL = "file://";
@@ -34120,7 +34137,8 @@ function isGlobPattern(filePath) {
34120
34137
  return filePath.includes("*") || filePath.includes("?") || filePath.includes("{");
34121
34138
  }
34122
34139
  function parseYamlCases(content, filePath) {
34123
- const parsed = parseYaml(content);
34140
+ const raw = parseYaml(content);
34141
+ const parsed = interpolateEnv(raw, process.env);
34124
34142
  if (!Array.isArray(parsed)) {
34125
34143
  throw new Error(
34126
34144
  `External test file must contain a YAML array, got ${typeof parsed}: ${filePath}`
@@ -34142,7 +34160,8 @@ function parseJsonlCases(content, filePath) {
34142
34160
  const line = lines[i].trim();
34143
34161
  if (line === "") continue;
34144
34162
  try {
34145
- const parsed = JSON.parse(line);
34163
+ const raw = JSON.parse(line);
34164
+ const parsed = interpolateEnv(raw, process.env);
34146
34165
  if (!isJsonObject(parsed)) {
34147
34166
  throw new Error("Expected JSON object");
34148
34167
  }
@@ -36247,7 +36266,7 @@ async function loadSidecarMetadata(jsonlPath, verbose) {
36247
36266
  }
36248
36267
  try {
36249
36268
  const content = await readFile5(sidecarPath, "utf8");
36250
- const parsed = parseYaml2(content);
36269
+ const parsed = interpolateEnv(parseYaml2(content), process.env);
36251
36270
  if (!isJsonObject(parsed)) {
36252
36271
  logWarning4(`Invalid sidecar metadata format in ${sidecarPath}`);
36253
36272
  return {};
@@ -36270,7 +36289,8 @@ function parseJsonlContent(content, filePath) {
36270
36289
  const line = lines[i].trim();
36271
36290
  if (line === "") continue;
36272
36291
  try {
36273
- const parsed = JSON.parse(line);
36292
+ const raw = JSON.parse(line);
36293
+ const parsed = interpolateEnv(raw, process.env);
36274
36294
  if (!isJsonObject(parsed)) {
36275
36295
  throw new Error("Expected JSON object");
36276
36296
  }
@@ -36327,9 +36347,10 @@ async function loadTestsFromJsonl(evalFilePath, repoRoot, options) {
36327
36347
  }
36328
36348
  const inputMessages = resolveInputMessages(evalcase);
36329
36349
  const expectedMessages = resolveExpectedMessages(evalcase) ?? [];
36330
- if (!id || !outcome || !inputMessages || inputMessages.length === 0) {
36350
+ const hasEvaluationSpec = !!outcome || expectedMessages.length > 0 || evalcase.assert !== void 0;
36351
+ if (!id || !hasEvaluationSpec || !inputMessages || inputMessages.length === 0) {
36331
36352
  logError(
36332
- `Skipping incomplete test at line ${lineNumber}: ${id ?? "unknown"}. Missing required fields: id, criteria, and/or input`
36353
+ `Skipping incomplete test at line ${lineNumber}: ${id ?? "unknown"}. Missing required fields: id, input, and at least one of criteria/expected_output/assert`
36333
36354
  );
36334
36355
  continue;
36335
36356
  }
@@ -36407,7 +36428,7 @@ async function loadTestsFromJsonl(evalFilePath, repoRoot, options) {
36407
36428
  guideline_paths: guidelinePaths.map((guidelinePath) => path6.resolve(guidelinePath)),
36408
36429
  guideline_patterns: guidelinePatterns,
36409
36430
  file_paths: allFilePaths,
36410
- criteria: outcome,
36431
+ criteria: outcome ?? "",
36411
36432
  evaluator: evalCaseEvaluatorKind,
36412
36433
  evaluators
36413
36434
  };
@@ -36711,7 +36732,7 @@ async function readTestSuiteMetadata(testFilePath) {
36711
36732
  try {
36712
36733
  const absolutePath = path8.resolve(testFilePath);
36713
36734
  const content = await readFile7(absolutePath, "utf8");
36714
- const parsed = parse22(content);
36735
+ const parsed = interpolateEnv(parse22(content), process.env);
36715
36736
  if (!isJsonObject(parsed)) {
36716
36737
  return {};
36717
36738
  }
@@ -36761,11 +36782,11 @@ async function loadTestsFromYaml(evalFilePath, repoRoot, options) {
36761
36782
  const config2 = await loadConfig(absoluteTestPath, repoRootPath);
36762
36783
  const guidelinePatterns = config2?.guideline_patterns;
36763
36784
  const rawFile = await readFile7(absoluteTestPath, "utf8");
36764
- const parsed = parse22(rawFile);
36765
- if (!isJsonObject(parsed)) {
36785
+ const interpolated = interpolateEnv(parse22(rawFile), process.env);
36786
+ if (!isJsonObject(interpolated)) {
36766
36787
  throw new Error(`Invalid test file format: ${evalFilePath}`);
36767
36788
  }
36768
- const suite = parsed;
36789
+ const suite = interpolated;
36769
36790
  const datasetNameFromSuite = asString6(suite.dataset)?.trim();
36770
36791
  const fallbackDataset = path8.basename(absoluteTestPath).replace(/\.ya?ml$/i, "") || "eval";
36771
36792
  const datasetName = datasetNameFromSuite && datasetNameFromSuite.length > 0 ? datasetNameFromSuite : fallbackDataset;
@@ -36809,9 +36830,10 @@ async function loadTestsFromYaml(evalFilePath, repoRoot, options) {
36809
36830
  }
36810
36831
  const testInputMessages = resolveInputMessages(evalcase);
36811
36832
  const expectedMessages = resolveExpectedMessages(evalcase) ?? [];
36812
- if (!id || !outcome || !testInputMessages || testInputMessages.length === 0) {
36833
+ const hasEvaluationSpec = !!outcome || expectedMessages.length > 0 || evalcase.assert !== void 0;
36834
+ if (!id || !hasEvaluationSpec || !testInputMessages || testInputMessages.length === 0) {
36813
36835
  logError2(
36814
- `Skipping incomplete test: ${id ?? "unknown"}. Missing required fields: id, criteria, and/or input`
36836
+ `Skipping incomplete test: ${id ?? "unknown"}. Missing required fields: id, input, and at least one of criteria/expected_output/assert`
36815
36837
  );
36816
36838
  continue;
36817
36839
  }
@@ -36907,7 +36929,7 @@ async function loadTestsFromYaml(evalFilePath, repoRoot, options) {
36907
36929
  guideline_paths: guidelinePaths.map((guidelinePath) => path8.resolve(guidelinePath)),
36908
36930
  guideline_patterns: guidelinePatterns,
36909
36931
  file_paths: allFilePaths,
36910
- criteria: outcome,
36932
+ criteria: outcome ?? "",
36911
36933
  evaluator: evalCaseEvaluatorKind,
36912
36934
  evaluators,
36913
36935
  workspace: mergedWorkspace,
@@ -37017,30 +37039,24 @@ function parseWorkspaceHookConfig(raw, evalFileDir) {
37017
37039
  const script = parseWorkspaceScriptConfig(raw, evalFileDir);
37018
37040
  const obj = raw;
37019
37041
  const reset = obj.reset === "none" || obj.reset === "fast" || obj.reset === "strict" ? obj.reset : void 0;
37020
- const clean = obj.clean === "always" || obj.clean === "on_success" || obj.clean === "on_failure" || obj.clean === "never" ? obj.clean : void 0;
37021
- if (!script && !reset && !clean) return void 0;
37042
+ if (!script && !reset) return void 0;
37022
37043
  return {
37023
37044
  ...script ?? {},
37024
- ...reset !== void 0 && { reset },
37025
- ...clean !== void 0 && { clean }
37045
+ ...reset !== void 0 && { reset }
37026
37046
  };
37027
37047
  }
37028
37048
  function parseWorkspaceHooksConfig(raw, evalFileDir) {
37029
37049
  if (!isJsonObject(raw)) return void 0;
37030
37050
  const obj = raw;
37031
- const beforeAllTests = parseWorkspaceHookConfig(obj.before_all_tests, evalFileDir);
37032
- const beforeEachTest = parseWorkspaceHookConfig(obj.before_each_test, evalFileDir);
37033
- const afterEachTest = parseWorkspaceHookConfig(obj.after_each_test, evalFileDir);
37034
- const afterAllTests = parseWorkspaceHookConfig(obj.after_all_tests, evalFileDir);
37035
- const onReuse = parseWorkspaceHookConfig(obj.on_reuse, evalFileDir);
37036
- const onFinish = parseWorkspaceHookConfig(obj.on_finish, evalFileDir);
37051
+ const beforeAll = parseWorkspaceHookConfig(obj.before_all, evalFileDir);
37052
+ const beforeEach = parseWorkspaceHookConfig(obj.before_each, evalFileDir);
37053
+ const afterEach = parseWorkspaceHookConfig(obj.after_each, evalFileDir);
37054
+ const afterAll = parseWorkspaceHookConfig(obj.after_all, evalFileDir);
37037
37055
  const hooks = {
37038
- ...beforeAllTests !== void 0 && { before_all_tests: beforeAllTests },
37039
- ...beforeEachTest !== void 0 && { before_each_test: beforeEachTest },
37040
- ...afterEachTest !== void 0 && { after_each_test: afterEachTest },
37041
- ...afterAllTests !== void 0 && { after_all_tests: afterAllTests },
37042
- ...onReuse !== void 0 && { on_reuse: onReuse },
37043
- ...onFinish !== void 0 && { on_finish: onFinish }
37056
+ ...beforeAll !== void 0 && { before_all: beforeAll },
37057
+ ...beforeEach !== void 0 && { before_each: beforeEach },
37058
+ ...afterEach !== void 0 && { after_each: afterEach },
37059
+ ...afterAll !== void 0 && { after_all: afterAll }
37044
37060
  };
37045
37061
  return Object.keys(hooks).length > 0 ? hooks : void 0;
37046
37062
  }
@@ -37053,7 +37069,7 @@ async function resolveWorkspaceConfig(raw, evalFileDir) {
37053
37069
  } catch {
37054
37070
  throw new Error(`Workspace file not found: ${raw} (resolved to ${workspaceFilePath})`);
37055
37071
  }
37056
- const parsed = parse22(content);
37072
+ const parsed = interpolateEnv(parse22(content), process.env);
37057
37073
  if (!isJsonObject(parsed)) {
37058
37074
  throw new Error(
37059
37075
  `Invalid workspace file format: ${workspaceFilePath} (expected a YAML object)`
@@ -37101,18 +37117,10 @@ function mergeWorkspaceConfigs(suiteLevel, caseLevel) {
37101
37117
  };
37102
37118
  };
37103
37119
  const mergedHooks = {
37104
- before_all_tests: mergeHook(
37105
- suiteLevel.hooks?.before_all_tests,
37106
- caseLevel.hooks?.before_all_tests
37107
- ),
37108
- before_each_test: mergeHook(
37109
- suiteLevel.hooks?.before_each_test,
37110
- caseLevel.hooks?.before_each_test
37111
- ),
37112
- after_each_test: mergeHook(suiteLevel.hooks?.after_each_test, caseLevel.hooks?.after_each_test),
37113
- after_all_tests: mergeHook(suiteLevel.hooks?.after_all_tests, caseLevel.hooks?.after_all_tests),
37114
- on_reuse: mergeHook(suiteLevel.hooks?.on_reuse, caseLevel.hooks?.on_reuse),
37115
- on_finish: mergeHook(suiteLevel.hooks?.on_finish, caseLevel.hooks?.on_finish)
37120
+ before_all: mergeHook(suiteLevel.hooks?.before_all, caseLevel.hooks?.before_all),
37121
+ before_each: mergeHook(suiteLevel.hooks?.before_each, caseLevel.hooks?.before_each),
37122
+ after_each: mergeHook(suiteLevel.hooks?.after_each, caseLevel.hooks?.after_each),
37123
+ after_all: mergeHook(suiteLevel.hooks?.after_all, caseLevel.hooks?.after_all)
37116
37124
  };
37117
37125
  const hasHooks = Object.values(mergedHooks).some((hook) => hook !== void 0);
37118
37126
  return {
@@ -39186,6 +39194,7 @@ var CopilotCliProvider = class {
39186
39194
  const agentProcess = spawn(executable, args, {
39187
39195
  stdio: ["pipe", "pipe", "inherit"]
39188
39196
  });
39197
+ await waitForProcessSpawn(agentProcess, executable, this.targetName);
39189
39198
  const toolCallsInProgress = /* @__PURE__ */ new Map();
39190
39199
  const completedToolCalls = [];
39191
39200
  let finalContent = "";
@@ -39465,6 +39474,47 @@ var CopilotCliProvider = class {
39465
39474
  }
39466
39475
  }
39467
39476
  };
39477
+ async function waitForProcessSpawn(proc, executable, targetName) {
39478
+ if (proc.pid) {
39479
+ return;
39480
+ }
39481
+ await new Promise((resolve2, reject) => {
39482
+ const onSpawn = () => {
39483
+ cleanup();
39484
+ resolve2();
39485
+ };
39486
+ const onError = (error40) => {
39487
+ cleanup();
39488
+ reject(new Error(formatCopilotSpawnError(error40, executable, targetName)));
39489
+ };
39490
+ const cleanup = () => {
39491
+ proc.off("spawn", onSpawn);
39492
+ proc.off("error", onError);
39493
+ };
39494
+ proc.once("spawn", onSpawn);
39495
+ proc.once("error", onError);
39496
+ });
39497
+ }
39498
+ function formatCopilotSpawnError(error40, executable, targetName) {
39499
+ const code = error40.code;
39500
+ const base = `Failed to start Copilot CLI executable '${executable}' for target '${targetName}'. ${error40.message}`;
39501
+ if (process.platform !== "win32") {
39502
+ return base;
39503
+ }
39504
+ if (code !== "ENOENT" && code !== "EINVAL") {
39505
+ return base;
39506
+ }
39507
+ return `${base}
39508
+
39509
+ On Windows, shell commands like 'copilot -h' can work via .ps1/.bat shims, but AgentV launches a subprocess that needs a directly spawnable executable path.
39510
+
39511
+ Fix options:
39512
+ 1) Install native Copilot binary package:
39513
+ npm install -g @github/copilot-win32-x64
39514
+ 2) Set explicit executable for Copilot targets:
39515
+ - In .env: COPILOT_EXE=C:\\Users\\<you>\\AppData\\Roaming\\npm\\node_modules\\@github\\copilot-win32-x64\\copilot.exe
39516
+ - In .agentv/targets.yaml: executable: \${{ COPILOT_EXE }}`;
39517
+ }
39468
39518
  function summarizeAcpEvent(eventType, data) {
39469
39519
  if (!data || typeof data !== "object") {
39470
39520
  return eventType;
@@ -47183,9 +47233,8 @@ async function runEvaluation(options) {
47183
47233
  const hasSharedWorkspace = !!(useStaticWorkspace || workspaceTemplate || suiteWorkspace?.hooks || suiteWorkspace?.repos?.length && !isPerTestIsolation);
47184
47234
  const poolEnabled = configuredMode === "pooled" ? true : configuredMode === "ephemeral" || useStaticWorkspace ? false : suiteWorkspace?.pool ?? poolWorkspaces ?? true;
47185
47235
  const usePool = poolEnabled !== false && !!suiteWorkspace?.repos?.length && !isPerTestIsolation && !useStaticWorkspace;
47186
- const finishCleanPolicy = suiteWorkspace?.hooks?.on_finish?.clean;
47187
- const resolvedRetainOnSuccess = (finishCleanPolicy === "always" || finishCleanPolicy === "on_success" ? "cleanup" : finishCleanPolicy === "on_failure" || finishCleanPolicy === "never" ? "keep" : void 0) ?? retainOnSuccess ?? (keepWorkspaces ? "keep" : "cleanup");
47188
- const resolvedRetainOnFailure = (finishCleanPolicy === "always" || finishCleanPolicy === "on_failure" ? "cleanup" : finishCleanPolicy === "on_success" || finishCleanPolicy === "never" ? "keep" : void 0) ?? retainOnFailure ?? (cleanupWorkspaces ? "cleanup" : "keep");
47236
+ const resolvedRetainOnSuccess = retainOnSuccess ?? (keepWorkspaces ? "keep" : "cleanup");
47237
+ const resolvedRetainOnFailure = retainOnFailure ?? (cleanupWorkspaces ? "cleanup" : "keep");
47189
47238
  const requestedWorkers = options.maxConcurrency ?? target.workers ?? 1;
47190
47239
  const workers = hasSharedWorkspace && !usePool ? 1 : requestedWorkers;
47191
47240
  setupLog(
@@ -47220,7 +47269,7 @@ async function runEvaluation(options) {
47220
47269
  repos: suiteWorkspace.repos,
47221
47270
  maxSlots: poolMaxSlots,
47222
47271
  repoManager: poolRepoManager,
47223
- poolReset: (workspaceClean === "full" ? "strict" : workspaceClean === "standard" ? "fast" : null) ?? suiteWorkspace.hooks?.on_reuse?.reset ?? "fast"
47272
+ poolReset: (workspaceClean === "full" ? "strict" : workspaceClean === "standard" ? "fast" : null) ?? "fast"
47224
47273
  });
47225
47274
  poolSlots.push(slot);
47226
47275
  setupLog(`pool slot ${i} acquired at: ${slot.path} (existing=${slot.isExisting})`);
@@ -47271,7 +47320,7 @@ async function runEvaluation(options) {
47271
47320
  throw new Error(`Failed to materialize repos: ${message}`);
47272
47321
  }
47273
47322
  }
47274
- const suiteBeforeAllHook = suiteWorkspace?.hooks?.before_all_tests;
47323
+ const suiteBeforeAllHook = suiteWorkspace?.hooks?.before_all;
47275
47324
  if (sharedWorkspacePath && hasHookCommand(suiteBeforeAllHook)) {
47276
47325
  const beforeAllHook = suiteBeforeAllHook;
47277
47326
  const beforeAllCommand = (beforeAllHook.command ?? beforeAllHook.script ?? []).join(" ");
@@ -47286,7 +47335,7 @@ async function runEvaluation(options) {
47286
47335
  };
47287
47336
  try {
47288
47337
  beforeAllOutput = await executeWorkspaceScript(
47289
- toScriptConfig(beforeAllHook, "before_all_tests", "suite workspace"),
47338
+ toScriptConfig(beforeAllHook, "before_all", "suite workspace"),
47290
47339
  scriptContext
47291
47340
  );
47292
47341
  setupLog("shared before_all completed");
@@ -47311,7 +47360,7 @@ async function runEvaluation(options) {
47311
47360
  };
47312
47361
  try {
47313
47362
  const output = await executeWorkspaceScript(
47314
- toScriptConfig(beforeAllHook, "before_all_tests", "suite workspace"),
47363
+ toScriptConfig(beforeAllHook, "before_all", "suite workspace"),
47315
47364
  scriptContext
47316
47365
  );
47317
47366
  if (!beforeAllOutput) beforeAllOutput = output;
@@ -47540,7 +47589,7 @@ async function runEvaluation(options) {
47540
47589
  }
47541
47590
  }
47542
47591
  const afterAllWorkspaces = poolSlots.length > 1 ? poolSlots.map((s) => s.path) : sharedWorkspacePath ? [sharedWorkspacePath] : [];
47543
- const suiteAfterAllHook = suiteWorkspace?.hooks?.after_all_tests;
47592
+ const suiteAfterAllHook = suiteWorkspace?.hooks?.after_all;
47544
47593
  if (afterAllWorkspaces.length > 0 && hasHookCommand(suiteAfterAllHook)) {
47545
47594
  const afterAllHook = suiteAfterAllHook;
47546
47595
  for (const wsPath of afterAllWorkspaces) {
@@ -47552,7 +47601,7 @@ async function runEvaluation(options) {
47552
47601
  };
47553
47602
  try {
47554
47603
  const afterAllOutput = await executeWorkspaceScript(
47555
- toScriptConfig(afterAllHook, "after_all_tests", "suite workspace"),
47604
+ toScriptConfig(afterAllHook, "after_all", "suite workspace"),
47556
47605
  scriptContext,
47557
47606
  "warn"
47558
47607
  );
@@ -47849,7 +47898,7 @@ async function runEvalCase(options) {
47849
47898
  );
47850
47899
  }
47851
47900
  }
47852
- const caseBeforeAllHook = evalCase.workspace?.hooks?.before_all_tests;
47901
+ const caseBeforeAllHook = evalCase.workspace?.hooks?.before_all;
47853
47902
  if (workspacePath && hasHookCommand(caseBeforeAllHook)) {
47854
47903
  const beforeAllHook = caseBeforeAllHook;
47855
47904
  const beforeAllCommand = (beforeAllHook.command ?? beforeAllHook.script ?? []).join(" ");
@@ -47868,7 +47917,7 @@ async function runEvalCase(options) {
47868
47917
  };
47869
47918
  try {
47870
47919
  beforeAllOutput = await executeWorkspaceScript(
47871
- toScriptConfig(beforeAllHook, "before_all_tests", `test '${evalCase.id}'`),
47920
+ toScriptConfig(beforeAllHook, "before_all", `test '${evalCase.id}'`),
47872
47921
  scriptContext
47873
47922
  );
47874
47923
  if (setupDebug) {
@@ -47893,7 +47942,7 @@ async function runEvalCase(options) {
47893
47942
  }
47894
47943
  }
47895
47944
  }
47896
- const caseBeforeEachHook = evalCase.workspace?.hooks?.before_each_test;
47945
+ const caseBeforeEachHook = evalCase.workspace?.hooks?.before_each;
47897
47946
  if (workspacePath && hasHookCommand(caseBeforeEachHook)) {
47898
47947
  const beforeEachHook = caseBeforeEachHook;
47899
47948
  const scriptContext = {
@@ -47906,7 +47955,7 @@ async function runEvalCase(options) {
47906
47955
  };
47907
47956
  try {
47908
47957
  beforeEachOutput = await executeWorkspaceScript(
47909
- toScriptConfig(beforeEachHook, "before_each_test", `test '${evalCase.id}'`),
47958
+ toScriptConfig(beforeEachHook, "before_each", `test '${evalCase.id}'`),
47910
47959
  scriptContext
47911
47960
  );
47912
47961
  } catch (error40) {
@@ -48023,17 +48072,17 @@ async function runEvalCase(options) {
48023
48072
  }
48024
48073
  }
48025
48074
  const providerError = extractProviderError(providerResponse);
48026
- if (repoManager && workspacePath && evalCase.workspace?.hooks?.after_each_test?.reset && evalCase.workspace.hooks.after_each_test.reset !== "none" && evalCase.workspace.repos) {
48075
+ if (repoManager && workspacePath && evalCase.workspace?.hooks?.after_each?.reset && evalCase.workspace.hooks.after_each.reset !== "none" && evalCase.workspace.repos) {
48027
48076
  try {
48028
48077
  await repoManager.reset(
48029
48078
  evalCase.workspace.repos,
48030
48079
  workspacePath,
48031
- evalCase.workspace.hooks.after_each_test.reset
48080
+ evalCase.workspace.hooks.after_each.reset
48032
48081
  );
48033
48082
  } catch {
48034
48083
  }
48035
48084
  }
48036
- const caseAfterEachHook = evalCase.workspace?.hooks?.after_each_test;
48085
+ const caseAfterEachHook = evalCase.workspace?.hooks?.after_each;
48037
48086
  if (workspacePath && hasHookCommand(caseAfterEachHook)) {
48038
48087
  const afterEachHook = caseAfterEachHook;
48039
48088
  const scriptContext = {
@@ -48046,7 +48095,7 @@ async function runEvalCase(options) {
48046
48095
  };
48047
48096
  try {
48048
48097
  afterEachOutput = await executeWorkspaceScript(
48049
- toScriptConfig(afterEachHook, "after_each_test", `test '${evalCase.id}'`),
48098
+ toScriptConfig(afterEachHook, "after_each", `test '${evalCase.id}'`),
48050
48099
  scriptContext,
48051
48100
  "warn"
48052
48101
  );
@@ -48446,9 +48495,11 @@ async function runEvaluatorList(options) {
48446
48495
  registry: typeRegistry
48447
48496
  };
48448
48497
  for (const evaluatorConfig of evaluators ?? []) {
48498
+ const startedAt = /* @__PURE__ */ new Date();
48449
48499
  try {
48450
48500
  const evaluatorInstance = await typeRegistry.create(evaluatorConfig, dispatchContext);
48451
48501
  const score2 = await evaluatorInstance.evaluate(evalContext);
48502
+ const endedAt = /* @__PURE__ */ new Date();
48452
48503
  const weight = evaluatorConfig.weight ?? 1;
48453
48504
  scored.push({
48454
48505
  score: score2,
@@ -48469,9 +48520,13 @@ async function runEvaluatorList(options) {
48469
48520
  evaluatorProviderRequest: score2.evaluatorRawRequest,
48470
48521
  details: score2.details,
48471
48522
  scores: mapChildResults(score2.scores),
48472
- tokenUsage: score2.tokenUsage
48523
+ tokenUsage: score2.tokenUsage,
48524
+ durationMs: endedAt.getTime() - startedAt.getTime(),
48525
+ startedAt: startedAt.toISOString(),
48526
+ endedAt: endedAt.toISOString()
48473
48527
  });
48474
48528
  } catch (error40) {
48529
+ const endedAt = /* @__PURE__ */ new Date();
48475
48530
  const message = error40 instanceof Error ? error40.message : String(error40);
48476
48531
  const fallbackScore = {
48477
48532
  score: 0,
@@ -48497,7 +48552,10 @@ async function runEvaluatorList(options) {
48497
48552
  verdict: "fail",
48498
48553
  hits: [],
48499
48554
  misses: [`Evaluator '${evaluatorConfig.name ?? "unknown"}' failed: ${message}`],
48500
- reasoning: message
48555
+ reasoning: message,
48556
+ durationMs: endedAt.getTime() - startedAt.getTime(),
48557
+ startedAt: startedAt.toISOString(),
48558
+ endedAt: endedAt.toISOString()
48501
48559
  });
48502
48560
  }
48503
48561
  if (evaluatorConfig.negate === true && scored.length > 0) {
@@ -49654,4 +49712,4 @@ export {
49654
49712
  OtelStreamingObserver,
49655
49713
  createAgentKernel
49656
49714
  };
49657
- //# sourceMappingURL=chunk-LZ5MPQFM.js.map
49715
+ //# sourceMappingURL=chunk-SO4O4O2B.js.map