agentv 4.35.1 → 4.37.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 (33) hide show
  1. package/dist/{artifact-writer-G57MG52C.js → artifact-writer-GFNKYREE.js} +4 -4
  2. package/dist/{chunk-INOKS5LF.js → chunk-M7AMFWBZ.js} +275 -58
  3. package/dist/chunk-M7AMFWBZ.js.map +1 -0
  4. package/dist/{chunk-KJGYL3M3.js → chunk-N6E5XFOM.js} +213 -85
  5. package/dist/chunk-N6E5XFOM.js.map +1 -0
  6. package/dist/{chunk-KNF3AGCI.js → chunk-OYI35QFW.js} +314 -49
  7. package/dist/chunk-OYI35QFW.js.map +1 -0
  8. package/dist/{chunk-CRMGUVRZ.js → chunk-P4LSNFZR.js} +85 -19
  9. package/dist/chunk-P4LSNFZR.js.map +1 -0
  10. package/dist/{chunk-6QEIZ33V.js → chunk-RL4S2FBZ.js} +2700 -456
  11. package/dist/chunk-RL4S2FBZ.js.map +1 -0
  12. package/dist/cli.js +5 -5
  13. package/dist/dashboard/assets/index-9tV-u4HJ.css +1 -0
  14. package/dist/dashboard/assets/{index-Bdk-9a_8.js → index-BDRYJsGF.js} +1 -1
  15. package/dist/dashboard/assets/index-DuESU7zZ.js +118 -0
  16. package/dist/dashboard/index.html +2 -2
  17. package/dist/{dist-M4B77IW4.js → dist-OY3JSP6Z.js} +125 -3
  18. package/dist/index.js +5 -5
  19. package/dist/{interactive-VYQ5SYMR.js → interactive-CQELHITQ.js} +5 -5
  20. package/dist/skills/agentv-eval-writer/SKILL.md +6 -0
  21. package/dist/{ts-eval-loader-EQJX3OLT-THE7D3GR.js → ts-eval-loader-RBTB2HG2-H5TRXZLO.js} +2 -2
  22. package/package.json +1 -1
  23. package/dist/chunk-6QEIZ33V.js.map +0 -1
  24. package/dist/chunk-CRMGUVRZ.js.map +0 -1
  25. package/dist/chunk-INOKS5LF.js.map +0 -1
  26. package/dist/chunk-KJGYL3M3.js.map +0 -1
  27. package/dist/chunk-KNF3AGCI.js.map +0 -1
  28. package/dist/dashboard/assets/index-BPMAZqjE.css +0 -1
  29. package/dist/dashboard/assets/index-BWO0UcxG.js +0 -118
  30. /package/dist/{artifact-writer-G57MG52C.js.map → artifact-writer-GFNKYREE.js.map} +0 -0
  31. /package/dist/{dist-M4B77IW4.js.map → dist-OY3JSP6Z.js.map} +0 -0
  32. /package/dist/{interactive-VYQ5SYMR.js.map → interactive-CQELHITQ.js.map} +0 -0
  33. /package/dist/{ts-eval-loader-EQJX3OLT-THE7D3GR.js.map → ts-eval-loader-RBTB2HG2-H5TRXZLO.js.map} +0 -0
@@ -1,5 +1,6 @@
1
1
  import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
2
2
  import {
3
+ buildTraceFromMessages,
3
4
  external_exports,
4
5
  extractLastAssistantContent,
5
6
  getAgentvConfigDir,
@@ -9,10 +10,8 @@ import {
9
10
  parseRepoCheckout,
10
11
  parseRepoClone,
11
12
  parseRepoSource,
12
- parseYamlValue,
13
- toCamelCaseDeep,
14
- toSnakeCaseDeep
15
- } from "./chunk-6QEIZ33V.js";
13
+ parseYamlValue
14
+ } from "./chunk-RL4S2FBZ.js";
16
15
 
17
16
  // ../../packages/core/dist/index.js
18
17
  import { readFileSync } from "node:fs";
