agentv 4.43.0-next.1 → 5.0.0-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.
Files changed (53) hide show
  1. package/README.md +2 -2
  2. package/dist/{artifact-writer-STR7E5UO.js → artifact-writer-QD52FC56.js} +12 -10
  3. package/dist/{chunk-E2NL57MZ.js → chunk-6JVM4GJI.js} +3 -2
  4. package/dist/chunk-6JVM4GJI.js.map +1 -0
  5. package/dist/{chunk-IFQXBQSY.js → chunk-6Q56CEXV.js} +333 -99
  6. package/dist/chunk-6Q56CEXV.js.map +1 -0
  7. package/dist/{chunk-RFJM2UBD.js → chunk-GZJMODLW.js} +1067 -669
  8. package/dist/chunk-GZJMODLW.js.map +1 -0
  9. package/dist/{chunk-ROLNQBYU.js → chunk-IBI7A5RP.js} +621 -191
  10. package/dist/chunk-IBI7A5RP.js.map +1 -0
  11. package/dist/{chunk-NPVGBFF6.js → chunk-IJEZFZJR.js} +2 -43
  12. package/dist/chunk-IJEZFZJR.js.map +1 -0
  13. package/dist/{chunk-BPGJ4HBU.js → chunk-RCIEHFQ2.js} +3 -3
  14. package/dist/{chunk-5NDSGGMJ.js → chunk-UG4JHZYM.js} +1176 -224
  15. package/dist/chunk-UG4JHZYM.js.map +1 -0
  16. package/dist/cli.js +7 -7
  17. package/dist/dashboard/assets/index-BVMrdN8a.js +119 -0
  18. package/dist/dashboard/assets/{index-DitffAxS.js → index-D5_8DE_B.js} +1 -1
  19. package/dist/dashboard/assets/index-DZWXfWsv.css +1 -0
  20. package/dist/dashboard/index.html +2 -2
  21. package/dist/{dist-FTTL5IOY.js → dist-KJ6PELQY.js} +45 -11
  22. package/dist/{docker-workspace-RPPXBT27-B4AQHVWA.js → docker-workspace-ZJ2ESVBI-6UDETQII.js} +2 -2
  23. package/dist/{exec-AR6JUUN5-6MBPURPR.js → exec-MYPAJJP7-C5HD5WG5.js} +2 -2
  24. package/dist/index.js +7 -7
  25. package/dist/{interactive-RE4DXH4A.js → interactive-2WMVAASS.js} +7 -7
  26. package/dist/skills/agentv-bench/SKILL.md +3 -3
  27. package/dist/skills/agentv-bench/agents/analyzer.md +1 -1
  28. package/dist/skills/agentv-bench/references/autoresearch.md +1 -1
  29. package/dist/skills/agentv-bench/references/eval-yaml-spec.md +13 -3
  30. package/dist/skills/agentv-bench/references/migrating-from-skill-creator.md +2 -2
  31. package/dist/skills/agentv-bench/references/schemas.md +6 -6
  32. package/dist/skills/agentv-bench/references/subagent-pipeline.md +1 -1
  33. package/dist/skills/agentv-eval-writer/SKILL.md +11 -1
  34. package/dist/skills/agentv-eval-writer/references/config-schema.json +16 -0
  35. package/dist/skills/agentv-eval-writer/references/eval-schema.json +3 -63
  36. package/dist/skills/agentv-eval-writer/references/experiment-schema.json +278 -0
  37. package/dist/{ts-eval-loader-HQDMXQQV-LBW3N3W6.js → ts-eval-loader-RE43OAGX-AMRCUKBZ.js} +3 -3
  38. package/package.json +1 -1
  39. package/dist/chunk-5NDSGGMJ.js.map +0 -1
  40. package/dist/chunk-E2NL57MZ.js.map +0 -1
  41. package/dist/chunk-IFQXBQSY.js.map +0 -1
  42. package/dist/chunk-NPVGBFF6.js.map +0 -1
  43. package/dist/chunk-RFJM2UBD.js.map +0 -1
  44. package/dist/chunk-ROLNQBYU.js.map +0 -1
  45. package/dist/dashboard/assets/index-1Hvy8sBy.js +0 -119
  46. package/dist/dashboard/assets/index-J5sPcQO3.css +0 -1
  47. /package/dist/{artifact-writer-STR7E5UO.js.map → artifact-writer-QD52FC56.js.map} +0 -0
  48. /package/dist/{chunk-BPGJ4HBU.js.map → chunk-RCIEHFQ2.js.map} +0 -0
  49. /package/dist/{dist-FTTL5IOY.js.map → dist-KJ6PELQY.js.map} +0 -0
  50. /package/dist/{docker-workspace-RPPXBT27-B4AQHVWA.js.map → docker-workspace-ZJ2ESVBI-6UDETQII.js.map} +0 -0
  51. /package/dist/{exec-AR6JUUN5-6MBPURPR.js.map → exec-MYPAJJP7-C5HD5WG5.js.map} +0 -0
  52. /package/dist/{interactive-RE4DXH4A.js.map → interactive-2WMVAASS.js.map} +0 -0
  53. /package/dist/{ts-eval-loader-HQDMXQQV-LBW3N3W6.js.map → ts-eval-loader-RE43OAGX-AMRCUKBZ.js.map} +0 -0
