agentv 2.14.2 → 2.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,7 +11,7 @@ import {
11
11
  validateEvalFile,
12
12
  validateFileReferences,
13
13
  validateTargetsFile
14
- } from "./chunk-LHDGRK2S.js";
14
+ } from "./chunk-ZDSLKUCM.js";
15
15
  import {
16
16
  RepoManager,
17
17
  assembleLlmJudgePrompt,
@@ -20,13 +20,16 @@ import {
20
20
  createProvider,
21
21
  executeScript,
22
22
  generateRubrics,
23
+ getAgentvHome,
24
+ getGitCacheRoot,
25
+ getWorkspacePoolRoot,
23
26
  loadTestById,
24
27
  loadTests,
25
28
  normalizeLineEndings,
26
29
  toCamelCaseDeep,
27
30
  toSnakeCaseDeep,
28
31
  trimBaselineResult
29
- } from "./chunk-OQN2GDEU.js";
32
+ } from "./chunk-VBK7BJLE.js";
30
33
  import {
31
34
  __commonJS,
32
35
  __esm,
@@ -2938,7 +2941,7 @@ var cleanCommand = command({
2938
2941
  const readline2 = await import("node:readline");
2939
2942
  const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
2940
2943
  const answer = await new Promise((resolve2) => {
2941
- rl.question("Remove all cached git repos from ~/.agentv/git-cache/? [y/N] ", resolve2);
2944
+ rl.question(`Remove all cached git repos from ${getGitCacheRoot()}? [y/N] `, resolve2);
2942
2945
  });
2943
2946
  rl.close();
2944
2947
  if (answer.toLowerCase() !== "y") {
@@ -4048,6 +4051,15 @@ var evalRunCommand = command({
4048
4051
  long: "cleanup-workspaces",
4049
4052
  description: "Always cleanup temporary workspaces, even on failure"
4050
4053
  }),
4054
+ poolWorkspaces: flag({
4055
+ long: "pool-workspaces",
4056
+ description: "Reuse materialized workspaces across eval runs"
4057
+ }),
4058
+ workspace: option({
4059
+ type: optional(string),
4060
+ long: "workspace",
4061
+ description: "Use an existing directory as the workspace directly (skips clone/copy/pool)"
4062
+ }),
4051
4063
  otelFile: option({
4052
4064
  type: optional(string),
4053
4065
  long: "otel-file",
@@ -4087,7 +4099,7 @@ var evalRunCommand = command({
4087
4099
  },
4088
4100
  handler: async (args) => {
4089
4101
  if (args.evalPaths.length === 0 && process.stdin.isTTY) {
4090
- const { launchInteractiveWizard } = await import("./interactive-R22BRR6A.js");
4102
+ const { launchInteractiveWizard } = await import("./interactive-SSGXAAKA.js");
4091
4103
  await launchInteractiveWizard();
4092
4104
  return;
4093
4105
  }
@@ -4111,6 +4123,8 @@ var evalRunCommand = command({
4111
4123
  verbose: args.verbose,
4112
4124
  keepWorkspaces: args.keepWorkspaces,
4113
4125
  cleanupWorkspaces: args.cleanupWorkspaces,
4126
+ poolWorkspaces: args.poolWorkspaces,
4127
+ workspace: args.workspace,
4114
4128
  trace: false,
4115
4129
  otelFile: args.otelFile,
4116
4130
  traceFile: args.traceFile,
@@ -4333,9 +4347,9 @@ function readTemplatesRecursively(dir, relativePath) {
4333
4347
  const entries2 = readdirSync(dir);
4334
4348
  for (const entry of entries2) {
4335
4349
  const fullPath = path4.join(dir, entry);
4336
- const stat2 = statSync(fullPath);
4350
+ const stat3 = statSync(fullPath);
4337
4351
  const entryRelativePath = relativePath ? path4.join(relativePath, entry) : entry;
4338
- if (stat2.isDirectory()) {
4352
+ if (stat3.isDirectory()) {
4339
4353
  templates.push(...readTemplatesRecursively(fullPath, entryRelativePath));
4340
4354
  } else {
4341
4355
  const content = readFileSync3(fullPath, "utf-8");
@@ -4598,7 +4612,7 @@ function listResultFiles(cwd, limit) {
4598
4612
  for (const filename of files) {
4599
4613
  const filePath = path6.join(resultsDir, filename);
4600
4614
  try {
4601
- const stat2 = statSync2(filePath);
4615
+ const stat3 = statSync2(filePath);
4602
4616
  const results = loadResultFile(filePath);
4603
4617
  const testCount = results.length;
4604
4618
  const passCount = results.filter((r) => r.score >= 1).length;
@@ -4613,7 +4627,7 @@ function listResultFiles(cwd, limit) {
4613
4627
  testCount,
4614
4628
  passRate,
4615
4629
  avgScore,
4616
- sizeBytes: stat2.size
4630
+ sizeBytes: stat3.size
4617
4631
  });
4618
4632
  } catch {
4619
4633
  }
@@ -5643,19 +5657,192 @@ var validateCommand = command({
5643
5657
  }
5644
5658
  });
5645
5659
 
5660
+ // src/commands/workspace/clean.ts
5661
+ import { existsSync as existsSync3 } from "node:fs";
5662
+ import { readFile as readFile3, readdir as readdir2, rm } from "node:fs/promises";
5663
+ import path8 from "node:path";
5664
+ async function confirm(message) {
5665
+ const readline2 = await import("node:readline");
5666
+ const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
5667
+ const answer = await new Promise((resolve2) => {
5668
+ rl.question(`${message} [y/N] `, resolve2);
5669
+ });
5670
+ rl.close();
5671
+ return answer.toLowerCase() === "y";
5672
+ }
5673
+ var cleanCommand2 = command({
5674
+ name: "clean",
5675
+ description: "Remove workspace pool entries",
5676
+ args: {
5677
+ repo: option({
5678
+ type: optional(string),
5679
+ long: "repo",
5680
+ description: "Only remove pools containing this repo URL"
5681
+ }),
5682
+ force: flag({
5683
+ long: "force",
5684
+ short: "f",
5685
+ description: "Skip confirmation prompt"
5686
+ })
5687
+ },
5688
+ handler: async ({ repo, force }) => {
5689
+ const poolRoot = getWorkspacePoolRoot();
5690
+ if (!existsSync3(poolRoot)) {
5691
+ console.log("No workspace pool entries found.");
5692
+ return;
5693
+ }
5694
+ if (repo) {
5695
+ const entries2 = await readdir2(poolRoot, { withFileTypes: true });
5696
+ const poolDirs = entries2.filter((e) => e.isDirectory());
5697
+ const matchingDirs = [];
5698
+ for (const dir of poolDirs) {
5699
+ const poolDir = path8.join(poolRoot, dir.name);
5700
+ const metadataPath = path8.join(poolDir, "metadata.json");
5701
+ try {
5702
+ const raw = await readFile3(metadataPath, "utf-8");
5703
+ const metadata = JSON.parse(raw);
5704
+ const hasRepo = metadata.repos?.some((r) => {
5705
+ if (r.source.type === "git" && r.source.url) {
5706
+ return r.source.url.toLowerCase().includes(repo.toLowerCase());
5707
+ }
5708
+ return false;
5709
+ });
5710
+ if (hasRepo) {
5711
+ matchingDirs.push(poolDir);
5712
+ }
5713
+ } catch {
5714
+ }
5715
+ }
5716
+ if (matchingDirs.length === 0) {
5717
+ console.log(`No workspace pool entries found matching repo "${repo}".`);
5718
+ return;
5719
+ }
5720
+ if (!force) {
5721
+ const confirmed = await confirm(
5722
+ `Remove ${matchingDirs.length} pool entry(s) matching repo "${repo}"?`
5723
+ );
5724
+ if (!confirmed) {
5725
+ console.log("Cancelled.");
5726
+ return;
5727
+ }
5728
+ }
5729
+ for (const dir of matchingDirs) {
5730
+ await rm(dir, { recursive: true, force: true });
5731
+ console.log(`Removed: ${path8.basename(dir).slice(0, 12)}...`);
5732
+ }
5733
+ console.log("Done.");
5734
+ } else {
5735
+ if (!force) {
5736
+ const confirmed = await confirm(`Remove all workspace pool entries from ${poolRoot}?`);
5737
+ if (!confirmed) {
5738
+ console.log("Cancelled.");
5739
+ return;
5740
+ }
5741
+ }
5742
+ await rm(poolRoot, { recursive: true, force: true });
5743
+ console.log("Workspace pool cleaned.");
5744
+ }
5745
+ }
5746
+ });
5747
+
5748
+ // src/commands/workspace/list.ts
5749
+ import { existsSync as existsSync4 } from "node:fs";
5750
+ import { readFile as readFile4, readdir as readdir3, stat as stat2 } from "node:fs/promises";
5751
+ import path9 from "node:path";
5752
+ async function getDirectorySize(dirPath) {
5753
+ let totalSize = 0;
5754
+ try {
5755
+ const entries2 = await readdir3(dirPath, { withFileTypes: true });
5756
+ for (const entry of entries2) {
5757
+ const fullPath = path9.join(dirPath, entry.name);
5758
+ if (entry.isDirectory()) {
5759
+ totalSize += await getDirectorySize(fullPath);
5760
+ } else {
5761
+ const stats = await stat2(fullPath);
5762
+ totalSize += stats.size;
5763
+ }
5764
+ }
5765
+ } catch {
5766
+ }
5767
+ return totalSize;
5768
+ }
5769
+ function formatSize2(bytes) {
5770
+ if (bytes < 1024) return `${bytes} B`;
5771
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
5772
+ if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
5773
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
5774
+ }
5775
+ var listCommand = command({
5776
+ name: "list",
5777
+ description: "List workspace pool entries",
5778
+ args: {},
5779
+ handler: async () => {
5780
+ const poolRoot = getWorkspacePoolRoot();
5781
+ if (!existsSync4(poolRoot)) {
5782
+ console.log("No workspace pool entries found.");
5783
+ return;
5784
+ }
5785
+ const entries2 = await readdir3(poolRoot, { withFileTypes: true });
5786
+ const poolDirs = entries2.filter((e) => e.isDirectory());
5787
+ if (poolDirs.length === 0) {
5788
+ console.log("No workspace pool entries found.");
5789
+ return;
5790
+ }
5791
+ for (const dir of poolDirs) {
5792
+ const poolDir = path9.join(poolRoot, dir.name);
5793
+ const fingerprint = dir.name;
5794
+ const poolEntries = await readdir3(poolDir, { withFileTypes: true });
5795
+ const slots = poolEntries.filter((e) => e.isDirectory() && e.name.startsWith("slot-"));
5796
+ const metadataPath = path9.join(poolDir, "metadata.json");
5797
+ let metadata = null;
5798
+ try {
5799
+ const raw = await readFile4(metadataPath, "utf-8");
5800
+ metadata = JSON.parse(raw);
5801
+ } catch {
5802
+ }
5803
+ const size = await getDirectorySize(poolDir);
5804
+ console.log(` ${fingerprint.slice(0, 12)}...`);
5805
+ console.log(` Slots: ${slots.length}`);
5806
+ console.log(` Size: ${formatSize2(size)}`);
5807
+ if (metadata) {
5808
+ if (metadata.templatePath) {
5809
+ console.log(` Template: ${metadata.templatePath}`);
5810
+ }
5811
+ if (metadata.repos && metadata.repos.length > 0) {
5812
+ const repoSources = metadata.repos.map(
5813
+ (r) => r.source.type === "git" ? r.source.url : r.source.path
5814
+ );
5815
+ console.log(` Repos: ${repoSources.join(", ")}`);
5816
+ }
5817
+ console.log(` Created: ${metadata.createdAt}`);
5818
+ }
5819
+ console.log();
5820
+ }
5821
+ }
5822
+ });
5823
+
5824
+ // src/commands/workspace/index.ts
5825
+ var workspaceCommand = subcommands({
5826
+ name: "workspace",
5827
+ description: "Manage workspace pool",
5828
+ cmds: {
5829
+ list: listCommand,
5830
+ clean: cleanCommand2
5831
+ }
5832
+ });
5833
+
5646
5834
  // src/update-check.ts
5647
5835
  import { spawn as spawn2 } from "node:child_process";
5648
- import { readFile as readFile3 } from "node:fs/promises";
5649
- import { homedir } from "node:os";
5836
+ import { readFile as readFile5 } from "node:fs/promises";
5650
5837
  import { join as join2 } from "node:path";
5651
5838
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
5652
- var AGENTV_DIR = join2(homedir(), ".agentv");
5839
+ var AGENTV_DIR = getAgentvHome();
5653
5840
  var CACHE_FILE = "version-check.json";
5654
5841
  var NPM_REGISTRY_URL = "https://registry.npmjs.org/agentv/latest";
5655
- async function getCachedUpdateInfo(path8) {
5656
- const filePath = path8 ?? join2(AGENTV_DIR, CACHE_FILE);
5842
+ async function getCachedUpdateInfo(path10) {
5843
+ const filePath = path10 ?? join2(AGENTV_DIR, CACHE_FILE);
5657
5844
  try {
5658
- const raw = await readFile3(filePath, "utf-8");
5845
+ const raw = await readFile5(filePath, "utf-8");
5659
5846
  const data = JSON.parse(raw);
5660
5847
  if (typeof data.latestVersion === "string" && typeof data.lastCheckedAt === "string") {
5661
5848
  return data;
@@ -5747,7 +5934,8 @@ var app = subcommands({
5747
5934
  self: selfCommand,
5748
5935
  trace: traceCommand,
5749
5936
  trim: trimCommand,
5750
- validate: validateCommand
5937
+ validate: validateCommand,
5938
+ workspace: workspaceCommand
5751
5939
  }
5752
5940
  });
5753
5941
  var PROMPT_EVAL_SUBCOMMANDS = /* @__PURE__ */ new Set(["overview", "input", "judge"]);
@@ -5793,4 +5981,4 @@ export {
5793
5981
  preprocessArgv,
5794
5982
  runCli
5795
5983
  };
5796
- //# sourceMappingURL=chunk-IO5LMHZH.js.map
5984
+ //# sourceMappingURL=chunk-IKGJTJSU.js.map