@agentforge/cli 0.18.2 → 0.18.4

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.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Command } from 'commander';
2
2
  import chalk4 from 'chalk';
3
- import path12 from 'path';
3
+ import path11 from 'path';
4
4
  import ora from 'ora';
5
5
  import inquirer from 'inquirer';
6
6
  import fs from 'fs-extra';
@@ -274,7 +274,7 @@ async function promptToolSetup(defaults = {}) {
274
274
  };
275
275
  }
276
276
  var __filename$1 = fileURLToPath(import.meta.url);
277
- var __dirname$1 = path12.dirname(__filename$1);
277
+ var __dirname$1 = path11.dirname(__filename$1);
278
278
  async function ensureDir(dir) {
279
279
  await fs.ensureDir(dir);
280
280
  }
@@ -292,9 +292,9 @@ async function copyTemplate(templatePath, targetPath, replacements = {}) {
292
292
  throw new Error(`No files found in template: ${templatePath}`);
293
293
  }
294
294
  for (const file of files) {
295
- const sourcePath = path12.join(templatePath, file);
296
- const destPath = path12.join(targetPath, file);
297
- await fs.ensureDir(path12.dirname(destPath));
295
+ const sourcePath = path11.join(templatePath, file);
296
+ const destPath = path11.join(targetPath, file);
297
+ await fs.ensureDir(path11.dirname(destPath));
298
298
  let content = await fs.readFile(sourcePath, "utf-8");
299
299
  for (const [key, value] of Object.entries(replacements)) {
300
300
  content = content.replace(new RegExp(`{{${key}}}`, "g"), value);
@@ -318,11 +318,11 @@ async function readFile(filePath) {
318
318
  return fs.readFile(filePath, "utf-8");
319
319
  }
320
320
  async function writeFile(filePath, content) {
321
- await fs.ensureDir(path12.dirname(filePath));
321
+ await fs.ensureDir(path11.dirname(filePath));
322
322
  await fs.writeFile(filePath, content);
323
323
  }
324
324
  function getTemplatePath(template) {
325
- return path12.join(__dirname$1, "..", "templates", template);
325
+ return path11.join(__dirname$1, "..", "templates", template);
326
326
  }
327
327
  async function isEmptyDir(dir) {
328
328
  if (!await pathExists(dir)) {
@@ -332,13 +332,13 @@ async function isEmptyDir(dir) {
332
332
  return files.length === 0;
333
333
  }
334
334
  async function detectPackageManager(cwd = process.cwd()) {
335
- if (await fs.pathExists(path12.join(cwd, "pnpm-lock.yaml"))) {
335
+ if (await fs.pathExists(path11.join(cwd, "pnpm-lock.yaml"))) {
336
336
  return "pnpm";
337
337
  }
338
- if (await fs.pathExists(path12.join(cwd, "yarn.lock"))) {
338
+ if (await fs.pathExists(path11.join(cwd, "yarn.lock"))) {
339
339
  return "yarn";
340
340
  }
341
- if (await fs.pathExists(path12.join(cwd, "package-lock.json"))) {
341
+ if (await fs.pathExists(path11.join(cwd, "package-lock.json"))) {
342
342
  return "npm";
343
343
  }
344
344
  try {
@@ -446,7 +446,7 @@ pnpm-debug.log*
446
446
  .temp/
447
447
  .tmp/
448
448
  `;
449
- await fs.writeFile(path12.join(cwd, ".gitignore"), gitignore);
449
+ await fs.writeFile(path11.join(cwd, ".gitignore"), gitignore);
450
450
  }
451
451
  async function createInitialCommit(cwd) {
452
452
  await execa("git", ["add", "."], { cwd });
@@ -460,7 +460,7 @@ async function createCommand(projectName, options) {
460
460
  if (!projectName) {
461
461
  return exitWithCommandError("Project name is required");
462
462
  }
463
- const targetPath = path12.join(process.cwd(), projectName);
463
+ const targetPath = path11.join(process.cwd(), projectName);
464
464
  if (!await isEmptyDir(targetPath)) {
465
465
  return exitWithCommandError(`Directory ${projectName} already exists and is not empty`);
466
466
  }
@@ -489,7 +489,7 @@ async function createCommand(projectName, options) {
489
489
  });
490
490
  logger.succeedSpinner("Template files copied");
491
491
  logger.startSpinner("Updating package.json...");
492
- const packageJsonPath = path12.join(targetPath, "package.json");
492
+ const packageJsonPath = path11.join(targetPath, "package.json");
493
493
  const packageJson = await readJson(packageJsonPath);
494
494
  packageJson.name = answers.projectName;
495
495
  if (answers.author) {
@@ -657,8 +657,8 @@ async function agentCreateCommand(name, options) {
657
657
  logger.info(`Pattern: ${chalk4.cyan(answers.pattern)}`);
658
658
  logger.newLine();
659
659
  const cwd = process.cwd();
660
- const agentDir = path12.join(cwd, "src", "agents");
661
- const agentFile = path12.join(agentDir, `${answers.name}.ts`);
660
+ const agentDir = path11.join(cwd, "src", "agents");
661
+ const agentFile = path11.join(agentDir, `${answers.name}.ts`);
662
662
  logger.startSpinner("Creating agent file...");
663
663
  await ensureDir(agentDir);
664
664
  const agentContent = generateAgentContent(answers.name, answers.pattern, answers.description);
@@ -666,8 +666,8 @@ async function agentCreateCommand(name, options) {
666
666
  logger.succeedSpinner("Agent file created");
667
667
  if (answers.generateTests) {
668
668
  logger.startSpinner("Creating test file...");
669
- const testDir = path12.join(cwd, "tests", "agents");
670
- const testFile = path12.join(testDir, `${answers.name}.test.ts`);
669
+ const testDir = path11.join(cwd, "tests", "agents");
670
+ const testFile = path11.join(testDir, `${answers.name}.test.ts`);
671
671
  await ensureDir(testDir);
672
672
  const testContent = generateTestContent(answers.name, answers.pattern);
673
673
  await writeFile(testFile, testContent);
@@ -825,7 +825,7 @@ async function agentCreateReusableCommand(name, options) {
825
825
  logger.info(`Description: ${chalk4.gray(answers.description)}`);
826
826
  logger.newLine();
827
827
  const cwd = process.cwd();
828
- const agentDir = path12.join(cwd, answers.name);
828
+ const agentDir = path11.join(cwd, answers.name);
829
829
  const agentNameKebab = answers.name;
830
830
  const agentNamePascal = kebabToPascal(agentNameKebab);
831
831
  const agentNameCamel = kebabToCamel(agentNameKebab);
@@ -844,10 +844,10 @@ async function agentCreateReusableCommand(name, options) {
844
844
  logger.succeedSpinner("Agent structure created");
845
845
  logger.startSpinner("Organizing files...");
846
846
  const fs5 = await import('fs-extra');
847
- const srcDir = path12.join(agentDir, "src");
847
+ const srcDir = path11.join(agentDir, "src");
848
848
  await fs5.ensureDir(srcDir);
849
- await fs5.move(path12.join(agentDir, "index.ts"), path12.join(srcDir, "index.ts"));
850
- await fs5.move(path12.join(agentDir, "index.test.ts"), path12.join(srcDir, "index.test.ts"));
849
+ await fs5.move(path11.join(agentDir, "index.ts"), path11.join(srcDir, "index.ts"));
850
+ await fs5.move(path11.join(agentDir, "index.test.ts"), path11.join(srcDir, "index.test.ts"));
851
851
  logger.succeedSpinner("Files organized");
852
852
  logger.newLine();
853
853
  logger.success(chalk4.bold.green("\u2728 Reusable agent created successfully!"));
@@ -879,7 +879,7 @@ async function agentListCommand(options) {
879
879
  try {
880
880
  logger.header("\u{1F4CB} List Agents");
881
881
  const cwd = process.cwd();
882
- const agentDir = path12.join(cwd, "src", "agents");
882
+ const agentDir = path11.join(cwd, "src", "agents");
883
883
  const agentFiles = await findFiles("*.ts", agentDir);
884
884
  if (agentFiles.length === 0) {
885
885
  logger.warn("No agents found");
@@ -889,8 +889,8 @@ async function agentListCommand(options) {
889
889
  logger.info(`Found ${chalk4.cyan(agentFiles.length)} agent(s):
890
890
  `);
891
891
  for (const file of agentFiles) {
892
- const agentName = path12.basename(file, ".ts");
893
- const agentPath = path12.join(agentDir, file);
892
+ const agentName = path11.basename(file, ".ts");
893
+ const agentPath = path11.join(agentDir, file);
894
894
  if (options.verbose) {
895
895
  const content = await readFile(agentPath);
896
896
  const pattern = extractPattern(content);
@@ -929,17 +929,17 @@ function extractDescription(content) {
929
929
  const match = content.match(/\/\*\*\s*\n\s*\*\s*(.+?)\s*\n/);
930
930
  return match ? match[1] : null;
931
931
  }
932
- async function agentTestCommand(name, options) {
932
+ async function runNamedTestCommand(name, options, convention) {
933
933
  try {
934
- logger.header("\u{1F9EA} Test Agent");
934
+ logger.header(`\u{1F9EA} Test ${convention.noun}`);
935
935
  const cwd = process.cwd();
936
- const testFile = path12.join(cwd, "tests", "agents", `${name}.test.ts`);
936
+ const testFile = path11.join(cwd, "tests", convention.testDirectory, `${name}.test.ts`);
937
937
  if (!await pathExists(testFile)) {
938
938
  logger.error(`Test file not found: ${testFile}`);
939
- logger.info(`Create tests with: ${chalk4.cyan(`agentforge agent:create ${name} --test`)}`);
939
+ logger.info(`Create tests with: ${chalk4.cyan(convention.creationHint)}`);
940
940
  return exitWithCommandError(`Test file not found: ${testFile}`, { logError: false });
941
941
  }
942
- logger.info(`Testing agent: ${chalk4.cyan(name)}`);
942
+ logger.info(`Testing ${convention.noun.toLowerCase()}: ${chalk4.cyan(name)}`);
943
943
  logger.info(`Watch mode: ${options.watch ? "Yes" : "No"}`);
944
944
  logger.newLine();
945
945
  const packageManager = await detectPackageManager(cwd);
@@ -952,6 +952,15 @@ async function agentTestCommand(name, options) {
952
952
  return exitWithCommandError(error, { spinnerFailureText: "Tests failed" });
953
953
  }
954
954
  }
955
+
956
+ // src/commands/agent/test.ts
957
+ async function agentTestCommand(name, options) {
958
+ return runNamedTestCommand(name, options, {
959
+ noun: "Agent",
960
+ testDirectory: "agents",
961
+ creationHint: `agentforge agent:create ${name} --test`
962
+ });
963
+ }
955
964
  async function agentDeployCommand(name, options) {
956
965
  try {
957
966
  logger.header("\u{1F680} Deploy Agent");
@@ -1082,8 +1091,8 @@ function capitalize2(str) {
1082
1091
  return str.charAt(0).toUpperCase() + str.slice(1);
1083
1092
  }
1084
1093
  async function createSingleFileTool(cwd, answers) {
1085
- const toolDir = path12.join(cwd, "src", "tools");
1086
- const toolFile = path12.join(toolDir, `${answers.name}.ts`);
1094
+ const toolDir = path11.join(cwd, "src", "tools");
1095
+ const toolFile = path11.join(toolDir, `${answers.name}.ts`);
1087
1096
  logger.startSpinner("Creating tool file...");
1088
1097
  await ensureDir(toolDir);
1089
1098
  const toolContent = generateToolContent(answers.name, answers.category, answers.description);
@@ -1091,8 +1100,8 @@ async function createSingleFileTool(cwd, answers) {
1091
1100
  logger.succeedSpinner("Tool file created");
1092
1101
  if (answers.generateTests) {
1093
1102
  logger.startSpinner("Creating test file...");
1094
- const testDir = path12.join(cwd, "tests", "tools");
1095
- const testFile = path12.join(testDir, `${answers.name}.test.ts`);
1103
+ const testDir = path11.join(cwd, "tests", "tools");
1104
+ const testFile = path11.join(testDir, `${answers.name}.test.ts`);
1096
1105
  await ensureDir(testDir);
1097
1106
  const testContent = generateTestContent2(answers.name);
1098
1107
  await writeFile(testFile, testContent);
@@ -1100,7 +1109,7 @@ async function createSingleFileTool(cwd, answers) {
1100
1109
  }
1101
1110
  }
1102
1111
  async function createMultiFileTool(cwd, answers) {
1103
- const toolDir = path12.join(cwd, "src", "tools", answers.name);
1112
+ const toolDir = path11.join(cwd, "src", "tools", answers.name);
1104
1113
  logger.startSpinner("Creating tool directory structure...");
1105
1114
  await ensureDir(toolDir);
1106
1115
  const templatePath = getTemplatePath("tool-multi");
@@ -1117,7 +1126,7 @@ async function createMultiFileTool(cwd, answers) {
1117
1126
  if (!answers.generateTests) {
1118
1127
  logger.startSpinner("Cleaning up test files...");
1119
1128
  const fs5 = await import('fs-extra');
1120
- const testDir = path12.join(toolDir, "__tests__");
1129
+ const testDir = path11.join(toolDir, "__tests__");
1121
1130
  await fs5.remove(testDir);
1122
1131
  logger.succeedSpinner("Test files removed");
1123
1132
  }
@@ -1126,7 +1135,7 @@ async function toolListCommand(options) {
1126
1135
  try {
1127
1136
  logger.header("\u{1F4CB} List Tools");
1128
1137
  const cwd = process.cwd();
1129
- const toolDir = path12.join(cwd, "src", "tools");
1138
+ const toolDir = path11.join(cwd, "src", "tools");
1130
1139
  const toolFiles = await findFiles("*.ts", toolDir);
1131
1140
  if (toolFiles.length === 0) {
1132
1141
  logger.warn("No tools found");
@@ -1137,7 +1146,7 @@ async function toolListCommand(options) {
1137
1146
  if (options.category) {
1138
1147
  filteredTools = [];
1139
1148
  for (const file of toolFiles) {
1140
- const toolPath = path12.join(toolDir, file);
1149
+ const toolPath = path11.join(toolDir, file);
1141
1150
  const content = await readFile(toolPath);
1142
1151
  const category = extractCategory(content);
1143
1152
  if (category === options.category) {
@@ -1152,8 +1161,8 @@ async function toolListCommand(options) {
1152
1161
  logger.info(`Found ${chalk4.cyan(filteredTools.length)} tool(s):
1153
1162
  `);
1154
1163
  for (const file of filteredTools) {
1155
- const toolName = path12.basename(file, ".ts");
1156
- const toolPath = path12.join(toolDir, file);
1164
+ const toolName = path11.basename(file, ".ts");
1165
+ const toolPath = path11.join(toolDir, file);
1157
1166
  if (options.verbose) {
1158
1167
  const content = await readFile(toolPath);
1159
1168
  const category = extractCategory(content);
@@ -1187,38 +1196,24 @@ function extractDescription2(content) {
1187
1196
  const match = content.match(/\/\*\*\s*\n\s*\*\s*(.+?)\s*\n/);
1188
1197
  return match ? match[1] : null;
1189
1198
  }
1199
+
1200
+ // src/commands/tool/test.ts
1190
1201
  async function toolTestCommand(name, options) {
1191
- try {
1192
- logger.header("\u{1F9EA} Test Tool");
1193
- const cwd = process.cwd();
1194
- const testFile = path12.join(cwd, "tests", "tools", `${name}.test.ts`);
1195
- if (!await pathExists(testFile)) {
1196
- logger.error(`Test file not found: ${testFile}`);
1197
- logger.info(`Create tests with: ${chalk4.cyan(`agentforge tool:create ${name} --test`)}`);
1198
- return exitWithCommandError(`Test file not found: ${testFile}`, { logError: false });
1199
- }
1200
- logger.info(`Testing tool: ${chalk4.cyan(name)}`);
1201
- logger.info(`Watch mode: ${options.watch ? "Yes" : "No"}`);
1202
- logger.newLine();
1203
- const packageManager = await detectPackageManager(cwd);
1204
- logger.startSpinner("Running tests...");
1205
- const testCommand2 = options.watch ? "test:watch" : "test";
1206
- process.env.TEST_FILE = testFile;
1207
- await runScript(cwd, testCommand2, packageManager);
1208
- logger.succeedSpinner("Tests completed");
1209
- } catch (error) {
1210
- return exitWithCommandError(error, { spinnerFailureText: "Tests failed" });
1211
- }
1202
+ return runNamedTestCommand(name, options, {
1203
+ noun: "Tool",
1204
+ testDirectory: "tools",
1205
+ creationHint: `agentforge tool:create ${name} --test`
1206
+ });
1212
1207
  }
1213
1208
  async function resolveToolPath(name) {
1214
1209
  const cwd = process.cwd();
1215
1210
  const isScopedPackage = /^@[^/]+\/[^/]+$/.test(name);
1216
1211
  const isPath = !isScopedPackage && (name.includes("/") || name.includes("\\"));
1217
1212
  if (isPath) {
1218
- const absolutePath = path12.isAbsolute(name) ? name : path12.resolve(cwd, name);
1213
+ const absolutePath = path11.isAbsolute(name) ? name : path11.resolve(cwd, name);
1219
1214
  return validateToolPath(absolutePath, name);
1220
1215
  }
1221
- const cwdPackageJsonPath = path12.join(cwd, "package.json");
1216
+ const cwdPackageJsonPath = path11.join(cwd, "package.json");
1222
1217
  if (await fs.pathExists(cwdPackageJsonPath)) {
1223
1218
  const cwdPackageJson = await fs.readJson(cwdPackageJsonPath);
1224
1219
  if (cwdPackageJson.name === name || cwdPackageJson.name === `@agentforge/${name}`) {
@@ -1228,7 +1223,7 @@ async function resolveToolPath(name) {
1228
1223
  const possiblePaths = buildPossiblePaths(cwd, name, isScopedPackage);
1229
1224
  for (const possiblePath of possiblePaths) {
1230
1225
  if (await fs.pathExists(possiblePath)) {
1231
- const packageJsonPath = path12.join(possiblePath, "package.json");
1226
+ const packageJsonPath = path11.join(possiblePath, "package.json");
1232
1227
  if (await fs.pathExists(packageJsonPath)) {
1233
1228
  return validateToolPath(possiblePath, name);
1234
1229
  }
@@ -1239,7 +1234,7 @@ async function resolveToolPath(name) {
1239
1234
  logger.info("Tried the following locations:");
1240
1235
  logger.list([
1241
1236
  `Current directory (${cwd})`,
1242
- ...possiblePaths.map((possiblePath) => path12.relative(cwd, possiblePath) || ".")
1237
+ ...possiblePaths.map((possiblePath) => path11.relative(cwd, possiblePath) || ".")
1243
1238
  ]);
1244
1239
  logger.newLine();
1245
1240
  logger.info("Make sure you are either:");
@@ -1252,16 +1247,16 @@ async function resolveToolPath(name) {
1252
1247
  }
1253
1248
  function buildPossiblePaths(cwd, name, isScopedPackage) {
1254
1249
  const possiblePaths = [
1255
- path12.join(cwd, "tools", name),
1256
- path12.join(cwd, "packages", name),
1257
- path12.join(cwd, name)
1250
+ path11.join(cwd, "tools", name),
1251
+ path11.join(cwd, "packages", name),
1252
+ path11.join(cwd, name)
1258
1253
  ];
1259
1254
  if (isScopedPackage) {
1260
1255
  const unscopedName = name.split("/")[1];
1261
1256
  possiblePaths.push(
1262
- path12.join(cwd, "tools", unscopedName),
1263
- path12.join(cwd, "packages", unscopedName),
1264
- path12.join(cwd, unscopedName)
1257
+ path11.join(cwd, "tools", unscopedName),
1258
+ path11.join(cwd, "packages", unscopedName),
1259
+ path11.join(cwd, unscopedName)
1265
1260
  );
1266
1261
  }
1267
1262
  return possiblePaths;
@@ -1270,7 +1265,7 @@ async function validateToolPath(toolPath, expectedName) {
1270
1265
  if (!await fs.pathExists(toolPath)) {
1271
1266
  return exitWithCommandError(`Tool directory not found: ${toolPath}`);
1272
1267
  }
1273
- const packageJsonPath = path12.join(toolPath, "package.json");
1268
+ const packageJsonPath = path11.join(toolPath, "package.json");
1274
1269
  if (!await fs.pathExists(packageJsonPath)) {
1275
1270
  logger.info("Tool packages must have a package.json file");
1276
1271
  return exitWithCommandError(`package.json not found in: ${toolPath}`);