@@ -9,6 +9,7 @@ import {
9
9
  buildDefaultRunDirFromName,
10
10
  c,
11
11
  clearRemoteRunTags,
12
+ confirmRemoteResultsMerge,
12
13
  createRunDirName,
13
14
  detectFileType,
14
15
  discoverEvalFiles,
@@ -64,12 +65,12 @@ import {
64
65
  validateTargetsFile,
65
66
  validateWorkspacePaths,
66
67
  writeRunTags
67
- } from "./chunk-ROLNQBYU.js";
68
+ } from "./chunk-IBI7A5RP.js";
68
69
  import {
69
70
  materializeEvalBundle,
70
71
  toSnakeCaseDeep as toSnakeCaseDeep2,
71
72
  writeArtifactsFromResults as writeArtifactsFromResults2
72
- } from "./chunk-E2NL57MZ.js";
73
+ } from "./chunk-6JVM4GJI.js";
73
74
  import {
74
75
  DEFAULT_CATEGORY,
75
76
  deriveCategory,
@@ -86,17 +87,16 @@ import {
86
87
  syncProjects,
87
88
  transpileEvalYamlFile,
88
89
  trimBaselineResult
89
- } from "./chunk-5NDSGGMJ.js";
90
+ } from "./chunk-UG4JHZYM.js";
90
91
  import {
91
92
  AGENTV_RESULTS_ARTIFACTS_REF,
92
93
  DEFAULT_THRESHOLD,
93
94
  EXECUTION_TRACE_SCHEMA_VERSION,
94
95
  addProject,
95
96
  aggregateRunDir,
96
- buildBenchmarkArtifact,
97
97
  buildResultIndexArtifact,
98
+ buildRunSummaryArtifact,
98
99
  buildTestTargetKey,
99
- buildTimingArtifact,
100
100
  buildTraceEnvelopeFromEvaluationResult,
101
101
  buildTraceFromMessages,
102
102
  createBuiltinRegistry,
@@ -105,6 +105,7 @@ import {
105
105
  externalTraceMetadataFromRecord,
106
106
  external_exports,
107
107
  getAgentvConfigDir,
108
+ getLocalConfigPath,
108
109
  getProject,
109
110
  getWorkspacePoolRoot,
110
111
  gradePreparedEvalCase,
@@ -113,6 +114,7 @@ import {
113
114
  loadConfig,
114
115
  loadProjectRegistry,
115
116
  loadTestSuite,
117
+ mergeConfigObjects,
116
118
  normalizeLineEndings,
117
119
  normalizeResultRow,
118
120
  omitExternalTraceMetadataKeys,
@@ -145,7 +147,7 @@ import {
145
147
  traceEnvelopeToTranscriptMessages,
146
148
  traceFromTranscriptJsonLines,
147
149
  writeArtifactsFromResults
148
- } from "./chunk-RFJM2UBD.js";
150
+ } from "./chunk-GZJMODLW.js";
149
151
  import {
150
152
  __commonJS,
151
153
  __require,
@@ -4258,7 +4260,7 @@ var doctorCommand = command({
4258
4260
  import path5 from "node:path";
4259
4261
  var evalAggregateCommand = command({
4260
4262
  name: "aggregate",
4261
- description: "Recompute benchmark.json and timing.json from a run directory. Deduplicates by (test_id, target), keeping the last entry.",
4263
+ description: "Recompute summary.json from a run directory. Deduplicates by (test_id, target), keeping the last entry.",
4262
4264
  args: {
4263
4265
  runDir: positional({
4264
4266
  type: string,
@@ -4268,10 +4270,9 @@ var evalAggregateCommand = command({
4268
4270
  },
4269
4271
  handler: async (args) => {
4270
4272
  const runDir = path5.resolve(args.runDir);
4271
- const { benchmarkPath, timingPath, testCount, targetCount } = await aggregateRunDir(runDir);
4273
+ const { summaryPath, testCount, targetCount } = await aggregateRunDir(runDir);
4272
4274
  console.log(`Aggregated ${testCount} test result(s) across ${targetCount} target(s)`);
4273
- console.log(` Benchmark: ${benchmarkPath}`);
4274
- console.log(` Timing: ${timingPath}`);
4275
+ console.log(` Summary: ${summaryPath}`);
4275
4276
  }
4276
4277
  });
4277
4278
 
@@ -4629,7 +4630,7 @@ var evalRunCommand = command({
4629
4630
  type: optional(string),
4630
4631
  long: "output",
4631
4632
  short: "o",
4632
- description: "Run artifact directory (writes index.jsonl, benchmark.json, timing, and per-test artifacts)"
4633
+ description: "Run artifact directory (writes index.jsonl, summary.json, and per-case artifacts)"
4633
4634
  }),
4634
4635
  outputFormat: option({
4635
4636
  type: optional(string),
@@ -4827,12 +4828,6 @@ var evalRunCommand = command({
4827
4828
  })
4828
4829
  },
4829
4830
  handler: async (args) => {
4830
- if (args.evalPaths.length === 0 && process.stdin.isTTY) {
4831
- const { launchInteractiveWizard } = await import("./interactive-RE4DXH4A.js");
4832
- await launchInteractiveWizard();
4833
- return;
4834
- }
4835
- const resolvedPaths = await resolveEvalPaths(args.evalPaths, process.cwd());
4836
4831
  if (args.budgetUsd !== void 0 && args.budgetUsd <= 0) {
4837
4832
  console.error("Error: --budget-usd must be a positive number.");
4838
4833
  process.exit(2);
@@ -4891,7 +4886,7 @@ var evalRunCommand = command({
4891
4886
  recordReplay: args.recordReplay,
4892
4887
  recordReplayVariant: args.recordReplayVariant
4893
4888
  };
4894
- const result = await runEvalCommand({ testFiles: resolvedPaths, rawOptions });
4889
+ const result = await runEvalCommand({ testFiles: args.evalPaths, rawOptions });
4895
4890
  if (result?.allExecutionErrors) {
4896
4891
  process.exit(2);
4897
4892
  }
@@ -9089,7 +9084,6 @@ var evalBenchCommand = command({
9089
9084
  const grading = {
9090
9085
  assertions: allAssertions,
9091
9086
  summary: { passed, failed, total: allAssertions.length, pass_rate: passRate },
9092
- execution_metrics: { tool_calls: {}, total_tool_calls: 0, errors_encountered: 0 },
9093
9087
  graders: evaluators.map((e) => ({
9094
9088
  name: e.name,
9095
9089
  type: e.type,
@@ -9151,7 +9145,7 @@ var evalBenchCommand = command({
9151
9145
  "utf8"
9152
9146
  );
9153
9147
  const passRateStats = computeStats(allPassRates);
9154
- const benchmark = {
9148
+ const summary = {
9155
9149
  metadata: {
9156
9150
  eval_file: manifest.eval_file,
9157
9151
  timestamp: manifest.timestamp,
@@ -9166,11 +9160,24 @@ var evalBenchCommand = command({
9166
9160
  tokens: { mean: 0, stddev: 0 }
9167
9161
  }
9168
9162
  },
9163
+ timing: {
9164
+ total_tokens: 0,
9165
+ duration_ms: 0,
9166
+ total_duration_seconds: 0,
9167
+ cost_usd: null,
9168
+ token_usage: { input: 0, output: 0, reasoning: 0 },
9169
+ usage_sources: {
9170
+ token_usage: "unavailable",
9171
+ total_tokens: "unavailable",
9172
+ duration: "unavailable",
9173
+ cost: "unavailable"
9174
+ }
9175
+ },
9169
9176
  notes: []
9170
9177
  };
9171
9178
  await writeFile7(
9172
- join(exportDir, "benchmark.json"),
9173
- `${JSON.stringify(benchmark, null, 2)}
9179
+ join(exportDir, "summary.json"),
9180
+ `${JSON.stringify(summary, null, 2)}
9174
9181
  `,
9175
9182
  "utf8"
9176
9183
  );
@@ -10359,10 +10366,10 @@ function parseJsonlLine(line) {
10359
10366
  function readManifestRecords(manifestPath) {
10360
10367
  return readFileSync8(manifestPath, "utf8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map(parseJsonlLine);
10361
10368
  }
10362
- function readBenchmarkMetadata(manifestPath) {
10369
+ function readSummaryMetadata(manifestPath) {
10363
10370
  try {
10364
- const benchmarkPath = path19.join(path19.dirname(manifestPath), "benchmark.json");
10365
- const parsed = JSON.parse(readFileSync8(benchmarkPath, "utf8"));
10371
+ const summaryPath = path19.join(path19.dirname(manifestPath), "summary.json");
10372
+ const parsed = JSON.parse(readFileSync8(summaryPath, "utf8"));
10366
10373
  return {
10367
10374
  timestamp: parsed.metadata?.timestamp,
10368
10375
  displayName: parsed.metadata?.display_name
@@ -10388,7 +10395,7 @@ function loadSources(sources) {
10388
10395
  if (records.length !== results.length) {
10389
10396
  throw new Error(`Manifest could not be hydrated completely: ${manifestPath}`);
10390
10397
  }
10391
- const metadata = readBenchmarkMetadata(manifestPath);
10398
+ const metadata = readSummaryMetadata(manifestPath);
10392
10399
  return {
10393
10400
  ...source,
10394
10401
  index,
@@ -10529,6 +10536,7 @@ function resolveCombinedExperiment(sources, requestedExperiment) {
10529
10536
  }
10530
10537
  var MANIFEST_PATH_FIELDS = [
10531
10538
  "artifact_dir",
10539
+ "summary_path",
10532
10540
  "grading_path",
10533
10541
  "timing_path",
10534
10542
  "input_path",
@@ -10705,15 +10713,12 @@ function combineRunSources(options) {
10705
10713
  const records = rows.map((row) => rewriteAndCopyRecord(row, runDir, experiment));
10706
10714
  const manifestPath = path19.join(runDir, "index.jsonl");
10707
10715
  writeJsonl(manifestPath, records);
10708
- const timing = buildTimingArtifact(results);
10709
- const timingPath = path19.join(runDir, "timing.json");
10710
- writeJson3(timingPath, timing);
10711
- const benchmark = buildBenchmarkArtifact(results, "", "combined", results.length);
10712
- const benchmarkWithMetadata = {
10713
- ...benchmark,
10716
+ const summary = buildRunSummaryArtifact(results, "", "combined", results.length);
10717
+ const summaryWithMetadata = {
10718
+ ...summary,
10714
10719
  metadata: {
10715
- ...benchmark.metadata,
10716
- timestamp: startedAt ?? benchmark.metadata.timestamp,
10720
+ ...summary.metadata,
10721
+ timestamp: startedAt ?? summary.metadata.timestamp,
10717
10722
  display_name: displayName,
10718
10723
  experiment,
10719
10724
  combined_from_run_ids: loadedSources.map((source) => source.id),
@@ -10721,15 +10726,14 @@ function combineRunSources(options) {
10721
10726
  duplicate_policy: options.duplicatePolicy
10722
10727
  }
10723
10728
  };
10724
- const benchmarkPath = path19.join(runDir, "benchmark.json");
10725
- writeJson3(benchmarkPath, benchmarkWithMetadata);
10729
+ const summaryPath = path19.join(runDir, "summary.json");
10730
+ writeJson3(summaryPath, summaryWithMetadata);
10726
10731
  const tags = [...new Set(loadedSources.flatMap((source) => source.tags ?? []))].sort();
10727
10732
  return {
10728
10733
  runDir,
10729
10734
  runId: toRunId(options.cwd, runDir),
10730
10735
  manifestPath,
10731
- benchmarkPath,
10732
- timingPath,
10736
+ summaryPath,
10733
10737
  displayName,
10734
10738
  experiment,
10735
10739
  combinedFromRunIds: loadedSources.map((source) => source.id),
@@ -10819,7 +10823,7 @@ var resultsCombineCommand = command({
10819
10823
  displayName: option({
10820
10824
  type: optional(string),
10821
10825
  long: "display-name",
10822
- description: "Display name stored in benchmark.json metadata"
10826
+ description: "Display name stored in summary.json metadata"
10823
10827
  }),
10824
10828
  duplicatePolicy: option({
10825
10829
  type: optional(oneOf(["prompt", "error", "latest"])),
@@ -10871,8 +10875,7 @@ var resultsCombineCommand = command({
10871
10875
  });
10872
10876
  console.log(`Combined ${result.testCount} result row(s) into ${result.runDir}`);
10873
10877
  console.log(` Run ID: ${result.runId}`);
10874
- console.log(` Benchmark: ${result.benchmarkPath}`);
10875
- console.log(` Timing: ${result.timingPath}`);
10878
+ console.log(` Summary: ${result.summaryPath}`);
10876
10879
  if (result.duplicateConflicts.length > 0) {
10877
10880
  console.log(` Duplicates handled: ${result.duplicateConflicts.length}`);
10878
10881
  }
@@ -11028,11 +11031,11 @@ function artifactRefs(indexEntry, options) {
11028
11031
  return dropUndefined({
11029
11032
  ...metadataRefs,
11030
11033
  artifact_dir: indexEntry.artifact_dir,
11034
+ summary_path: indexEntry.summary_path,
11031
11035
  grading_path: indexEntry.grading_path,
11032
11036
  input_path: indexEntry.input_path,
11033
11037
  output_path: indexEntry.output_path,
11034
11038
  answer_path: indexEntry.answer_path,
11035
- response_path: indexEntry.response_path,
11036
11039
  transcript_path: indexEntry.transcript_path,
11037
11040
  metrics_path: indexEntry.metrics_path,
11038
11041
  trace_path: tracePathFor(indexEntry),
@@ -11109,8 +11112,7 @@ function buildEntry(result, options, indexRecord) {
11109
11112
  source: { kind: "agentv_run", path: sourcePath, format: "agentv_result" },
11110
11113
  artifacts: {
11111
11114
  trace_path: tracePathFor(indexRecord ?? plannedIndexEntry),
11112
- answer_path: result.output.length > 0 ? "outputs/answer.md" : void 0,
11113
- response_path: result.output.length > 0 ? "outputs/response.md" : void 0
11115
+ answer_path: result.output.length > 0 ? "outputs/answer.md" : void 0
11114
11116
  },
11115
11117
  duplicatePolicy: options.duplicatePolicy,
11116
11118
  capture: captureOptions(includeRawContent),
@@ -13092,14 +13094,14 @@ function normalizeEvalFileLabel(value) {
13092
13094
  }
13093
13095
  return path23.basename(trimmed).replace(/\.results\.jsonl$/i, "").replace(/\.eval\.ya?ml$/i, "").replace(/\.ya?ml$/i, "").replace(/\.jsonl$/i, "");
13094
13096
  }
13095
- function readBenchmarkEvalFile(sourceFile) {
13096
- const benchmarkPath = path23.join(path23.dirname(sourceFile), "benchmark.json");
13097
- if (!existsSync11(benchmarkPath)) {
13097
+ function readSummaryEvalFile(sourceFile) {
13098
+ const summaryPath = path23.join(path23.dirname(sourceFile), "summary.json");
13099
+ if (!existsSync11(summaryPath)) {
13098
13100
  return void 0;
13099
13101
  }
13100
13102
  try {
13101
- const benchmark = JSON.parse(readFileSync10(benchmarkPath, "utf8"));
13102
- return normalizeEvalFileLabel(benchmark.metadata?.eval_file);
13103
+ const summary = JSON.parse(readFileSync10(summaryPath, "utf8"));
13104
+ return normalizeEvalFileLabel(summary.metadata?.eval_file);
13103
13105
  } catch {
13104
13106
  return void 0;
13105
13107
  }
@@ -13107,8 +13109,8 @@ function readBenchmarkEvalFile(sourceFile) {
13107
13109
  function deriveReportPath(sourceFile) {
13108
13110
  return path23.join(path23.dirname(sourceFile), "report.html");
13109
13111
  }
13110
- function serializeReportResult(result, sourceFile, manifestRecord, benchmarkEvalFile) {
13111
- const fallbackEvalFile = normalizeEvalFileLabel(manifestRecord?.eval_file) ?? benchmarkEvalFile ?? normalizeEvalFileLabel(result.suite) ?? path23.basename(path23.dirname(sourceFile));
13112
+ function serializeReportResult(result, sourceFile, manifestRecord, summaryEvalFile) {
13113
+ const fallbackEvalFile = normalizeEvalFileLabel(manifestRecord?.eval_file) ?? summaryEvalFile ?? normalizeEvalFileLabel(result.suite) ?? path23.basename(path23.dirname(sourceFile));
13112
13114
  return {
13113
13115
  timestamp: result.timestamp,
13114
13116
  test_id: result.testId,
@@ -13141,23 +13143,23 @@ async function loadReportSource(source, cwd) {
13141
13143
  sourceFile: resolvedSourceFile,
13142
13144
  results,
13143
13145
  records,
13144
- benchmarkEvalFile: readBenchmarkEvalFile(resolvedSourceFile)
13146
+ summaryEvalFile: readSummaryEvalFile(resolvedSourceFile)
13145
13147
  };
13146
13148
  }
13147
- function renderResultsReport(results, sourceFile, records, benchmarkEvalFile) {
13149
+ function renderResultsReport(results, sourceFile, records, summaryEvalFile) {
13148
13150
  if (!RESULTS_REPORT_TEMPLATE.includes("__DATA_PLACEHOLDER__")) {
13149
13151
  throw new Error("Report template is missing __DATA_PLACEHOLDER__");
13150
13152
  }
13151
13153
  const rows = results.map(
13152
- (result, index) => serializeReportResult(result, sourceFile, records[index], benchmarkEvalFile)
13154
+ (result, index) => serializeReportResult(result, sourceFile, records[index], summaryEvalFile)
13153
13155
  );
13154
13156
  const dataJson = JSON.stringify(rows).replace(/<\//g, "<\\/");
13155
13157
  return RESULTS_REPORT_TEMPLATE.replace("__DATA_PLACEHOLDER__", () => dataJson);
13156
13158
  }
13157
13159
  async function writeResultsReport(source, outputPath, cwd) {
13158
- const { sourceFile, results, records, benchmarkEvalFile } = await loadReportSource(source, cwd);
13160
+ const { sourceFile, results, records, summaryEvalFile } = await loadReportSource(source, cwd);
13159
13161
  const resolvedOutputPath = outputPath ? path23.isAbsolute(outputPath) ? outputPath : path23.resolve(cwd, outputPath) : deriveReportPath(sourceFile);
13160
- const html = renderResultsReport(results, sourceFile, records, benchmarkEvalFile);
13162
+ const html = renderResultsReport(results, sourceFile, records, summaryEvalFile);
13161
13163
  mkdirSync3(path23.dirname(resolvedOutputPath), { recursive: true });
13162
13164
  writeFileSync4(resolvedOutputPath, html, "utf8");
13163
13165
  const written = readFileSync10(resolvedOutputPath, "utf8");
@@ -13423,10 +13425,10 @@ function checkIndexJsonl(runDir) {
13423
13425
  message: `index.jsonl line ${i + 1} (${entry.test_id ?? "?"}): missing 'target'`
13424
13426
  });
13425
13427
  }
13426
- if (!entry.grading_path) {
13428
+ if (!entry.summary_path) {
13427
13429
  diagnostics.push({
13428
- severity: "warning",
13429
- message: `index.jsonl line ${i + 1} (${entry.test_id ?? "?"}): missing 'grading_path'`
13430
+ severity: "error",
13431
+ message: `index.jsonl line ${i + 1} (${entry.test_id ?? "?"}): missing 'summary_path'`
13430
13432
  });
13431
13433
  }
13432
13434
  if (!entry.scores || !Array.isArray(entry.scores) || entry.scores.length === 0) {
@@ -13481,6 +13483,35 @@ function checkArtifactFiles(runDir, entries2) {
13481
13483
  const diagnostics = [];
13482
13484
  for (const entry of entries2) {
13483
13485
  const testId = entry.test_id ?? "?";
13486
+ if (entry.summary_path) {
13487
+ const summaryPath2 = path24.join(runDir, entry.summary_path);
13488
+ if (!existsSync13(summaryPath2)) {
13489
+ diagnostics.push({
13490
+ severity: "error",
13491
+ message: `${testId}: summary.json not found at '${entry.summary_path}'`
13492
+ });
13493
+ }
13494
+ }
13495
+ for (const trial of entry.trials ?? []) {
13496
+ if (!entry.artifact_dir || !trial.run_path) {
13497
+ continue;
13498
+ }
13499
+ const runDirPath = path24.join(runDir, entry.artifact_dir, trial.run_path);
13500
+ const resultPath = path24.join(runDirPath, "result.json");
13501
+ const gradingPath = path24.join(runDirPath, "grading.json");
13502
+ if (!existsSync13(resultPath)) {
13503
+ diagnostics.push({
13504
+ severity: "error",
13505
+ message: `${testId}: result.json not found at '${path24.posix.join(entry.artifact_dir, trial.run_path, "result.json")}'`
13506
+ });
13507
+ }
13508
+ if (!existsSync13(gradingPath)) {
13509
+ diagnostics.push({
13510
+ severity: "error",
13511
+ message: `${testId}: grading.json not found at '${path24.posix.join(entry.artifact_dir, trial.run_path, "grading.json")}'`
13512
+ });
13513
+ }
13514
+ }
13484
13515
  if (entry.grading_path) {
13485
13516
  const gradingPath = path24.join(runDir, entry.grading_path);
13486
13517
  if (!existsSync13(gradingPath)) {
@@ -13521,9 +13552,9 @@ function checkArtifactFiles(runDir, entries2) {
13521
13552
  }
13522
13553
  }
13523
13554
  }
13524
- const benchmarkPath = path24.join(runDir, "benchmark.json");
13525
- if (!existsSync13(benchmarkPath)) {
13526
- diagnostics.push({ severity: "warning", message: "benchmark.json is missing" });
13555
+ const summaryPath = path24.join(runDir, "summary.json");
13556
+ if (!existsSync13(summaryPath)) {
13557
+ diagnostics.push({ severity: "error", message: "summary.json is missing" });
13527
13558
  }
13528
13559
  return diagnostics;
13529
13560
  }
@@ -14167,8 +14198,8 @@ var DEFAULTS = {
14167
14198
  function loadStudioConfig(agentvDir) {
14168
14199
  const localConfigPath = path26.join(agentvDir, "config.yaml");
14169
14200
  const globalConfigPath = path26.join(getAgentvConfigDir(), "config.yaml");
14170
- const localConfig = loadParsedConfig(localConfigPath);
14171
- const globalConfig = path26.resolve(globalConfigPath) === path26.resolve(localConfigPath) ? void 0 : loadParsedConfig(globalConfigPath);
14201
+ const localConfig = loadParsedConfigPair(localConfigPath);
14202
+ const globalConfig = path26.resolve(path26.dirname(globalConfigPath)) === path26.resolve(path26.dirname(localConfigPath)) ? void 0 : loadParsedConfigPair(globalConfigPath);
14172
14203
  const threshold = [
14173
14204
  readThreshold(localConfig?.dashboard),
14174
14205
  readThreshold(localConfig?.studio),
@@ -14190,6 +14221,12 @@ function loadParsedConfig(configPath) {
14190
14221
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
14191
14222
  return parsed;
14192
14223
  }
14224
+ function loadParsedConfigPair(configPath) {
14225
+ const base = loadParsedConfig(configPath);
14226
+ const local = loadParsedConfig(getLocalConfigPath(configPath));
14227
+ if (base && local) return mergeConfigObjects(base, local);
14228
+ return local ?? base;
14229
+ }
14193
14230
  function readThreshold(section) {
14194
14231
  if (!section || typeof section !== "object" || Array.isArray(section)) return void 0;
14195
14232
  const values = section;
@@ -14350,21 +14387,25 @@ function flattenFileTree(nodes) {
14350
14387
  }
14351
14388
  return files;
14352
14389
  }
14353
- function ensureCatalogFileNode(root, entry) {
14354
- const segments = entry.displayPath.split("/").filter(Boolean);
14390
+ function ensureCatalogFileNode(root, entry, rootPrefix) {
14391
+ const fullPath = entry.displayPath;
14392
+ const nestPath = rootPrefix && fullPath.startsWith(`${rootPrefix}/`) ? fullPath.slice(rootPrefix.length + 1) : fullPath;
14393
+ const usePrefix = nestPath !== fullPath ? rootPrefix : void 0;
14394
+ const segments = nestPath.split("/").filter(Boolean);
14355
14395
  if (segments.length === 0) return;
14356
14396
  let siblings = root;
14357
- let currentPath = "";
14397
+ let nestedPath = "";
14358
14398
  for (let i = 0; i < segments.length; i += 1) {
14359
14399
  const segment = segments[i];
14360
14400
  if (!segment) continue;
14361
- currentPath = currentPath ? `${currentPath}/${segment}` : segment;
14401
+ nestedPath = nestedPath ? `${nestedPath}/${segment}` : segment;
14402
+ const fullNodePath = usePrefix ? `${usePrefix}/${nestedPath}` : nestedPath;
14362
14403
  const isFile = i === segments.length - 1;
14363
14404
  let node = siblings.find((candidate) => candidate.name === segment);
14364
14405
  if (!node) {
14365
14406
  node = {
14366
14407
  name: segment,
14367
- path: currentPath,
14408
+ path: fullNodePath,
14368
14409
  type: isFile ? "file" : "dir",
14369
14410
  ...isFile ? {
14370
14411
  kind: entry.kind,
@@ -14394,6 +14435,15 @@ function ensureCatalogFileNode(root, entry) {
14394
14435
  siblings = node.children;
14395
14436
  }
14396
14437
  }
14438
+ function overlayCatalogFileNodes(files, catalog, rootPrefix) {
14439
+ const localFilePaths = new Set(flattenFileTree(files).map((file) => file.path));
14440
+ for (const entry of catalog) {
14441
+ if (entry.storage === "git" || !localFilePaths.has(entry.displayPath)) {
14442
+ ensureCatalogFileNode(files, entry, rootPrefix);
14443
+ }
14444
+ }
14445
+ return files;
14446
+ }
14397
14447
  function inferLanguage(filePath) {
14398
14448
  const ext = path27.extname(filePath).toLowerCase();
14399
14449
  const langMap = {
@@ -14564,6 +14614,28 @@ function normalizeArtifactRelativePath(relativePath) {
14564
14614
  }
14565
14615
  return segments.join("/");
14566
14616
  }
14617
+ function requestedArtifactDir(c4) {
14618
+ const raw = c4.req.query("artifact_dir")?.trim();
14619
+ if (!raw) {
14620
+ return {};
14621
+ }
14622
+ const normalized = normalizeArtifactRelativePath(raw);
14623
+ if (!normalized) {
14624
+ return { error: "Invalid artifact_dir" };
14625
+ }
14626
+ return { value: normalized };
14627
+ }
14628
+ function manifestRecordSelection(records, evalId, artifactDir) {
14629
+ return records.map((record, index) => ({ record, index })).find(({ record }) => {
14630
+ if (record.test_id !== evalId) {
14631
+ return false;
14632
+ }
14633
+ if (!artifactDir) {
14634
+ return true;
14635
+ }
14636
+ return normalizeArtifactRelativePath(record.artifact_dir ?? "") === artifactDir;
14637
+ });
14638
+ }
14567
14639
  function relativeRunPathFromNormalizedManifestPath(manifestPath) {
14568
14640
  const parts = manifestPath.split("/").filter(Boolean);
14569
14641
  const runsIndex = parts.lastIndexOf("runs");
@@ -14656,6 +14728,39 @@ function displayPathFromArtifactKey(key, runPath) {
14656
14728
  if (!normalizedKey.startsWith(runPrefix)) return normalizedKey;
14657
14729
  return normalizeArtifactRelativePath(normalizedKey.slice(runPrefix.length)) ?? normalizedKey;
14658
14730
  }
14731
+ function addTrialRunCatalogEntries(entries2, seen, record) {
14732
+ const artifactDir = record.artifact_dir ? normalizeArtifactRelativePath(record.artifact_dir) : void 0;
14733
+ if (!artifactDir) return;
14734
+ for (const trial of record.trials ?? []) {
14735
+ const runPath = trial.run_path ? normalizeArtifactRelativePath(trial.run_path) : void 0;
14736
+ if (!runPath) continue;
14737
+ const runDir = path27.posix.join(artifactDir, runPath);
14738
+ addDirectArtifactCatalogEntry(
14739
+ entries2,
14740
+ seen,
14741
+ path27.posix.join(runDir, "result.json"),
14742
+ "artifact"
14743
+ );
14744
+ addDirectArtifactCatalogEntry(
14745
+ entries2,
14746
+ seen,
14747
+ path27.posix.join(runDir, "grading.json"),
14748
+ "artifact"
14749
+ );
14750
+ addDirectArtifactCatalogEntry(
14751
+ entries2,
14752
+ seen,
14753
+ path27.posix.join(runDir, "metrics.json"),
14754
+ "artifact"
14755
+ );
14756
+ addDirectArtifactCatalogEntry(
14757
+ entries2,
14758
+ seen,
14759
+ path27.posix.join(runDir, "timing.json"),
14760
+ "artifact"
14761
+ );
14762
+ }
14763
+ }
14659
14764
  function buildResultArtifactCatalog(record, options) {
14660
14765
  const entries2 = [];
14661
14766
  const seen = /* @__PURE__ */ new Set();
@@ -14666,6 +14771,7 @@ function buildResultArtifactCatalog(record, options) {
14666
14771
  addPointerArtifactCatalogEntry(entries2, seen, transcript, "transcript", options?.runPath);
14667
14772
  addPointerArtifactCatalogEntry(entries2, seen, trace, "trace", options?.runPath);
14668
14773
  addPointerArtifactCatalogEntry(entries2, seen, answer, "answer", options?.runPath);
14774
+ addDirectArtifactCatalogEntry(entries2, seen, record.summary_path, "artifact");
14669
14775
  addDirectArtifactCatalogEntry(entries2, seen, record.grading_path, "artifact");
14670
14776
  addDirectArtifactCatalogEntry(entries2, seen, record.timing_path, "artifact");
14671
14777
  addDirectArtifactCatalogEntry(entries2, seen, record.input_path, "artifact");
@@ -14676,6 +14782,7 @@ function buildResultArtifactCatalog(record, options) {
14676
14782
  addDirectArtifactCatalogEntry(entries2, seen, recordWithTrace.trace_path, "trace");
14677
14783
  addDirectArtifactCatalogEntry(entries2, seen, record.eval_path, "artifact");
14678
14784
  addDirectArtifactCatalogEntry(entries2, seen, record.targets_path, "artifact");
14785
+ addTrialRunCatalogEntries(entries2, seen, record);
14679
14786
  return entries2;
14680
14787
  }
14681
14788
  function resultArtifactTreeRootPaths(record, catalog) {
@@ -14686,16 +14793,25 @@ function resultArtifactTreeRootPaths(record, catalog) {
14686
14793
  record.graders_path
14687
14794
  ].filter((p, index, all) => !!p && all.indexOf(p) === index);
14688
14795
  }
14689
- function buildLocalResultArtifactTree(baseDir, record, catalog) {
14796
+ function artifactTreeCommonDir(record, catalog) {
14690
14797
  const knownPaths = resultArtifactTreeRootPaths(record, catalog);
14691
- if (knownPaths.length === 0) return [];
14798
+ if (knownPaths.length === 0) return void 0;
14692
14799
  const artifactDirs = knownPaths.map((p) => path27.dirname(p));
14693
14800
  let commonDir = artifactDirs[0];
14694
14801
  for (const dir of artifactDirs) {
14695
14802
  while (!dir.startsWith(commonDir)) {
14696
- commonDir = path27.dirname(commonDir);
14803
+ const parent = path27.dirname(commonDir);
14804
+ if (parent === commonDir) break;
14805
+ commonDir = parent;
14697
14806
  }
14698
14807
  }
14808
+ return commonDir === "." || commonDir === "" ? void 0 : commonDir;
14809
+ }
14810
+ function buildLocalResultArtifactTree(baseDir, record, catalog) {
14811
+ const commonDir = artifactTreeCommonDir(record, catalog);
14812
+ if (commonDir === void 0) {
14813
+ return resultArtifactTreeRootPaths(record, catalog).length === 0 ? [] : buildFileTree(baseDir, baseDir);
14814
+ }
14699
14815
  return buildFileTree(path27.join(baseDir, commonDir), baseDir);
14700
14816
  }
14701
14817
  function catalogEntryForDiscoveredLocalFile(nodes, displayPath) {
@@ -14804,6 +14920,87 @@ function stripHeavyFields(results) {
14804
14920
  };
14805
14921
  });
14806
14922
  }
14923
+ function readArtifactJsonObject(baseDir, relativePath) {
14924
+ if (!relativePath) return void 0;
14925
+ const resolved = resolveReadableRunArtifactFile(baseDir, relativePath);
14926
+ if (!resolved.absolutePath) return void 0;
14927
+ try {
14928
+ const parsed = JSON.parse(readFileSync14(resolved.absolutePath, "utf8"));
14929
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
14930
+ } catch {
14931
+ return void 0;
14932
+ }
14933
+ }
14934
+ function numberField(record, key) {
14935
+ const value = record?.[key];
14936
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
14937
+ }
14938
+ function objectField(record, key) {
14939
+ const value = record?.[key];
14940
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
14941
+ }
14942
+ function caseTrialArtifactPath(artifactDir, runPath, filePath) {
14943
+ if (!artifactDir || !runPath) return void 0;
14944
+ return path27.posix.join(artifactDir, runPath, filePath);
14945
+ }
14946
+ function buildRepeatTrialReadModels(baseDir, record) {
14947
+ if (!record.trials || record.trials.length === 0) return void 0;
14948
+ const artifactDir = record.artifact_dir ? normalizeArtifactRelativePath(record.artifact_dir) : void 0;
14949
+ return record.trials.map((trial) => {
14950
+ const runPath = trial.run_path ? normalizeArtifactRelativePath(trial.run_path) : void 0;
14951
+ const metricsPath = caseTrialArtifactPath(artifactDir, runPath, "metrics.json");
14952
+ const timingPath = caseTrialArtifactPath(artifactDir, runPath, "timing.json");
14953
+ const gradingPath = caseTrialArtifactPath(artifactDir, runPath, "grading.json");
14954
+ const transcriptPath = caseTrialArtifactPath(artifactDir, runPath, "transcript-raw.jsonl");
14955
+ const answerPath = caseTrialArtifactPath(artifactDir, runPath, "outputs/answer.md");
14956
+ const metrics = readArtifactJsonObject(baseDir, metricsPath);
14957
+ const timing = readArtifactJsonObject(baseDir, timingPath);
14958
+ const toolCalls = objectField(metrics, "tool_calls");
14959
+ const tokenUsage = objectField(timing, "token_usage");
14960
+ return {
14961
+ ...trial,
14962
+ ...numberField(timing, "duration_ms") !== void 0 && {
14963
+ duration_ms: numberField(timing, "duration_ms")
14964
+ },
14965
+ ...numberField(timing, "total_tokens") !== void 0 && {
14966
+ total_tokens: numberField(timing, "total_tokens")
14967
+ },
14968
+ ...numberField(timing, "cost_usd") !== void 0 && {
14969
+ cost_usd: numberField(timing, "cost_usd")
14970
+ },
14971
+ ...tokenUsage && { token_usage: tokenUsage },
14972
+ ...numberField(metrics, "total_tool_calls") !== void 0 && {
14973
+ total_tool_calls: numberField(metrics, "total_tool_calls")
14974
+ },
14975
+ ...toolCalls && { tool_calls: toolCalls },
14976
+ ...metricsPath && { metrics_path: metricsPath },
14977
+ ...timingPath && { timing_path: timingPath },
14978
+ ...gradingPath && { grading_path: gradingPath },
14979
+ ...transcriptPath && { transcript_path: transcriptPath },
14980
+ ...answerPath && { answer_path: answerPath }
14981
+ };
14982
+ });
14983
+ }
14984
+ function attachRunDetailReadModelFields(results, records, baseDir) {
14985
+ return results.map((result, index) => {
14986
+ const record = records[index];
14987
+ if (!record) return result;
14988
+ const trials = buildRepeatTrialReadModels(baseDir, record);
14989
+ return {
14990
+ ...result,
14991
+ ...record.aggregation && { aggregation: record.aggregation },
14992
+ ...record.artifact_dir && { artifact_dir: record.artifact_dir },
14993
+ ...record.summary_path && { summary_path: record.summary_path },
14994
+ ...record.grading_path && { grading_path: record.grading_path },
14995
+ ...record.timing_path && { timing_path: record.timing_path },
14996
+ ...record.metrics_path && { metrics_path: record.metrics_path },
14997
+ ...record.transcript_path && { transcript_path: record.transcript_path },
14998
+ ...record.output_path && { output_path: record.output_path },
14999
+ ...record.answer_path && { answer_path: record.answer_path },
15000
+ ...trials && { trials }
15001
+ };
15002
+ });
15003
+ }
14807
15004
  function inferExperimentFromRunId(runId) {
14808
15005
  const separatorIndex = runId.lastIndexOf("::");
14809
15006
  if (separatorIndex === -1) {
@@ -15104,8 +15301,12 @@ async function handleRunDetail(c4, { searchDir, projectId }) {
15104
15301
  const resumeMeta = meta.source === "local" ? deriveResumeMeta(searchDir, meta.path) : {};
15105
15302
  const liveStatus = meta.source === "local" ? getActiveRunStatus(meta.path) : void 0;
15106
15303
  const tagFields = await readRunTagFields(searchDir, meta, projectId);
15304
+ const baseDir = path27.dirname(meta.path);
15107
15305
  return c4.json({
15108
- results: attachExternalTraceFields(stripHeavyFields(loaded), records),
15306
+ results: attachExternalTraceFields(
15307
+ attachRunDetailReadModelFields(stripHeavyFields(loaded), records, baseDir),
15308
+ records
15309
+ ),
15109
15310
  source: meta.source,
15110
15311
  source_label: meta.displayName,
15111
15312
  ...tagFields,
@@ -15146,9 +15347,9 @@ function deriveResumeMeta(cwd, manifestPath) {
15146
15347
  const relative3 = path27.relative(cwd, runDir);
15147
15348
  out.run_dir = relative3 !== "" && !relative3.startsWith("..") ? relative3 : runDir;
15148
15349
  try {
15149
- const benchmarkPath = path27.join(runDir, "benchmark.json");
15150
- if (existsSync16(benchmarkPath)) {
15151
- const parsed = JSON.parse(readFileSync14(benchmarkPath, "utf8"));
15350
+ const summaryPath = path27.join(runDir, "summary.json");
15351
+ if (existsSync16(summaryPath)) {
15352
+ const parsed = JSON.parse(readFileSync14(summaryPath, "utf8"));
15152
15353
  const evalFile = parsed.metadata?.eval_file;
15153
15354
  if (typeof evalFile === "string" && evalFile.trim()) {
15154
15355
  out.suite_filter = evalFile.trim();
@@ -15261,14 +15462,24 @@ async function handleCategorySuites(c4, { searchDir, agentvDir, projectId }) {
15261
15462
  }
15262
15463
  async function handleEvalDetail(c4, { searchDir, projectId }) {
15263
15464
  const filename = c4.req.param("filename") ?? "";
15264
- const evalId = c4.req.param("evalId");
15465
+ const evalId = c4.req.param("evalId") ?? "";
15466
+ if (!evalId) return c4.json({ error: "Eval id is required" }, 400);
15467
+ const artifactDir = requestedArtifactDir(c4);
15468
+ if (artifactDir.error) return c4.json({ error: artifactDir.error }, 400);
15265
15469
  const meta = await findRunById(searchDir, filename, projectId);
15266
15470
  if (!meta) return c4.json({ error: "Run not found" }, 404);
15267
15471
  try {
15268
15472
  const loaded = await loadManifestResultsForMeta(searchDir, meta, projectId);
15269
- const result = loaded.find((r) => r.testId === evalId);
15270
- if (!result) return c4.json({ error: "Eval not found" }, 404);
15271
- const [stripped] = stripHeavyFields([result]);
15473
+ const records = await parseManifestForMeta(searchDir, meta, projectId);
15474
+ const selection = manifestRecordSelection(records, evalId, artifactDir.value);
15475
+ const result = selection ? loaded[selection.index] : void 0;
15476
+ if (!selection || !result) return c4.json({ error: "Eval not found" }, 404);
15477
+ const baseDir = path27.dirname(meta.path);
15478
+ const [stripped] = attachRunDetailReadModelFields(
15479
+ stripHeavyFields([result]),
15480
+ [selection.record],
15481
+ baseDir
15482
+ );
15272
15483
  return c4.json({ eval: stripped });
15273
15484
  } catch {
15274
15485
  return c4.json({ error: "Failed to load eval" }, 500);
@@ -15276,24 +15487,24 @@ async function handleEvalDetail(c4, { searchDir, projectId }) {
15276
15487
  }
15277
15488
  async function handleEvalFiles(c4, { searchDir, projectId }) {
15278
15489
  const filename = c4.req.param("filename") ?? "";
15279
- const evalId = c4.req.param("evalId");
15490
+ const evalId = c4.req.param("evalId") ?? "";
15491
+ if (!evalId) return c4.json({ error: "Eval id is required" }, 400);
15492
+ const artifactDir = requestedArtifactDir(c4);
15493
+ if (artifactDir.error) return c4.json({ error: artifactDir.error }, 400);
15280
15494
  const meta = await findRunById(searchDir, filename, projectId);
15281
15495
  if (!meta) return c4.json({ error: "Run not found" }, 404);
15282
15496
  try {
15283
15497
  const records = await parseManifestForMeta(searchDir, meta, projectId);
15284
- const record = records.find((r) => r.test_id === evalId);
15285
- if (!record) return c4.json({ error: "Eval not found" }, 404);
15498
+ const selection = manifestRecordSelection(records, evalId, artifactDir.value);
15499
+ if (!selection) return c4.json({ error: "Eval not found" }, 404);
15500
+ const { record } = selection;
15286
15501
  const baseDir = path27.dirname(meta.path);
15287
15502
  const catalog = buildResultArtifactCatalog(record, {
15288
15503
  runPath: relativeRunPathFromManifestPath(meta.path)
15289
15504
  });
15290
15505
  const files = buildLocalResultArtifactTree(baseDir, record, catalog);
15291
- const localFilePaths = new Set(flattenFileTree(files).map((file) => file.path));
15292
- for (const entry of catalog) {
15293
- if (entry.storage === "git" || !localFilePaths.has(entry.displayPath)) {
15294
- ensureCatalogFileNode(files, entry);
15295
- }
15296
- }
15506
+ const rootPrefix = artifactTreeCommonDir(record, catalog);
15507
+ overlayCatalogFileNodes(files, catalog, rootPrefix);
15297
15508
  return c4.json({ files });
15298
15509
  } catch {
15299
15510
  return c4.json({ error: "Failed to load file tree" }, 500);
@@ -15301,7 +15512,10 @@ async function handleEvalFiles(c4, { searchDir, projectId }) {
15301
15512
  }
15302
15513
  async function handleEvalFileContent(c4, { searchDir, projectId }) {
15303
15514
  const filename = c4.req.param("filename") ?? "";
15304
- const evalId = c4.req.param("evalId");
15515
+ const evalId = c4.req.param("evalId") ?? "";
15516
+ if (!evalId) return c4.json({ error: "Eval id is required" }, 400);
15517
+ const artifactDir = requestedArtifactDir(c4);
15518
+ if (artifactDir.error) return c4.json({ error: artifactDir.error }, 400);
15305
15519
  const meta = await findRunById(searchDir, filename, projectId);
15306
15520
  if (!meta) return c4.json({ error: "Run not found" }, 404);
15307
15521
  const marker = "/files/";
@@ -15316,8 +15530,9 @@ async function handleEvalFileContent(c4, { searchDir, projectId }) {
15316
15530
  if (!filePath) return c4.json({ error: "No file path specified" }, 400);
15317
15531
  await ensureRunReadable(searchDir, meta, projectId);
15318
15532
  const records = parseResultManifest(readFileSync14(meta.path, "utf8"));
15319
- const record = records.find((r) => r.test_id === evalId);
15320
- if (!record) return c4.json({ error: "Eval not found" }, 404);
15533
+ const selection = manifestRecordSelection(records, evalId, artifactDir.value);
15534
+ if (!selection) return c4.json({ error: "Eval not found" }, 404);
15535
+ const { record } = selection;
15321
15536
  const catalog = buildResultArtifactCatalog(record, {
15322
15537
  runPath: relativeRunPathFromManifestPath(meta.path)
15323
15538
  });
@@ -15337,13 +15552,17 @@ async function handleEvalFileContent(c4, { searchDir, projectId }) {
15337
15552
  }
15338
15553
  async function handleEvalTraceSession(c4, { searchDir, projectId }) {
15339
15554
  const filename = c4.req.param("filename") ?? "";
15340
- const evalId = c4.req.param("evalId");
15555
+ const evalId = c4.req.param("evalId") ?? "";
15556
+ if (!evalId) return c4.json({ error: "Eval id is required" }, 400);
15557
+ const artifactDir = requestedArtifactDir(c4);
15558
+ if (artifactDir.error) return c4.json({ error: artifactDir.error }, 400);
15341
15559
  const meta = await findRunById(searchDir, filename, projectId);
15342
15560
  if (!meta) return c4.json({ error: "Run not found" }, 404);
15343
15561
  try {
15344
15562
  const records = await parseManifestForMeta(searchDir, meta, projectId);
15345
- const record = records.find((r) => r.test_id === evalId);
15346
- if (!record) return c4.json({ error: "Eval not found" }, 404);
15563
+ const selection = manifestRecordSelection(records, evalId, artifactDir.value);
15564
+ if (!selection) return c4.json({ error: "Eval not found" }, 404);
15565
+ const { record } = selection;
15347
15566
  const trace = resolveRecordArtifactPointer(record, "trace");
15348
15567
  const runPath = relativeRunPathFromManifestPath(meta.path);
15349
15568
  const traceEntry = findPointerArtifactCatalogEntry(
@@ -15453,13 +15672,17 @@ async function handleEvalTraceSession(c4, { searchDir, projectId }) {
15453
15672
  }
15454
15673
  async function handleEvalTranscript(c4, { searchDir, projectId }) {
15455
15674
  const filename = c4.req.param("filename") ?? "";
15456
- const evalId = c4.req.param("evalId");
15675
+ const evalId = c4.req.param("evalId") ?? "";
15676
+ if (!evalId) return c4.json({ error: "Eval id is required" }, 400);
15677
+ const artifactDir = requestedArtifactDir(c4);
15678
+ if (artifactDir.error) return c4.json({ error: artifactDir.error }, 400);
15457
15679
  const meta = await findRunById(searchDir, filename, projectId);
15458
15680
  if (!meta) return c4.json({ error: "Run not found" }, 404);
15459
15681
  try {
15460
15682
  const records = await parseManifestForMeta(searchDir, meta, projectId);
15461
- const record = records.find((r) => r.test_id === evalId);
15462
- if (!record) return c4.json({ error: "Eval not found" }, 404);
15683
+ const selection = manifestRecordSelection(records, evalId, artifactDir.value);
15684
+ if (!selection) return c4.json({ error: "Eval not found" }, 404);
15685
+ const { record } = selection;
15463
15686
  const transcript = resolveRecordArtifactPointer(record, "transcript");
15464
15687
  const answer = resolveRecordArtifactPointer(record, "answer");
15465
15688
  const runPath = relativeRunPathFromManifestPath(meta.path);
@@ -16328,6 +16551,10 @@ function createApp(results, resultDir, cwd, sourceFile, options) {
16328
16551
  "/api/remote/sync",
16329
16552
  async (c4) => c4.json(await syncRemoteResults(searchDir, defaultCtx.projectId))
16330
16553
  );
16554
+ app2.post(
16555
+ "/api/remote/sync/confirm-merge",
16556
+ async (c4) => c4.json(await confirmRemoteResultsMerge(searchDir, defaultCtx.projectId))
16557
+ );
16331
16558
  app2.get("/api/runs", (c4) => handleRuns(c4, defaultCtx));
16332
16559
  app2.post("/api/runs/combine", (c4) => {
16333
16560
  if (readOnly) {
@@ -16447,6 +16674,13 @@ function createApp(results, resultDir, cwd, sourceFile, options) {
16447
16674
  async (ctx, dataCtx) => ctx.json(await syncRemoteResults(dataCtx.searchDir, dataCtx.projectId))
16448
16675
  )
16449
16676
  );
16677
+ app2.post(
16678
+ "/api/projects/:projectId/remote/sync/confirm-merge",
16679
+ (c4) => withProject(
16680
+ c4,
16681
+ async (ctx, dataCtx) => ctx.json(await confirmRemoteResultsMerge(dataCtx.searchDir, dataCtx.projectId))
16682
+ )
16683
+ );
16450
16684
  app2.get("/api/projects/:projectId/runs", (c4) => withProject(c4, handleRuns));
16451
16685
  app2.post("/api/projects/:projectId/runs/combine", (c4) => {
16452
16686
  if (readOnly) {
@@ -18765,4 +18999,4 @@ export {
18765
18999
  preprocessArgv,
18766
19000
  runCli
18767
19001
  };
18768
- //# sourceMappingURL=chunk-IFQXBQSY.js.map
19002
+ //# sourceMappingURL=chunk-6Q56CEXV.js.map