@@ -547,6 +546,8 @@ function extractReposFromObject(obj) {
547
546
  var execFileAsync = promisify(execFile);
548
547
  var RESULTS_REPO_RESULTS_DIR = ".agentv/results";
549
548
  var RESULTS_REPO_RUNS_DIR = `${RESULTS_REPO_RESULTS_DIR}/runs`;
549
+ var RESULTS_REPO_COMMIT_EMAIL = "agentv@results-repo";
550
+ var RESULTS_REPO_COMMIT_NAME = "AgentV Results";
550
551
  var activeResultsRepoSyncs = /* @__PURE__ */ new Set();
551
552
  function sanitizeRepoSlug(repo) {
552
553
  return repo.trim().replace(/[^A-Za-z0-9._-]+/g, "-");
@@ -567,10 +568,12 @@ function expandHome(p) {
567
568
  }
568
569
  function normalizeResultsConfig(config) {
569
570
  const repo = config.repo.trim();
571
+ const branch = config.branch?.trim();
570
572
  const resolvedPath = config.path ? expandHome(config.path.trim()) : path3.join(getAgentvDataDir(), "results", sanitizeRepoSlug(repo));
571
573
  return {
572
574
  mode: "github",
573
575
  repo,
576
+ ...branch ? { branch } : {},
574
577
  path: resolvedPath,
575
578
  auto_push: config.auto_push === true,
576
579
  branch_prefix: config.branch_prefix?.trim() || "eval-results"
@@ -638,6 +641,10 @@ async function runGit(args, options) {
638
641
  async function runGh(args, options) {
639
642
  return runCommand("gh", args, options);
640
643
  }
644
+ async function ensureResultsRepoCommitIdentity(repoDir) {
645
+ await runGit(["config", "user.email", RESULTS_REPO_COMMIT_EMAIL], { cwd: repoDir });
646
+ await runGit(["config", "user.name", RESULTS_REPO_COMMIT_NAME], { cwd: repoDir });
647
+ }
641
648
  async function resolveDefaultBranch(repoDir) {
642
649
  try {
643
650
  const { stdout } = await runGit(["symbolic-ref", "refs/remotes/origin/HEAD"], { cwd: repoDir });
@@ -660,6 +667,64 @@ async function resolveDefaultBranch(repoDir) {
660
667
  async function fetchResultsRepo(repoDir) {
661
668
  await runGit(["fetch", "origin", "--prune"], { cwd: repoDir });
662
669
  }
670
+ function remoteBranchRef(branch) {
671
+ return `origin/${branch}`;
672
+ }
673
+ function missingConfiguredBranchError(config) {
674
+ const branch = config.branch ?? "<unknown>";
675
+ return new Error(
676
+ [
677
+ `Results repo remote branch '${branch}' does not exist in ${config.repo}.`,
678
+ "Create the storage branch once, then retry. Example:",
679
+ ` git clone ${resolveResultsRepoUrl(config.repo)} /tmp/agentv-results-init`,
680
+ " cd /tmp/agentv-results-init",
681
+ ` git switch --orphan ${branch}`,
682
+ " git rm -rf .",
683
+ ' git commit --allow-empty -m "chore(results): initialize AgentV results branch"',
684
+ ` git push origin HEAD:${branch}`
685
+ ].join("\n")
686
+ );
687
+ }
688
+ async function assertConfiguredResultsBranchExists(repoDir, config) {
689
+ if (!config.branch) {
690
+ return void 0;
691
+ }
692
+ const ref = remoteBranchRef(config.branch);
693
+ const { stdout } = await runGit(["rev-parse", "--verify", `${ref}^{commit}`], {
694
+ cwd: repoDir,
695
+ check: false
696
+ });
697
+ if (!stdout.trim()) {
698
+ throw missingConfiguredBranchError(config);
699
+ }
700
+ return ref;
701
+ }
702
+ async function localBranchExists(repoDir, branch) {
703
+ const { stdout } = await runGit(["rev-parse", "--verify", `refs/heads/${branch}`], {
704
+ cwd: repoDir,
705
+ check: false
706
+ });
707
+ return stdout.trim().length > 0;
708
+ }
709
+ async function checkoutConfiguredResultsBranch(repoDir, config) {
710
+ const remoteRef = await assertConfiguredResultsBranchExists(repoDir, config);
711
+ if (!config.branch || !remoteRef) {
712
+ return void 0;
713
+ }
714
+ const currentBranch = await getCurrentBranch(repoDir);
715
+ if (currentBranch !== config.branch) {
716
+ if (await localBranchExists(repoDir, config.branch)) {
717
+ await runGit(["checkout", config.branch], { cwd: repoDir });
718
+ } else {
719
+ await runGit(["checkout", "--track", "-b", config.branch, remoteRef], { cwd: repoDir });
720
+ }
721
+ }
722
+ await runGit(["branch", "--set-upstream-to", remoteRef, config.branch], {
723
+ cwd: repoDir,
724
+ check: false
725
+ });
726
+ return remoteRef;
727
+ }
663
728
  async function isGitRepository(repoDir) {
664
729
  try {
665
730
  const { stdout } = await runGit(["rev-parse", "--is-inside-work-tree"], { cwd: repoDir });
@@ -763,7 +828,10 @@ async function getCurrentBranch(repoDir) {
763
828
  });
764
829
  return sha.trim() ? `HEAD@${sha.trim()}` : void 0;
765
830
  }
766
- async function resolveComparisonRef(repoDir) {
831
+ async function resolveComparisonRef(repoDir, config) {
832
+ if (config?.branch) {
833
+ return assertConfiguredResultsBranchExists(repoDir, config);
834
+ }
767
835
  const { stdout: upstream } = await runGit(
768
836
  ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}"],
769
837
  { cwd: repoDir, check: false }
@@ -826,9 +894,9 @@ async function buildGitDiffSummary(repoDir, upstream) {
826
894
  }
827
895
  return summaries.length > 0 ? summaries.join("\n") : void 0;
828
896
  }
829
- async function inspectResultsRepoGit(repoDir) {
897
+ async function inspectResultsRepoGit(repoDir, config) {
830
898
  const branch = await getCurrentBranch(repoDir);
831
- const upstream = await resolveComparisonRef(repoDir);
899
+ const upstream = await resolveComparisonRef(repoDir, config);
832
900
  const { stdout: porcelain } = await runGit(
833
901
  ["status", "--porcelain=v1", "--untracked-files=all"],
834
902
  {
@@ -936,7 +1004,10 @@ function getPushTargetBranch(upstream, baseBranch) {
936
1004
  return upstream?.startsWith("origin/") ? upstream.slice("origin/".length) : baseBranch;
937
1005
  }
938
1006
  async function statusFromInspection(normalized, repoDir) {
939
- return withGitInspection(getResultsRepoStatus(normalized), await inspectResultsRepoGit(repoDir));
1007
+ return withGitInspection(
1008
+ getResultsRepoStatus(normalized),
1009
+ await inspectResultsRepoGit(repoDir, normalized)
1010
+ );
940
1011
  }
941
1012
  async function getResultsRepoSyncStatus(config) {
942
1013
  const baseStatus = getResultsRepoStatus(config);
@@ -957,10 +1028,15 @@ async function getResultsRepoSyncStatus(config) {
957
1028
  };
958
1029
  }
959
1030
  try {
960
- return withGitInspection(baseStatus, await inspectResultsRepoGit(normalized.path));
1031
+ if (normalized.branch) {
1032
+ await fetchResultsRepo(normalized.path);
1033
+ await checkoutConfiguredResultsBranch(normalized.path, normalized);
1034
+ }
1035
+ return withGitInspection(baseStatus, await inspectResultsRepoGit(normalized.path, normalized));
961
1036
  } catch (error) {
962
1037
  return {
963
1038
  ...baseStatus,
1039
+ ...normalized.branch ? { available: false } : {},
964
1040
  sync_status: "unavailable",
965
1041
  last_error: getStatusMessage(error)
966
1042
  };
@@ -971,6 +1047,7 @@ async function syncResultsRepo(config) {
971
1047
  try {
972
1048
  const repoDir = await ensureResultsRepoClone(normalized);
973
1049
  await fetchResultsRepo(repoDir);
1050
+ await checkoutConfiguredResultsBranch(repoDir, normalized);
974
1051
  updateStatusFile(normalized, {
975
1052
  last_synced_at: (/* @__PURE__ */ new Date()).toISOString(),
976
1053
  last_error: void 0
@@ -1004,7 +1081,8 @@ async function syncResultsRepoForProject(config) {
1004
1081
  try {
1005
1082
  const repoDir = await ensureResultsRepoClone(normalized);
1006
1083
  await fetchResultsRepo(repoDir);
1007
- let inspection = await inspectResultsRepoGit(repoDir);
1084
+ await checkoutConfiguredResultsBranch(repoDir, normalized);
1085
+ let inspection = await inspectResultsRepoGit(repoDir, normalized);
1008
1086
  if (inspection.syncStatus === "conflicted") {
1009
1087
  const status = withGitInspection(getResultsRepoStatus(normalized), inspection);
1010
1088
  updateStatusFile(normalized, {
@@ -1047,9 +1125,9 @@ async function syncResultsRepoForProject(config) {
1047
1125
  try {
1048
1126
  await runGit(["merge", "--ff-only", inspection.upstream], { cwd: repoDir });
1049
1127
  pullPerformed = true;
1050
- inspection = await inspectResultsRepoGit(repoDir);
1128
+ inspection = await inspectResultsRepoGit(repoDir, normalized);
1051
1129
  } catch (error) {
1052
- inspection = await inspectResultsRepoGit(repoDir);
1130
+ inspection = await inspectResultsRepoGit(repoDir, normalized);
1053
1131
  const status = withGitInspection(getResultsRepoStatus(normalized), inspection);
1054
1132
  const reason = `Results repo could not be fast-forwarded: ${getStatusMessage(error)}`;
1055
1133
  updateStatusFile(normalized, { last_error: reason });
@@ -1062,6 +1140,7 @@ async function syncResultsRepoForProject(config) {
1062
1140
  }
1063
1141
  if (inspection.syncStatus === "dirty") {
1064
1142
  await runGit(["add", "--all", "--", RESULTS_REPO_RESULTS_DIR], { cwd: repoDir });
1143
+ await ensureResultsRepoCommitIdentity(repoDir);
1065
1144
  await runGit(
1066
1145
  [
1067
1146
  "commit",
@@ -1075,7 +1154,7 @@ async function syncResultsRepoForProject(config) {
1075
1154
  }
1076
1155
  );
1077
1156
  commitCreated = true;
1078
- inspection = await inspectResultsRepoGit(repoDir);
1157
+ inspection = await inspectResultsRepoGit(repoDir, normalized);
1079
1158
  }
1080
1159
  }
1081
1160
  if (inspection.syncStatus === "diverged") {
@@ -1104,9 +1183,9 @@ async function syncResultsRepoForProject(config) {
1104
1183
  try {
1105
1184
  await runGit(["merge", "--ff-only", inspection.upstream], { cwd: repoDir });
1106
1185
  pullPerformed = true;
1107
- inspection = await inspectResultsRepoGit(repoDir);
1186
+ inspection = await inspectResultsRepoGit(repoDir, normalized);
1108
1187
  } catch (error) {
1109
- inspection = await inspectResultsRepoGit(repoDir);
1188
+ inspection = await inspectResultsRepoGit(repoDir, normalized);
1110
1189
  const status = withGitInspection(getResultsRepoStatus(normalized), inspection);
1111
1190
  const reason = `Results repo could not be fast-forwarded: ${getStatusMessage(error)}`;
1112
1191
  updateStatusFile(normalized, { last_error: reason });
@@ -1137,16 +1216,16 @@ async function syncResultsRepoForProject(config) {
1137
1216
  commitCreated
1138
1217
  });
1139
1218
  }
1140
- const baseBranch = await resolveDefaultBranch(repoDir);
1219
+ const baseBranch = normalized.branch ?? await resolveDefaultBranch(repoDir);
1141
1220
  const targetBranch = getPushTargetBranch(inspection.upstream, baseBranch);
1142
1221
  try {
1143
1222
  await runGit(["push", "origin", `HEAD:${targetBranch}`], { cwd: repoDir });
1144
1223
  pushPerformed = true;
1145
1224
  await fetchResultsRepo(repoDir);
1146
- inspection = await inspectResultsRepoGit(repoDir);
1225
+ inspection = await inspectResultsRepoGit(repoDir, normalized);
1147
1226
  } catch (error) {
1148
1227
  await fetchResultsRepo(repoDir).catch(() => void 0);
1149
- inspection = await inspectResultsRepoGit(repoDir);
1228
+ inspection = await inspectResultsRepoGit(repoDir, normalized);
1150
1229
  const status = withGitInspection(getResultsRepoStatus(normalized), inspection);
1151
1230
  const reason = `Results repo push was rejected: ${getStatusMessage(error)}`;
1152
1231
  updateStatusFile(normalized, { last_error: reason });
@@ -1240,6 +1319,7 @@ async function commitAndPushResultsBranch(params) {
1240
1319
  if (diffStdout.trim().length === 0) {
1241
1320
  return false;
1242
1321
  }
1322
+ await ensureResultsRepoCommitIdentity(params.repoDir);
1243
1323
  await runGit(["commit", "-m", params.commitMessage], { cwd: params.repoDir });
1244
1324
  await runGit(["push", "-u", "origin", params.branchName], { cwd: params.repoDir });
1245
1325
  return true;
@@ -1276,17 +1356,17 @@ async function createDraftResultsPr(params) {
1276
1356
  return stdout.trim();
1277
1357
  }
1278
1358
  var DIRECT_PUSH_MAX_RETRIES = 3;
1279
- async function hasUnpushedCommits(repoDir, baseBranch) {
1280
- const { stdout } = await runGit(["rev-list", "--count", `origin/${baseBranch}..HEAD`], {
1359
+ async function hasUnpushedCommits(repoDir, upstreamRef) {
1360
+ const { stdout } = await runGit(["rev-list", "--count", `${upstreamRef}..HEAD`], {
1281
1361
  cwd: repoDir,
1282
1362
  check: false
1283
1363
  });
1284
1364
  return Number.parseInt(stdout.trim(), 10) > 0;
1285
1365
  }
1286
- async function pushDirectResultsToBase(params) {
1366
+ async function pushDirectResultsToStorageBranch(params) {
1287
1367
  for (let attempt = 1; attempt <= DIRECT_PUSH_MAX_RETRIES; attempt++) {
1288
1368
  try {
1289
- await runGit(["push", "origin", `HEAD:${params.baseBranch}`], { cwd: params.repoDir });
1369
+ await runGit(["push", "origin", `HEAD:${params.storageBranch}`], { cwd: params.repoDir });
1290
1370
  updateStatusFile(params.normalized, {
1291
1371
  last_synced_at: (/* @__PURE__ */ new Date()).toISOString(),
1292
1372
  last_error: void 0
@@ -1296,7 +1376,7 @@ async function pushDirectResultsToBase(params) {
1296
1376
  const message = error instanceof Error ? error.message : String(error);
1297
1377
  if (attempt < DIRECT_PUSH_MAX_RETRIES && message.includes("non-fast-forward")) {
1298
1378
  await fetchResultsRepo(params.repoDir);
1299
- await runGit(["rebase", `origin/${params.baseBranch}`], { cwd: params.repoDir });
1379
+ await runGit(["rebase", params.upstreamRef], { cwd: params.repoDir });
1300
1380
  } else {
1301
1381
  throw error;
1302
1382
  }
@@ -1306,8 +1386,10 @@ async function pushDirectResultsToBase(params) {
1306
1386
  async function directPushResults(params) {
1307
1387
  const normalized = normalizeResultsConfig(params.config);
1308
1388
  const repoDir = await ensureResultsRepoClone(normalized);
1309
- const baseBranch = await resolveDefaultBranch(repoDir);
1310
1389
  await fetchResultsRepo(repoDir);
1390
+ const configuredRef = await checkoutConfiguredResultsBranch(repoDir, normalized);
1391
+ const storageBranch = normalized.branch ?? await resolveDefaultBranch(repoDir);
1392
+ const upstreamRef = configuredRef ?? remoteBranchRef(storageBranch);
1311
1393
  const targetRunId = buildGitRunId(params.destinationPath);
1312
1394
  const destinationDir = path3.join(
1313
1395
  repoDir,
@@ -1326,20 +1408,21 @@ async function directPushResults(params) {
1326
1408
  check: false
1327
1409
  });
1328
1410
  if (status.trim().length === 0) {
1329
- if (await hasUnpushedCommits(repoDir, baseBranch)) {
1330
- const aheadPaths = await getAheadPaths(repoDir, `origin/${baseBranch}`);
1411
+ if (await hasUnpushedCommits(repoDir, upstreamRef)) {
1412
+ const aheadPaths = await getAheadPaths(repoDir, upstreamRef);
1331
1413
  if (!areSafeResultsRepoPaths(aheadPaths)) {
1332
1414
  throw new Error("Results repo has non-results committed changes");
1333
1415
  }
1334
- await pushDirectResultsToBase({ normalized, repoDir, baseBranch });
1416
+ await pushDirectResultsToStorageBranch({ normalized, repoDir, storageBranch, upstreamRef });
1335
1417
  return true;
1336
1418
  }
1337
1419
  return false;
1338
1420
  }
1421
+ await ensureResultsRepoCommitIdentity(repoDir);
1339
1422
  await runGit(["commit", "-m", params.commitMessage, "-m", `Agentv-Run: ${targetRunId}`], {
1340
1423
  cwd: repoDir
1341
1424
  });
1342
- await pushDirectResultsToBase({ normalized, repoDir, baseBranch });
1425
+ await pushDirectResultsToStorageBranch({ normalized, repoDir, storageBranch, upstreamRef });
1343
1426
  return true;
1344
1427
  }
1345
1428
  function buildGitRunId(relativeRunPath) {
@@ -1445,6 +1528,75 @@ function parseGitBatchBlobs(output) {
1445
1528
  }
1446
1529
  return blobs;
1447
1530
  }
1531
+ function buildWipBranchName(runDir) {
1532
+ const hostname = os.hostname().replace(/[^A-Za-z0-9._-]+/g, "-").slice(0, 40);
1533
+ const runBasename = path3.basename(runDir).replace(/[^A-Za-z0-9._-]+/g, "-").slice(0, 60);
1534
+ return `agentv/inflight/${hostname}/${runBasename}`;
1535
+ }
1536
+ async function setupWipWorktree(params) {
1537
+ const normalized = normalizeResultsConfig(params.config);
1538
+ const cloneDir = await ensureResultsRepoClone(normalized);
1539
+ await fetchResultsRepo(cloneDir);
1540
+ const baseRef = normalized.branch ? await assertConfiguredResultsBranchExists(cloneDir, normalized) : remoteBranchRef(await resolveDefaultBranch(cloneDir));
1541
+ if (!baseRef) {
1542
+ throw missingConfiguredBranchError(normalized);
1543
+ }
1544
+ const worktreeRoot = await mkdtemp(path3.join(os.tmpdir(), "agentv-wip-"));
1545
+ const worktreeDir = path3.join(worktreeRoot, "repo");
1546
+ await runGit(["worktree", "add", "-B", params.wipBranch, worktreeDir, baseRef], {
1547
+ cwd: cloneDir
1548
+ });
1549
+ await runGit(["config", "user.email", "agentv@wip-checkpoint"], { cwd: worktreeDir });
1550
+ await runGit(["config", "user.name", "AgentV WIP Checkpoint"], { cwd: worktreeDir });
1551
+ return {
1552
+ wipBranch: params.wipBranch,
1553
+ worktreeDir,
1554
+ cloneDir,
1555
+ cleanup: async () => {
1556
+ try {
1557
+ await runGit(["worktree", "remove", "--force", worktreeDir], { cwd: cloneDir });
1558
+ } finally {
1559
+ await rm(worktreeRoot, { recursive: true, force: true }).catch(() => void 0);
1560
+ }
1561
+ }
1562
+ };
1563
+ }
1564
+ async function pushWipCheckpoint(params) {
1565
+ const destinationDir = path3.join(
1566
+ params.handle.worktreeDir,
1567
+ RESULTS_REPO_RUNS_DIR,
1568
+ params.destinationPath
1569
+ );
1570
+ await stageResultsArtifacts({
1571
+ repoDir: params.handle.worktreeDir,
1572
+ sourceDir: params.sourceDir,
1573
+ destinationDir
1574
+ });
1575
+ await runGit(["add", "--all", "--", RESULTS_REPO_RESULTS_DIR], {
1576
+ cwd: params.handle.worktreeDir
1577
+ });
1578
+ const { stdout: status } = await runGit(["status", "--porcelain"], {
1579
+ cwd: params.handle.worktreeDir,
1580
+ check: false
1581
+ });
1582
+ if (!status.trim()) {
1583
+ return false;
1584
+ }
1585
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
1586
+ await runGit(
1587
+ ["commit", "--amend", "-m", `wip(results): checkpoint ${params.handle.wipBranch} ${timestamp}`],
1588
+ { cwd: params.handle.worktreeDir }
1589
+ );
1590
+ await runGit(["push", "--force", "origin", params.handle.wipBranch], {
1591
+ cwd: params.handle.worktreeDir
1592
+ });
1593
+ return true;
1594
+ }
1595
+ async function deleteWipBranch(params) {
1596
+ const normalized = normalizeResultsConfig(params.config);
1597
+ const cloneDir = await ensureResultsRepoClone(normalized);
1598
+ await runGit(["push", "origin", "--delete", params.wipBranch], { cwd: cloneDir });
1599
+ }
1448
1600
  async function listGitRuns(repoDir, ref = "origin/main") {
1449
1601
  const { stdout: treeOut } = await runGit(
1450
1602
  ["ls-tree", "-r", "--name-only", ref, RESULTS_REPO_RUNS_DIR],
@@ -1563,6 +1715,7 @@ function fromYaml(raw) {
1563
1715
  const sync = r.sync && typeof r.sync === "object" ? r.sync : void 0;
1564
1716
  entry.results = {
1565
1717
  repoUrl: r.repo_url.trim(),
1718
+ ...typeof r.branch === "string" && r.branch.trim().length > 0 ? { branch: r.branch.trim() } : {},
1566
1719
  ...typeof r.path === "string" && r.path.trim().length > 0 ? { path: r.path.trim() } : {},
1567
1720
  ...sync && typeof sync.auto_push === "boolean" ? { sync: { autoPush: sync.auto_push } } : {},
1568
1721
  ...typeof r.branch_prefix === "string" && r.branch_prefix.trim().length > 0 ? { branchPrefix: r.branch_prefix.trim() } : {}
@@ -1584,6 +1737,7 @@ function toYaml(entry) {
1584
1737
  if (entry.results) {
1585
1738
  yaml.results = {
1586
1739
  repo_url: entry.results.repoUrl,
1740
+ ...entry.results.branch !== void 0 && { branch: entry.results.branch },
1587
1741
  ...entry.results.path !== void 0 && { path: entry.results.path },
1588
1742
  ...entry.results.sync?.autoPush !== void 0 && {
1589
1743
  sync: { auto_push: entry.results.sync.autoPush }
@@ -1924,9 +2078,7 @@ var OtelTraceExporter = class {
1924
2078
  if (result.suite) rootSpan.setAttribute("agentv.suite", result.suite);
1925
2079
  rootSpan.setAttribute("agentv.score", result.score);
1926
2080
  if (captureContent && result.output.length > 0) {
1927
- const lastMsg = result.output[result.output.length - 1];
1928
- const text = typeof lastMsg.content === "string" ? lastMsg.content : JSON.stringify(lastMsg.content);
1929
- rootSpan.setAttribute("agentv.output_text", text);
2081
+ rootSpan.setAttribute("agentv.output_text", result.output);
1930
2082
  }
1931
2083
  if (result.durationMs != null)
1932
2084
  rootSpan.setAttribute("agentv.trace.duration_ms", result.durationMs);
@@ -1952,10 +2104,11 @@ var OtelTraceExporter = class {
1952
2104
  if (t.llmCallCount != null)
1953
2105
  rootSpan.setAttribute("agentv.trace.llm_call_count", t.llmCallCount);
1954
2106
  }
1955
- if (result.output) {
2107
+ const traceMessages = result.trace?.messages ?? [];
2108
+ if (traceMessages.length > 0) {
1956
2109
  const parentCtx2 = api.trace.setSpan(api.context.active(), rootSpan);
1957
2110
  if (this.options.groupTurns) {
1958
- const turns = groupMessagesIntoTurns(result.output);
2111
+ const turns = groupMessagesIntoTurns(traceMessages);
1959
2112
  if (turns.length > 1) {
1960
2113
  for (const [i, turn] of turns.entries()) {
1961
2114
  api.context.with(parentCtx2, () => {
@@ -1973,12 +2126,12 @@ var OtelTraceExporter = class {
1973
2126
  });
1974
2127
  }
1975
2128
  } else {
1976
- for (const msg of result.output) {
2129
+ for (const msg of traceMessages) {
1977
2130
  this.exportMessage(tracer, api, parentCtx2, msg, captureContent);
1978
2131
  }
1979
2132
  }
1980
2133
  } else {
1981
- for (const msg of result.output) {
2134
+ for (const msg of traceMessages) {
1982
2135
  this.exportMessage(tracer, api, parentCtx2, msg, captureContent);
1983
2136
  }
1984
2137
  }
@@ -2245,9 +2398,9 @@ var OtelStreamingObserver = class {
2245
2398
  if (this.observedChildSpans || !this.rootCtx) {
2246
2399
  return;
2247
2400
  }
2248
- const model = result.output.find((msg) => msg.role === "assistant")?.metadata?.model ?? result.target ?? "unknown";
2401
+ const model = result.trace.messages.find((msg) => msg.role === "assistant")?.metadata?.model ?? result.target ?? "unknown";
2249
2402
  this.onLlmCall(String(model), result.tokenUsage);
2250
- for (const message of result.output) {
2403
+ for (const message of result.trace.messages) {
2251
2404
  for (const toolCall of message.toolCalls ?? []) {
2252
2405
  this.onToolCall(
2253
2406
  toolCall.tool,
@@ -2831,6 +2984,44 @@ async function discoverClaudeSessions(opts) {
2831
2984
  sessions.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
2832
2985
  return sessions.slice(0, limit);
2833
2986
  }
2987
+ function dropUndefined(value) {
2988
+ return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
2989
+ }
2990
+ function toTranscriptTokenUsage(usage) {
2991
+ if (!usage) {
2992
+ return void 0;
2993
+ }
2994
+ return dropUndefined({
2995
+ input: usage.input,
2996
+ output: usage.output,
2997
+ cached: usage.cached,
2998
+ reasoning: usage.reasoning
2999
+ });
3000
+ }
3001
+ function toTranscriptToolCall(toolCall) {
3002
+ return dropUndefined({
3003
+ tool: toolCall.tool,
3004
+ input: toolCall.input,
3005
+ output: toolCall.output,
3006
+ id: toolCall.id,
3007
+ start_time: toolCall.startTime,
3008
+ end_time: toolCall.endTime,
3009
+ duration_ms: toolCall.durationMs
3010
+ });
3011
+ }
3012
+ function toTranscriptMessageFields(message) {
3013
+ return dropUndefined({
3014
+ role: message.role,
3015
+ name: message.name,
3016
+ content: message.content,
3017
+ tool_calls: message.toolCalls?.map(toTranscriptToolCall),
3018
+ start_time: message.startTime,
3019
+ end_time: message.endTime,
3020
+ duration_ms: message.durationMs,
3021
+ metadata: message.metadata,
3022
+ token_usage: toTranscriptTokenUsage(message.tokenUsage)
3023
+ });
3024
+ }
2834
3025
  function toTranscriptJsonLines(entry, options) {
2835
3026
  const source = {
2836
3027
  provider: entry.source.provider,
@@ -2853,25 +3044,93 @@ function toTranscriptJsonLines(entry, options) {
2853
3044
  test_id: testId,
2854
3045
  target,
2855
3046
  message_index: index,
2856
- ...toSnakeCaseDeep(message),
3047
+ ...toTranscriptMessageFields(message),
2857
3048
  transcript_token_usage: transcriptTokenUsage,
2858
3049
  transcript_duration_ms: entry.durationMs,
2859
3050
  transcript_cost_usd: entry.costUsd,
2860
3051
  source
2861
3052
  }));
2862
3053
  }
3054
+ function traceToTranscriptJsonLines(trace, options) {
3055
+ const provider = (typeof trace.metadata?.provider === "string" ? trace.metadata.provider : void 0) ?? options?.target ?? "agentv";
3056
+ const sessionId = (typeof trace.metadata?.provider_session_id === "string" ? trace.metadata.provider_session_id : void 0) ?? (typeof trace.metadata?.eval_case_id === "string" ? trace.metadata.eval_case_id : void 0) ?? options?.testId ?? "trace";
3057
+ return toTranscriptJsonLines(
3058
+ {
3059
+ messages: [...trace.messages],
3060
+ source: {
3061
+ provider,
3062
+ sessionId,
3063
+ startedAt: trace.startTime
3064
+ },
3065
+ tokenUsage: trace.tokenUsage,
3066
+ durationMs: trace.durationMs,
3067
+ costUsd: trace.costUsd
3068
+ },
3069
+ options
3070
+ );
3071
+ }
3072
+ function traceFromTranscriptJsonLines(lines) {
3073
+ const [entry] = groupTranscriptJsonLines(lines);
3074
+ if (!entry) {
3075
+ return buildTraceFromMessages();
3076
+ }
3077
+ return buildTraceFromMessages({
3078
+ output: entry.messages,
3079
+ tokenUsage: entry.tokenUsage,
3080
+ durationMs: entry.durationMs,
3081
+ costUsd: entry.costUsd ?? void 0,
3082
+ startTime: entry.source.startedAt,
3083
+ provider: entry.source.provider,
3084
+ target: entry.target,
3085
+ testId: entry.testId,
3086
+ conversationId: entry.source.sessionId
3087
+ });
3088
+ }
3089
+ function fromTranscriptTokenUsage(usage) {
3090
+ if (!usage) {
3091
+ return void 0;
3092
+ }
3093
+ return {
3094
+ input: usage.input,
3095
+ output: usage.output,
3096
+ cached: usage.cached,
3097
+ reasoning: usage.reasoning
3098
+ };
3099
+ }
3100
+ function readOptionalString(record, key) {
3101
+ const value = record[key];
3102
+ return typeof value === "string" ? value : void 0;
3103
+ }
3104
+ function readOptionalNumber(record, key) {
3105
+ const value = record[key];
3106
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
3107
+ }
3108
+ function fromTranscriptToolCall(wire) {
3109
+ const tool = readOptionalString(wire, "tool");
3110
+ if (!tool) {
3111
+ return void 0;
3112
+ }
3113
+ return {
3114
+ tool,
3115
+ input: wire.input,
3116
+ output: wire.output,
3117
+ id: readOptionalString(wire, "id"),
3118
+ startTime: readOptionalString(wire, "start_time"),
3119
+ endTime: readOptionalString(wire, "end_time"),
3120
+ durationMs: readOptionalNumber(wire, "duration_ms")
3121
+ };
3122
+ }
2863
3123
  function buildReplayMessage(line) {
2864
- const camelCased = toCamelCaseDeep(line);
2865
3124
  return {
2866
- role: camelCased.role,
2867
- name: camelCased.name,
2868
- content: camelCased.content,
2869
- toolCalls: camelCased.toolCalls,
2870
- startTime: camelCased.startTime,
2871
- endTime: camelCased.endTime,
2872
- durationMs: camelCased.durationMs,
2873
- metadata: camelCased.metadata,
2874
- tokenUsage: camelCased.tokenUsage
3125
+ role: line.role,
3126
+ name: line.name,
3127
+ content: line.content,
3128
+ toolCalls: line.tool_calls?.map(fromTranscriptToolCall).filter((toolCall) => toolCall !== void 0),
3129
+ startTime: line.start_time,
3130
+ endTime: line.end_time,
3131
+ durationMs: line.duration_ms,
3132
+ metadata: line.metadata,
3133
+ tokenUsage: fromTranscriptTokenUsage(line.token_usage)
2875
3134
  };
2876
3135
  }
2877
3136
  function groupTranscriptJsonLines(lines) {
@@ -2999,6 +3258,10 @@ export {
2999
3258
  pushResultsRepoBranch,
3000
3259
  createDraftResultsPr,
3001
3260
  directPushResults,
3261
+ buildWipBranchName,
3262
+ setupWipWorktree,
3263
+ pushWipCheckpoint,
3264
+ deleteWipBranch,
3002
3265
  listGitRuns,
3003
3266
  materializeGitRun,
3004
3267
  getProjectsRegistryPath,
@@ -3027,10 +3290,12 @@ export {
3027
3290
  discoverCodexSessions,
3028
3291
  discoverClaudeSessions,
3029
3292
  toTranscriptJsonLines,
3293
+ traceToTranscriptJsonLines,
3294
+ traceFromTranscriptJsonLines,
3030
3295
  groupTranscriptJsonLines,
3031
3296
  readTranscriptJsonl,
3032
3297
  readTranscriptFile,
3033
3298
  TranscriptProvider,
3034
3299
  createAgentKernel
3035
3300
  };
3036
- //# sourceMappingURL=chunk-KNF3AGCI.js.map
3301
+ //# sourceMappingURL=chunk-OYI35QFW.js.map