@agentforge/cli 0.1.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.
- package/README.md +225 -0
- package/bin/agentforge.js +9 -0
- package/dist/index.cjs +1114 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1103 -0
- package/dist/index.js.map +1 -0
- package/package.json +81 -0
- package/templates/README.md +163 -0
- package/templates/api/.env.example +13 -0
- package/templates/api/README.md +153 -0
- package/templates/api/package.json +41 -0
- package/templates/api/src/routes/agent.ts +54 -0
- package/templates/api/src/routes/health.ts +15 -0
- package/templates/api/src/server.ts +41 -0
- package/templates/api/tsconfig.json +10 -0
- package/templates/cli/.env.example +13 -0
- package/templates/cli/README.md +164 -0
- package/templates/cli/package.json +44 -0
- package/templates/cli/src/cli.ts +31 -0
- package/templates/cli/src/commands/analyze.ts +65 -0
- package/templates/cli/src/commands/chat.ts +65 -0
- package/templates/cli/tsconfig.json +10 -0
- package/templates/full/.env.example +13 -0
- package/templates/full/README.md +151 -0
- package/templates/full/package.json +40 -0
- package/templates/full/src/index.ts +53 -0
- package/templates/full/src/tools/example.ts +20 -0
- package/templates/full/tests/example.test.ts +17 -0
- package/templates/full/tsconfig.json +10 -0
- package/templates/minimal/README.md +64 -0
- package/templates/minimal/package.json +35 -0
- package/templates/minimal/src/index.ts +40 -0
- package/templates/minimal/tsconfig.json +10 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1114 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var commander = require('commander');
|
|
4
|
+
var chalk = require('chalk');
|
|
5
|
+
var path = require('path');
|
|
6
|
+
var ora = require('ora');
|
|
7
|
+
var inquirer = require('inquirer');
|
|
8
|
+
var fs = require('fs-extra');
|
|
9
|
+
var glob = require('glob');
|
|
10
|
+
var execa = require('execa');
|
|
11
|
+
|
|
12
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
|
+
|
|
14
|
+
var chalk__default = /*#__PURE__*/_interopDefault(chalk);
|
|
15
|
+
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
16
|
+
var ora__default = /*#__PURE__*/_interopDefault(ora);
|
|
17
|
+
var inquirer__default = /*#__PURE__*/_interopDefault(inquirer);
|
|
18
|
+
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var Logger = class {
|
|
22
|
+
spinner = null;
|
|
23
|
+
info(message) {
|
|
24
|
+
console.log(chalk__default.default.blue("\u2139"), message);
|
|
25
|
+
}
|
|
26
|
+
success(message) {
|
|
27
|
+
console.log(chalk__default.default.green("\u2714"), message);
|
|
28
|
+
}
|
|
29
|
+
warn(message) {
|
|
30
|
+
console.log(chalk__default.default.yellow("\u26A0"), message);
|
|
31
|
+
}
|
|
32
|
+
error(message) {
|
|
33
|
+
console.log(chalk__default.default.red("\u2716"), message);
|
|
34
|
+
}
|
|
35
|
+
debug(message) {
|
|
36
|
+
if (process.env.DEBUG) {
|
|
37
|
+
console.log(chalk__default.default.gray("\u{1F41B}"), message);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
startSpinner(message) {
|
|
41
|
+
this.spinner = ora__default.default(message).start();
|
|
42
|
+
}
|
|
43
|
+
updateSpinner(message) {
|
|
44
|
+
if (this.spinner) {
|
|
45
|
+
this.spinner.text = message;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
succeedSpinner(message) {
|
|
49
|
+
if (this.spinner) {
|
|
50
|
+
this.spinner.succeed(message);
|
|
51
|
+
this.spinner = null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
failSpinner(message) {
|
|
55
|
+
if (this.spinner) {
|
|
56
|
+
this.spinner.fail(message);
|
|
57
|
+
this.spinner = null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
stopSpinner() {
|
|
61
|
+
if (this.spinner) {
|
|
62
|
+
this.spinner.stop();
|
|
63
|
+
this.spinner = null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
newLine() {
|
|
67
|
+
console.log();
|
|
68
|
+
}
|
|
69
|
+
divider() {
|
|
70
|
+
console.log(chalk__default.default.gray("\u2500".repeat(50)));
|
|
71
|
+
}
|
|
72
|
+
header(message) {
|
|
73
|
+
this.newLine();
|
|
74
|
+
console.log(chalk__default.default.bold.cyan(message));
|
|
75
|
+
this.divider();
|
|
76
|
+
}
|
|
77
|
+
code(code) {
|
|
78
|
+
console.log(chalk__default.default.gray(" " + code));
|
|
79
|
+
}
|
|
80
|
+
list(items) {
|
|
81
|
+
items.forEach((item) => {
|
|
82
|
+
console.log(chalk__default.default.gray(" \u2022"), item);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var logger = new Logger();
|
|
87
|
+
async function promptProjectSetup(defaults = {}) {
|
|
88
|
+
return inquirer__default.default.prompt([
|
|
89
|
+
{
|
|
90
|
+
type: "input",
|
|
91
|
+
name: "projectName",
|
|
92
|
+
message: "Project name:",
|
|
93
|
+
default: defaults.projectName || "my-agent",
|
|
94
|
+
validate: (input) => {
|
|
95
|
+
if (!input) return "Project name is required";
|
|
96
|
+
if (!/^[a-z0-9-]+$/.test(input)) {
|
|
97
|
+
return "Project name must contain only lowercase letters, numbers, and hyphens";
|
|
98
|
+
}
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: "list",
|
|
104
|
+
name: "template",
|
|
105
|
+
message: "Select a template:",
|
|
106
|
+
choices: [
|
|
107
|
+
{ name: "Minimal Starter - Basic ReAct agent", value: "minimal" },
|
|
108
|
+
{ name: "Full-Featured App - Multi-agent system with all features", value: "full" },
|
|
109
|
+
{ name: "API Service - Express/Fastify API with agents", value: "api" },
|
|
110
|
+
{ name: "CLI Tool - Command-line agent application", value: "cli" }
|
|
111
|
+
],
|
|
112
|
+
default: defaults.template || "minimal"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
type: "list",
|
|
116
|
+
name: "packageManager",
|
|
117
|
+
message: "Package manager:",
|
|
118
|
+
choices: ["pnpm", "npm", "yarn"],
|
|
119
|
+
default: defaults.packageManager || "pnpm"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
type: "confirm",
|
|
123
|
+
name: "installDependencies",
|
|
124
|
+
message: "Install dependencies?",
|
|
125
|
+
default: defaults.installDependencies !== false
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
type: "confirm",
|
|
129
|
+
name: "initGit",
|
|
130
|
+
message: "Initialize git repository?",
|
|
131
|
+
default: defaults.initGit !== false
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
type: "input",
|
|
135
|
+
name: "author",
|
|
136
|
+
message: "Author name (optional):",
|
|
137
|
+
default: defaults.author
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
type: "input",
|
|
141
|
+
name: "description",
|
|
142
|
+
message: "Project description (optional):",
|
|
143
|
+
default: defaults.description
|
|
144
|
+
}
|
|
145
|
+
]);
|
|
146
|
+
}
|
|
147
|
+
async function promptAgentSetup(defaults = {}) {
|
|
148
|
+
return inquirer__default.default.prompt([
|
|
149
|
+
{
|
|
150
|
+
type: "input",
|
|
151
|
+
name: "name",
|
|
152
|
+
message: "Agent name:",
|
|
153
|
+
default: defaults.name,
|
|
154
|
+
validate: (input) => {
|
|
155
|
+
if (!input) return "Agent name is required";
|
|
156
|
+
if (!/^[a-zA-Z][a-zA-Z0-9]*$/.test(input)) {
|
|
157
|
+
return "Agent name must start with a letter and contain only letters and numbers";
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: "list",
|
|
164
|
+
name: "pattern",
|
|
165
|
+
message: "Agent pattern:",
|
|
166
|
+
choices: [
|
|
167
|
+
{ name: "ReAct - Reasoning and Acting", value: "react" },
|
|
168
|
+
{ name: "Plan-Execute - Planning and Execution", value: "plan-execute" },
|
|
169
|
+
{ name: "Reflection - Generate, Reflect, Revise", value: "reflection" },
|
|
170
|
+
{ name: "Multi-Agent - Supervisor and Workers", value: "multi-agent" }
|
|
171
|
+
],
|
|
172
|
+
default: defaults.pattern || "react"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
type: "input",
|
|
176
|
+
name: "description",
|
|
177
|
+
message: "Agent description (optional):",
|
|
178
|
+
default: defaults.description
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
type: "confirm",
|
|
182
|
+
name: "generateTests",
|
|
183
|
+
message: "Generate tests?",
|
|
184
|
+
default: defaults.generateTests !== false
|
|
185
|
+
}
|
|
186
|
+
]);
|
|
187
|
+
}
|
|
188
|
+
async function promptToolSetup(defaults = {}) {
|
|
189
|
+
return inquirer__default.default.prompt([
|
|
190
|
+
{
|
|
191
|
+
type: "input",
|
|
192
|
+
name: "name",
|
|
193
|
+
message: "Tool name:",
|
|
194
|
+
default: defaults.name,
|
|
195
|
+
validate: (input) => {
|
|
196
|
+
if (!input) return "Tool name is required";
|
|
197
|
+
if (!/^[a-zA-Z][a-zA-Z0-9]*$/.test(input)) {
|
|
198
|
+
return "Tool name must start with a letter and contain only letters and numbers";
|
|
199
|
+
}
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
type: "list",
|
|
205
|
+
name: "category",
|
|
206
|
+
message: "Tool category:",
|
|
207
|
+
choices: [
|
|
208
|
+
{ name: "Web - HTTP, scraping, parsing", value: "web" },
|
|
209
|
+
{ name: "Data - JSON, CSV, XML processing", value: "data" },
|
|
210
|
+
{ name: "File - File operations", value: "file" },
|
|
211
|
+
{ name: "Utility - General utilities", value: "utility" }
|
|
212
|
+
],
|
|
213
|
+
default: defaults.category || "utility"
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
type: "input",
|
|
217
|
+
name: "description",
|
|
218
|
+
message: "Tool description:",
|
|
219
|
+
default: defaults.description,
|
|
220
|
+
validate: (input) => {
|
|
221
|
+
if (!input) return "Tool description is required";
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
type: "confirm",
|
|
227
|
+
name: "generateTests",
|
|
228
|
+
message: "Generate tests?",
|
|
229
|
+
default: defaults.generateTests !== false
|
|
230
|
+
}
|
|
231
|
+
]);
|
|
232
|
+
}
|
|
233
|
+
async function ensureDir(dir) {
|
|
234
|
+
await fs__default.default.ensureDir(dir);
|
|
235
|
+
}
|
|
236
|
+
async function copyTemplate(templatePath, targetPath, replacements = {}) {
|
|
237
|
+
await fs__default.default.ensureDir(targetPath);
|
|
238
|
+
const files = await glob.glob("**/*", {
|
|
239
|
+
cwd: templatePath,
|
|
240
|
+
dot: true,
|
|
241
|
+
nodir: true
|
|
242
|
+
});
|
|
243
|
+
for (const file of files) {
|
|
244
|
+
const sourcePath = path__default.default.join(templatePath, file);
|
|
245
|
+
const destPath = path__default.default.join(targetPath, file);
|
|
246
|
+
await fs__default.default.ensureDir(path__default.default.dirname(destPath));
|
|
247
|
+
let content = await fs__default.default.readFile(sourcePath, "utf-8");
|
|
248
|
+
for (const [key, value] of Object.entries(replacements)) {
|
|
249
|
+
content = content.replace(new RegExp(`{{${key}}}`, "g"), value);
|
|
250
|
+
}
|
|
251
|
+
await fs__default.default.writeFile(destPath, content);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
async function writeJson(filePath, data) {
|
|
255
|
+
await fs__default.default.writeJson(filePath, data, { spaces: 2 });
|
|
256
|
+
}
|
|
257
|
+
async function readJson(filePath) {
|
|
258
|
+
return fs__default.default.readJson(filePath);
|
|
259
|
+
}
|
|
260
|
+
async function pathExists(filePath) {
|
|
261
|
+
return fs__default.default.pathExists(filePath);
|
|
262
|
+
}
|
|
263
|
+
async function findFiles(pattern, cwd = process.cwd()) {
|
|
264
|
+
return glob.glob(pattern, { cwd });
|
|
265
|
+
}
|
|
266
|
+
async function readFile(filePath) {
|
|
267
|
+
return fs__default.default.readFile(filePath, "utf-8");
|
|
268
|
+
}
|
|
269
|
+
async function writeFile(filePath, content) {
|
|
270
|
+
await fs__default.default.ensureDir(path__default.default.dirname(filePath));
|
|
271
|
+
await fs__default.default.writeFile(filePath, content);
|
|
272
|
+
}
|
|
273
|
+
function getTemplatePath(template) {
|
|
274
|
+
return path__default.default.join(__dirname, "..", "..", "templates", template);
|
|
275
|
+
}
|
|
276
|
+
async function isEmptyDir(dir) {
|
|
277
|
+
if (!await pathExists(dir)) {
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
const files = await fs__default.default.readdir(dir);
|
|
281
|
+
return files.length === 0;
|
|
282
|
+
}
|
|
283
|
+
async function detectPackageManager(cwd = process.cwd()) {
|
|
284
|
+
if (await fs__default.default.pathExists(path__default.default.join(cwd, "pnpm-lock.yaml"))) {
|
|
285
|
+
return "pnpm";
|
|
286
|
+
}
|
|
287
|
+
if (await fs__default.default.pathExists(path__default.default.join(cwd, "yarn.lock"))) {
|
|
288
|
+
return "yarn";
|
|
289
|
+
}
|
|
290
|
+
if (await fs__default.default.pathExists(path__default.default.join(cwd, "package-lock.json"))) {
|
|
291
|
+
return "npm";
|
|
292
|
+
}
|
|
293
|
+
try {
|
|
294
|
+
await execa.execa("pnpm", ["--version"]);
|
|
295
|
+
return "pnpm";
|
|
296
|
+
} catch {
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
await execa.execa("yarn", ["--version"]);
|
|
300
|
+
return "yarn";
|
|
301
|
+
} catch {
|
|
302
|
+
}
|
|
303
|
+
return "npm";
|
|
304
|
+
}
|
|
305
|
+
async function installDependencies(cwd, packageManager = "pnpm") {
|
|
306
|
+
const commands = {
|
|
307
|
+
npm: ["install"],
|
|
308
|
+
pnpm: ["install"],
|
|
309
|
+
yarn: ["install"]
|
|
310
|
+
};
|
|
311
|
+
await execa.execa(packageManager, commands[packageManager], {
|
|
312
|
+
cwd,
|
|
313
|
+
stdio: "inherit"
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
async function runScript(cwd, script, packageManager = "pnpm") {
|
|
317
|
+
const commands = {
|
|
318
|
+
npm: ["run", script],
|
|
319
|
+
pnpm: ["run", script],
|
|
320
|
+
yarn: ["run", script]
|
|
321
|
+
};
|
|
322
|
+
await execa.execa(packageManager, commands[packageManager], {
|
|
323
|
+
cwd,
|
|
324
|
+
stdio: "inherit"
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
function getRunCommand(packageManager, script) {
|
|
328
|
+
const commands = {
|
|
329
|
+
npm: `npm run ${script}`,
|
|
330
|
+
pnpm: `pnpm ${script}`,
|
|
331
|
+
yarn: `yarn ${script}`
|
|
332
|
+
};
|
|
333
|
+
return commands[packageManager];
|
|
334
|
+
}
|
|
335
|
+
async function isGitInstalled() {
|
|
336
|
+
try {
|
|
337
|
+
await execa.execa("git", ["--version"]);
|
|
338
|
+
return true;
|
|
339
|
+
} catch {
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
async function initGitRepository(cwd) {
|
|
344
|
+
await execa.execa("git", ["init"], { cwd });
|
|
345
|
+
const gitignore = `# Dependencies
|
|
346
|
+
node_modules/
|
|
347
|
+
.pnp
|
|
348
|
+
.pnp.js
|
|
349
|
+
|
|
350
|
+
# Testing
|
|
351
|
+
coverage/
|
|
352
|
+
.nyc_output/
|
|
353
|
+
|
|
354
|
+
# Production
|
|
355
|
+
dist/
|
|
356
|
+
build/
|
|
357
|
+
|
|
358
|
+
# Environment
|
|
359
|
+
.env
|
|
360
|
+
.env.local
|
|
361
|
+
.env.*.local
|
|
362
|
+
|
|
363
|
+
# IDE
|
|
364
|
+
.vscode/
|
|
365
|
+
.idea/
|
|
366
|
+
*.swp
|
|
367
|
+
*.swo
|
|
368
|
+
*~
|
|
369
|
+
|
|
370
|
+
# OS
|
|
371
|
+
.DS_Store
|
|
372
|
+
Thumbs.db
|
|
373
|
+
|
|
374
|
+
# Logs
|
|
375
|
+
logs/
|
|
376
|
+
*.log
|
|
377
|
+
npm-debug.log*
|
|
378
|
+
yarn-debug.log*
|
|
379
|
+
yarn-error.log*
|
|
380
|
+
pnpm-debug.log*
|
|
381
|
+
|
|
382
|
+
# Misc
|
|
383
|
+
.cache/
|
|
384
|
+
.temp/
|
|
385
|
+
.tmp/
|
|
386
|
+
`;
|
|
387
|
+
await fs__default.default.writeFile(path__default.default.join(cwd, ".gitignore"), gitignore);
|
|
388
|
+
}
|
|
389
|
+
async function createInitialCommit(cwd) {
|
|
390
|
+
await execa.execa("git", ["add", "."], { cwd });
|
|
391
|
+
await execa.execa("git", ["commit", "-m", "Initial commit from AgentForge CLI"], { cwd });
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// src/commands/create.ts
|
|
395
|
+
async function createCommand(projectName, options) {
|
|
396
|
+
try {
|
|
397
|
+
logger.header("\u{1F680} Create AgentForge Project");
|
|
398
|
+
if (!projectName) {
|
|
399
|
+
logger.error("Project name is required");
|
|
400
|
+
process.exit(1);
|
|
401
|
+
}
|
|
402
|
+
const targetPath = path__default.default.join(process.cwd(), projectName);
|
|
403
|
+
if (!await isEmptyDir(targetPath)) {
|
|
404
|
+
logger.error(`Directory ${projectName} already exists and is not empty`);
|
|
405
|
+
process.exit(1);
|
|
406
|
+
}
|
|
407
|
+
const answers = await promptProjectSetup({
|
|
408
|
+
projectName,
|
|
409
|
+
template: options.template,
|
|
410
|
+
packageManager: options.packageManager,
|
|
411
|
+
installDependencies: options.install,
|
|
412
|
+
initGit: options.git
|
|
413
|
+
});
|
|
414
|
+
logger.newLine();
|
|
415
|
+
logger.info(`Creating project: ${chalk__default.default.cyan(answers.projectName)}`);
|
|
416
|
+
logger.info(`Template: ${chalk__default.default.cyan(answers.template)}`);
|
|
417
|
+
logger.info(`Package manager: ${chalk__default.default.cyan(answers.packageManager)}`);
|
|
418
|
+
logger.newLine();
|
|
419
|
+
logger.startSpinner("Creating project directory...");
|
|
420
|
+
await ensureDir(targetPath);
|
|
421
|
+
logger.succeedSpinner("Project directory created");
|
|
422
|
+
logger.startSpinner("Copying template files...");
|
|
423
|
+
const templatePath = getTemplatePath(answers.template);
|
|
424
|
+
await copyTemplate(templatePath, targetPath, {
|
|
425
|
+
PROJECT_NAME: answers.projectName,
|
|
426
|
+
AUTHOR: answers.author || "",
|
|
427
|
+
DESCRIPTION: answers.description || `AgentForge project created with ${answers.template} template`,
|
|
428
|
+
PACKAGE_MANAGER: answers.packageManager
|
|
429
|
+
});
|
|
430
|
+
logger.succeedSpinner("Template files copied");
|
|
431
|
+
logger.startSpinner("Updating package.json...");
|
|
432
|
+
const packageJsonPath = path__default.default.join(targetPath, "package.json");
|
|
433
|
+
const packageJson = await readJson(packageJsonPath);
|
|
434
|
+
packageJson.name = answers.projectName;
|
|
435
|
+
if (answers.author) {
|
|
436
|
+
packageJson.author = answers.author;
|
|
437
|
+
}
|
|
438
|
+
if (answers.description) {
|
|
439
|
+
packageJson.description = answers.description;
|
|
440
|
+
}
|
|
441
|
+
await writeJson(packageJsonPath, packageJson);
|
|
442
|
+
logger.succeedSpinner("package.json updated");
|
|
443
|
+
if (answers.installDependencies) {
|
|
444
|
+
logger.startSpinner("Installing dependencies...");
|
|
445
|
+
try {
|
|
446
|
+
await installDependencies(targetPath, answers.packageManager);
|
|
447
|
+
logger.succeedSpinner("Dependencies installed");
|
|
448
|
+
} catch (error) {
|
|
449
|
+
logger.failSpinner("Failed to install dependencies");
|
|
450
|
+
logger.warn("You can install them manually later");
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
if (answers.initGit && await isGitInstalled()) {
|
|
454
|
+
logger.startSpinner("Initializing git repository...");
|
|
455
|
+
try {
|
|
456
|
+
await initGitRepository(targetPath);
|
|
457
|
+
await createInitialCommit(targetPath);
|
|
458
|
+
logger.succeedSpinner("Git repository initialized");
|
|
459
|
+
} catch (error) {
|
|
460
|
+
logger.failSpinner("Failed to initialize git");
|
|
461
|
+
logger.warn("You can initialize it manually later");
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
logger.newLine();
|
|
465
|
+
logger.success(chalk__default.default.bold.green("\u2728 Project created successfully!"));
|
|
466
|
+
logger.newLine();
|
|
467
|
+
logger.header("\u{1F4DD} Next Steps");
|
|
468
|
+
logger.list([
|
|
469
|
+
`cd ${answers.projectName}`,
|
|
470
|
+
answers.installDependencies ? getRunCommand(answers.packageManager, "dev") : `${answers.packageManager} install`
|
|
471
|
+
]);
|
|
472
|
+
logger.newLine();
|
|
473
|
+
logger.info("Happy coding! \u{1F389}");
|
|
474
|
+
} catch (error) {
|
|
475
|
+
logger.error(`Failed to create project: ${error.message}`);
|
|
476
|
+
process.exit(1);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// src/commands/dev.ts
|
|
481
|
+
async function devCommand(options) {
|
|
482
|
+
try {
|
|
483
|
+
logger.header("\u{1F680} Starting Development Server");
|
|
484
|
+
const cwd = process.cwd();
|
|
485
|
+
const packageManager = await detectPackageManager(cwd);
|
|
486
|
+
logger.info(`Port: ${options.port || "3000"}`);
|
|
487
|
+
logger.info(`Package manager: ${packageManager}`);
|
|
488
|
+
logger.newLine();
|
|
489
|
+
logger.startSpinner("Starting development server...");
|
|
490
|
+
if (options.port) {
|
|
491
|
+
process.env.PORT = options.port;
|
|
492
|
+
}
|
|
493
|
+
await runScript(cwd, "dev", packageManager);
|
|
494
|
+
logger.succeedSpinner("Development server started");
|
|
495
|
+
} catch (error) {
|
|
496
|
+
logger.failSpinner("Failed to start development server");
|
|
497
|
+
logger.error(error.message);
|
|
498
|
+
process.exit(1);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// src/commands/build.ts
|
|
503
|
+
async function buildCommand(options) {
|
|
504
|
+
try {
|
|
505
|
+
logger.header("\u{1F4E6} Building for Production");
|
|
506
|
+
const cwd = process.cwd();
|
|
507
|
+
const packageManager = await detectPackageManager(cwd);
|
|
508
|
+
logger.info(`Minify: ${options.minify !== false ? "Yes" : "No"}`);
|
|
509
|
+
logger.info(`Sourcemap: ${options.sourcemap !== false ? "Yes" : "No"}`);
|
|
510
|
+
logger.newLine();
|
|
511
|
+
logger.startSpinner("Building project...");
|
|
512
|
+
process.env.NODE_ENV = "production";
|
|
513
|
+
if (options.minify === false) {
|
|
514
|
+
process.env.NO_MINIFY = "true";
|
|
515
|
+
}
|
|
516
|
+
if (options.sourcemap === false) {
|
|
517
|
+
process.env.NO_SOURCEMAP = "true";
|
|
518
|
+
}
|
|
519
|
+
await runScript(cwd, "build", packageManager);
|
|
520
|
+
logger.succeedSpinner("Build completed successfully");
|
|
521
|
+
logger.newLine();
|
|
522
|
+
logger.success("\u2728 Production build ready!");
|
|
523
|
+
} catch (error) {
|
|
524
|
+
logger.failSpinner("Build failed");
|
|
525
|
+
logger.error(error.message);
|
|
526
|
+
process.exit(1);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// src/commands/test.ts
|
|
531
|
+
async function testCommand(options) {
|
|
532
|
+
try {
|
|
533
|
+
logger.header("\u{1F9EA} Running Tests");
|
|
534
|
+
const cwd = process.cwd();
|
|
535
|
+
const packageManager = await detectPackageManager(cwd);
|
|
536
|
+
logger.info(`Watch mode: ${options.watch ? "Yes" : "No"}`);
|
|
537
|
+
logger.info(`UI: ${options.ui ? "Yes" : "No"}`);
|
|
538
|
+
logger.info(`Coverage: ${options.coverage ? "Yes" : "No"}`);
|
|
539
|
+
logger.newLine();
|
|
540
|
+
logger.startSpinner("Running tests...");
|
|
541
|
+
let script = "test";
|
|
542
|
+
if (options.ui) {
|
|
543
|
+
script = "test:ui";
|
|
544
|
+
} else if (options.coverage) {
|
|
545
|
+
script = "test:coverage";
|
|
546
|
+
} else if (options.watch) {
|
|
547
|
+
script = "test:watch";
|
|
548
|
+
}
|
|
549
|
+
await runScript(cwd, script, packageManager);
|
|
550
|
+
logger.succeedSpinner("Tests completed");
|
|
551
|
+
} catch (error) {
|
|
552
|
+
logger.failSpinner("Tests failed");
|
|
553
|
+
logger.error(error.message);
|
|
554
|
+
process.exit(1);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// src/commands/lint.ts
|
|
559
|
+
async function lintCommand(options) {
|
|
560
|
+
try {
|
|
561
|
+
logger.header("\u{1F50D} Linting Code");
|
|
562
|
+
const cwd = process.cwd();
|
|
563
|
+
const packageManager = await detectPackageManager(cwd);
|
|
564
|
+
logger.info(`Auto-fix: ${options.fix ? "Yes" : "No"}`);
|
|
565
|
+
logger.info(`Format: ${options.format !== false ? "Yes" : "No"}`);
|
|
566
|
+
logger.newLine();
|
|
567
|
+
logger.startSpinner("Running linter...");
|
|
568
|
+
try {
|
|
569
|
+
await runScript(cwd, options.fix ? "lint:fix" : "lint", packageManager);
|
|
570
|
+
logger.succeedSpinner("Linting completed");
|
|
571
|
+
} catch (error) {
|
|
572
|
+
logger.failSpinner("Linting found issues");
|
|
573
|
+
if (!options.fix) {
|
|
574
|
+
logger.info("Run with --fix to automatically fix issues");
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
if (options.format !== false) {
|
|
578
|
+
logger.startSpinner("Formatting code...");
|
|
579
|
+
try {
|
|
580
|
+
await runScript(cwd, "format", packageManager);
|
|
581
|
+
logger.succeedSpinner("Formatting completed");
|
|
582
|
+
} catch (error) {
|
|
583
|
+
logger.failSpinner("Formatting failed");
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
logger.newLine();
|
|
587
|
+
logger.success("\u2728 Code quality check completed!");
|
|
588
|
+
} catch (error) {
|
|
589
|
+
logger.error(error.message);
|
|
590
|
+
process.exit(1);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
async function agentCreateCommand(name, options) {
|
|
594
|
+
try {
|
|
595
|
+
logger.header("\u{1F916} Create Agent");
|
|
596
|
+
const answers = await promptAgentSetup({
|
|
597
|
+
name,
|
|
598
|
+
pattern: options.pattern,
|
|
599
|
+
generateTests: options.test
|
|
600
|
+
});
|
|
601
|
+
logger.newLine();
|
|
602
|
+
logger.info(`Creating agent: ${chalk__default.default.cyan(answers.name)}`);
|
|
603
|
+
logger.info(`Pattern: ${chalk__default.default.cyan(answers.pattern)}`);
|
|
604
|
+
logger.newLine();
|
|
605
|
+
const cwd = process.cwd();
|
|
606
|
+
const agentDir = path__default.default.join(cwd, "src", "agents");
|
|
607
|
+
const agentFile = path__default.default.join(agentDir, `${answers.name}.ts`);
|
|
608
|
+
logger.startSpinner("Creating agent file...");
|
|
609
|
+
await ensureDir(agentDir);
|
|
610
|
+
const agentContent = generateAgentContent(answers.name, answers.pattern, answers.description);
|
|
611
|
+
await writeFile(agentFile, agentContent);
|
|
612
|
+
logger.succeedSpinner("Agent file created");
|
|
613
|
+
if (answers.generateTests) {
|
|
614
|
+
logger.startSpinner("Creating test file...");
|
|
615
|
+
const testDir = path__default.default.join(cwd, "tests", "agents");
|
|
616
|
+
const testFile = path__default.default.join(testDir, `${answers.name}.test.ts`);
|
|
617
|
+
await ensureDir(testDir);
|
|
618
|
+
const testContent = generateTestContent(answers.name, answers.pattern);
|
|
619
|
+
await writeFile(testFile, testContent);
|
|
620
|
+
logger.succeedSpinner("Test file created");
|
|
621
|
+
}
|
|
622
|
+
logger.newLine();
|
|
623
|
+
logger.success(chalk__default.default.bold.green("\u2728 Agent created successfully!"));
|
|
624
|
+
logger.newLine();
|
|
625
|
+
logger.header("\u{1F4DD} Next Steps");
|
|
626
|
+
logger.list([
|
|
627
|
+
`Edit ${chalk__default.default.cyan(`src/agents/${answers.name}.ts`)} to customize your agent`,
|
|
628
|
+
answers.generateTests ? `Run ${chalk__default.default.cyan(`pnpm test tests/agents/${answers.name}.test.ts`)} to test your agent` : ""
|
|
629
|
+
].filter(Boolean));
|
|
630
|
+
} catch (error) {
|
|
631
|
+
logger.error(`Failed to create agent: ${error.message}`);
|
|
632
|
+
process.exit(1);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
function generateAgentContent(name, pattern, description) {
|
|
636
|
+
const patterns = {
|
|
637
|
+
"react": `import { createReActAgent } from '@agentforge/patterns';
|
|
638
|
+
import { ChatOpenAI } from '@langchain/openai';
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* ${description || `${name} agent using ReAct pattern`}
|
|
642
|
+
*/
|
|
643
|
+
export async function create${capitalize(name)}Agent() {
|
|
644
|
+
const model = new ChatOpenAI({
|
|
645
|
+
modelName: 'gpt-4',
|
|
646
|
+
temperature: 0,
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
const agent = createReActAgent({
|
|
650
|
+
model,
|
|
651
|
+
tools: [],
|
|
652
|
+
// Add your configuration here
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
return agent;
|
|
656
|
+
}
|
|
657
|
+
`,
|
|
658
|
+
"plan-execute": `import { createPlanExecuteAgent } from '@agentforge/patterns';
|
|
659
|
+
import { ChatOpenAI } from '@langchain/openai';
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* ${description || `${name} agent using Plan-Execute pattern`}
|
|
663
|
+
*/
|
|
664
|
+
export async function create${capitalize(name)}Agent() {
|
|
665
|
+
const model = new ChatOpenAI({
|
|
666
|
+
modelName: 'gpt-4',
|
|
667
|
+
temperature: 0,
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
const agent = createPlanExecuteAgent({
|
|
671
|
+
model,
|
|
672
|
+
tools: [],
|
|
673
|
+
// Add your configuration here
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
return agent;
|
|
677
|
+
}
|
|
678
|
+
`,
|
|
679
|
+
"reflection": `import { createReflectionAgent } from '@agentforge/patterns';
|
|
680
|
+
import { ChatOpenAI } from '@langchain/openai';
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* ${description || `${name} agent using Reflection pattern`}
|
|
684
|
+
*/
|
|
685
|
+
export async function create${capitalize(name)}Agent() {
|
|
686
|
+
const model = new ChatOpenAI({
|
|
687
|
+
modelName: 'gpt-4',
|
|
688
|
+
temperature: 0,
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
const agent = createReflectionAgent({
|
|
692
|
+
model,
|
|
693
|
+
// Add your configuration here
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
return agent;
|
|
697
|
+
}
|
|
698
|
+
`,
|
|
699
|
+
"multi-agent": `import { createMultiAgentSystem } from '@agentforge/patterns';
|
|
700
|
+
import { ChatOpenAI } from '@langchain/openai';
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* ${description || `${name} multi-agent system`}
|
|
704
|
+
*/
|
|
705
|
+
export async function create${capitalize(name)}System() {
|
|
706
|
+
const model = new ChatOpenAI({
|
|
707
|
+
modelName: 'gpt-4',
|
|
708
|
+
temperature: 0,
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
const system = createMultiAgentSystem({
|
|
712
|
+
model,
|
|
713
|
+
workers: [],
|
|
714
|
+
// Add your configuration here
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
return system;
|
|
718
|
+
}
|
|
719
|
+
`
|
|
720
|
+
};
|
|
721
|
+
return patterns[pattern] || patterns["react"];
|
|
722
|
+
}
|
|
723
|
+
function generateTestContent(name, pattern) {
|
|
724
|
+
return `import { describe, it, expect } from 'vitest';
|
|
725
|
+
import { create${capitalize(name)}${pattern === "multi-agent" ? "System" : "Agent"} } from '../../src/agents/${name}.js';
|
|
726
|
+
|
|
727
|
+
describe('${capitalize(name)} ${pattern === "multi-agent" ? "System" : "Agent"}', () => {
|
|
728
|
+
it('should create agent successfully', async () => {
|
|
729
|
+
const agent = await create${capitalize(name)}${pattern === "multi-agent" ? "System" : "Agent"}();
|
|
730
|
+
expect(agent).toBeDefined();
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
// Add more tests here
|
|
734
|
+
});
|
|
735
|
+
`;
|
|
736
|
+
}
|
|
737
|
+
function capitalize(str) {
|
|
738
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
739
|
+
}
|
|
740
|
+
async function agentListCommand(options) {
|
|
741
|
+
try {
|
|
742
|
+
logger.header("\u{1F4CB} List Agents");
|
|
743
|
+
const cwd = process.cwd();
|
|
744
|
+
const agentDir = path__default.default.join(cwd, "src", "agents");
|
|
745
|
+
const agentFiles = await findFiles("*.ts", agentDir);
|
|
746
|
+
if (agentFiles.length === 0) {
|
|
747
|
+
logger.warn("No agents found");
|
|
748
|
+
logger.info(`Create an agent with: ${chalk__default.default.cyan("agentforge agent:create <name>")}`);
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
logger.info(`Found ${chalk__default.default.cyan(agentFiles.length)} agent(s):
|
|
752
|
+
`);
|
|
753
|
+
for (const file of agentFiles) {
|
|
754
|
+
const agentName = path__default.default.basename(file, ".ts");
|
|
755
|
+
const agentPath = path__default.default.join(agentDir, file);
|
|
756
|
+
if (options.verbose) {
|
|
757
|
+
const content = await readFile(agentPath);
|
|
758
|
+
const pattern = extractPattern(content);
|
|
759
|
+
const description = extractDescription(content);
|
|
760
|
+
logger.info(chalk__default.default.bold.cyan(` ${agentName}`));
|
|
761
|
+
if (pattern) {
|
|
762
|
+
logger.info(` Pattern: ${pattern}`);
|
|
763
|
+
}
|
|
764
|
+
if (description) {
|
|
765
|
+
logger.info(` Description: ${description}`);
|
|
766
|
+
}
|
|
767
|
+
logger.info(` Path: ${chalk__default.default.gray(agentPath)}`);
|
|
768
|
+
logger.newLine();
|
|
769
|
+
} else {
|
|
770
|
+
logger.info(` \u2022 ${chalk__default.default.cyan(agentName)}`);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
if (!options.verbose) {
|
|
774
|
+
logger.newLine();
|
|
775
|
+
logger.info(`Use ${chalk__default.default.cyan("--verbose")} for more details`);
|
|
776
|
+
}
|
|
777
|
+
} catch (error) {
|
|
778
|
+
logger.error(`Failed to list agents: ${error.message}`);
|
|
779
|
+
process.exit(1);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
function extractPattern(content) {
|
|
783
|
+
const patterns = ["ReAct", "Plan-Execute", "Reflection", "Multi-Agent"];
|
|
784
|
+
for (const pattern of patterns) {
|
|
785
|
+
if (content.includes(`create${pattern.replace("-", "")}Agent`)) {
|
|
786
|
+
return pattern;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
return null;
|
|
790
|
+
}
|
|
791
|
+
function extractDescription(content) {
|
|
792
|
+
const match = content.match(/\/\*\*\s*\n\s*\*\s*(.+?)\s*\n/);
|
|
793
|
+
return match ? match[1] : null;
|
|
794
|
+
}
|
|
795
|
+
async function agentTestCommand(name, options) {
|
|
796
|
+
try {
|
|
797
|
+
logger.header("\u{1F9EA} Test Agent");
|
|
798
|
+
const cwd = process.cwd();
|
|
799
|
+
const testFile = path__default.default.join(cwd, "tests", "agents", `${name}.test.ts`);
|
|
800
|
+
if (!await pathExists(testFile)) {
|
|
801
|
+
logger.error(`Test file not found: ${testFile}`);
|
|
802
|
+
logger.info(`Create tests with: ${chalk__default.default.cyan(`agentforge agent:create ${name} --test`)}`);
|
|
803
|
+
process.exit(1);
|
|
804
|
+
}
|
|
805
|
+
logger.info(`Testing agent: ${chalk__default.default.cyan(name)}`);
|
|
806
|
+
logger.info(`Watch mode: ${options.watch ? "Yes" : "No"}`);
|
|
807
|
+
logger.newLine();
|
|
808
|
+
const packageManager = await detectPackageManager(cwd);
|
|
809
|
+
logger.startSpinner("Running tests...");
|
|
810
|
+
const testCommand2 = options.watch ? "test:watch" : "test";
|
|
811
|
+
process.env.TEST_FILE = testFile;
|
|
812
|
+
await runScript(cwd, testCommand2, packageManager);
|
|
813
|
+
logger.succeedSpinner("Tests completed");
|
|
814
|
+
} catch (error) {
|
|
815
|
+
logger.failSpinner("Tests failed");
|
|
816
|
+
logger.error(error.message);
|
|
817
|
+
process.exit(1);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
async function agentDeployCommand(name, options) {
|
|
821
|
+
try {
|
|
822
|
+
logger.header("\u{1F680} Deploy Agent");
|
|
823
|
+
logger.info(`Agent: ${chalk__default.default.cyan(name)}`);
|
|
824
|
+
logger.info(`Environment: ${chalk__default.default.cyan(options.environment || "production")}`);
|
|
825
|
+
logger.info(`Dry run: ${options.dryRun ? "Yes" : "No"}`);
|
|
826
|
+
logger.newLine();
|
|
827
|
+
if (options.dryRun) {
|
|
828
|
+
logger.warn("Dry run mode - no actual deployment will occur");
|
|
829
|
+
logger.newLine();
|
|
830
|
+
}
|
|
831
|
+
logger.startSpinner("Preparing deployment...");
|
|
832
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
833
|
+
logger.succeedSpinner("Deployment prepared");
|
|
834
|
+
if (!options.dryRun) {
|
|
835
|
+
logger.startSpinner("Deploying agent...");
|
|
836
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
837
|
+
logger.succeedSpinner("Agent deployed successfully");
|
|
838
|
+
}
|
|
839
|
+
logger.newLine();
|
|
840
|
+
logger.success(chalk__default.default.bold.green("\u2728 Deployment completed!"));
|
|
841
|
+
logger.newLine();
|
|
842
|
+
logger.info("Note: Actual deployment implementation coming soon");
|
|
843
|
+
logger.info("For now, please use the deployment templates in the templates/deployment directory");
|
|
844
|
+
} catch (error) {
|
|
845
|
+
logger.failSpinner("Deployment failed");
|
|
846
|
+
logger.error(error.message);
|
|
847
|
+
process.exit(1);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
async function toolCreateCommand(name, options) {
|
|
851
|
+
try {
|
|
852
|
+
logger.header("\u{1F527} Create Tool");
|
|
853
|
+
const answers = await promptToolSetup({
|
|
854
|
+
name,
|
|
855
|
+
category: options.category,
|
|
856
|
+
generateTests: options.test
|
|
857
|
+
});
|
|
858
|
+
logger.newLine();
|
|
859
|
+
logger.info(`Creating tool: ${chalk__default.default.cyan(answers.name)}`);
|
|
860
|
+
logger.info(`Category: ${chalk__default.default.cyan(answers.category)}`);
|
|
861
|
+
logger.newLine();
|
|
862
|
+
const cwd = process.cwd();
|
|
863
|
+
const toolDir = path__default.default.join(cwd, "src", "tools");
|
|
864
|
+
const toolFile = path__default.default.join(toolDir, `${answers.name}.ts`);
|
|
865
|
+
logger.startSpinner("Creating tool file...");
|
|
866
|
+
await ensureDir(toolDir);
|
|
867
|
+
const toolContent = generateToolContent(answers.name, answers.category, answers.description);
|
|
868
|
+
await writeFile(toolFile, toolContent);
|
|
869
|
+
logger.succeedSpinner("Tool file created");
|
|
870
|
+
if (answers.generateTests) {
|
|
871
|
+
logger.startSpinner("Creating test file...");
|
|
872
|
+
const testDir = path__default.default.join(cwd, "tests", "tools");
|
|
873
|
+
const testFile = path__default.default.join(testDir, `${answers.name}.test.ts`);
|
|
874
|
+
await ensureDir(testDir);
|
|
875
|
+
const testContent = generateTestContent2(answers.name);
|
|
876
|
+
await writeFile(testFile, testContent);
|
|
877
|
+
logger.succeedSpinner("Test file created");
|
|
878
|
+
}
|
|
879
|
+
logger.newLine();
|
|
880
|
+
logger.success(chalk__default.default.bold.green("\u2728 Tool created successfully!"));
|
|
881
|
+
logger.newLine();
|
|
882
|
+
logger.header("\u{1F4DD} Next Steps");
|
|
883
|
+
logger.list([
|
|
884
|
+
`Edit ${chalk__default.default.cyan(`src/tools/${answers.name}.ts`)} to implement your tool`,
|
|
885
|
+
answers.generateTests ? `Run ${chalk__default.default.cyan(`pnpm test tests/tools/${answers.name}.test.ts`)} to test your tool` : "",
|
|
886
|
+
`Register the tool in your agent's tool registry`
|
|
887
|
+
].filter(Boolean));
|
|
888
|
+
} catch (error) {
|
|
889
|
+
logger.error(`Failed to create tool: ${error.message}`);
|
|
890
|
+
process.exit(1);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
function generateToolContent(name, category, description) {
|
|
894
|
+
return `import { z } from 'zod';
|
|
895
|
+
import { createTool } from '@agentforge/core';
|
|
896
|
+
|
|
897
|
+
/**
|
|
898
|
+
* ${description}
|
|
899
|
+
* Category: ${category}
|
|
900
|
+
*/
|
|
901
|
+
export const ${name}Tool = createTool()
|
|
902
|
+
.name('${name}')
|
|
903
|
+
.description('${description}')
|
|
904
|
+
.category('${category}')
|
|
905
|
+
.schema(
|
|
906
|
+
z.object({
|
|
907
|
+
// Define your input schema here
|
|
908
|
+
input: z.string().describe('Input parameter'),
|
|
909
|
+
})
|
|
910
|
+
)
|
|
911
|
+
.implement(async ({ input }) => {
|
|
912
|
+
// Implement your tool logic here
|
|
913
|
+
return \`Processed: \${input}\`;
|
|
914
|
+
})
|
|
915
|
+
.build();
|
|
916
|
+
`;
|
|
917
|
+
}
|
|
918
|
+
function generateTestContent2(name) {
|
|
919
|
+
return `import { describe, it, expect } from 'vitest';
|
|
920
|
+
import { ${name}Tool } from '../../src/tools/${name}.js';
|
|
921
|
+
|
|
922
|
+
describe('${capitalize2(name)} Tool', () => {
|
|
923
|
+
it('should have correct metadata', () => {
|
|
924
|
+
expect(${name}Tool.name).toBe('${name}');
|
|
925
|
+
expect(${name}Tool.description).toBeDefined();
|
|
926
|
+
});
|
|
927
|
+
|
|
928
|
+
it('should execute successfully', async () => {
|
|
929
|
+
const result = await ${name}Tool.invoke({
|
|
930
|
+
input: 'test',
|
|
931
|
+
});
|
|
932
|
+
|
|
933
|
+
expect(result).toBeDefined();
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
// Add more tests here
|
|
937
|
+
});
|
|
938
|
+
`;
|
|
939
|
+
}
|
|
940
|
+
function capitalize2(str) {
|
|
941
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
942
|
+
}
|
|
943
|
+
async function toolListCommand(options) {
|
|
944
|
+
try {
|
|
945
|
+
logger.header("\u{1F4CB} List Tools");
|
|
946
|
+
const cwd = process.cwd();
|
|
947
|
+
const toolDir = path__default.default.join(cwd, "src", "tools");
|
|
948
|
+
const toolFiles = await findFiles("*.ts", toolDir);
|
|
949
|
+
if (toolFiles.length === 0) {
|
|
950
|
+
logger.warn("No tools found");
|
|
951
|
+
logger.info(`Create a tool with: ${chalk__default.default.cyan("agentforge tool:create <name>")}`);
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
let filteredTools = toolFiles;
|
|
955
|
+
if (options.category) {
|
|
956
|
+
filteredTools = [];
|
|
957
|
+
for (const file of toolFiles) {
|
|
958
|
+
const toolPath = path__default.default.join(toolDir, file);
|
|
959
|
+
const content = await readFile(toolPath);
|
|
960
|
+
const category = extractCategory(content);
|
|
961
|
+
if (category === options.category) {
|
|
962
|
+
filteredTools.push(file);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
if (filteredTools.length === 0) {
|
|
967
|
+
logger.warn(`No tools found in category: ${options.category}`);
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
logger.info(`Found ${chalk__default.default.cyan(filteredTools.length)} tool(s):
|
|
971
|
+
`);
|
|
972
|
+
for (const file of filteredTools) {
|
|
973
|
+
const toolName = path__default.default.basename(file, ".ts");
|
|
974
|
+
const toolPath = path__default.default.join(toolDir, file);
|
|
975
|
+
if (options.verbose) {
|
|
976
|
+
const content = await readFile(toolPath);
|
|
977
|
+
const category = extractCategory(content);
|
|
978
|
+
const description = extractDescription2(content);
|
|
979
|
+
logger.info(chalk__default.default.bold.cyan(` ${toolName}`));
|
|
980
|
+
if (category) {
|
|
981
|
+
logger.info(` Category: ${category}`);
|
|
982
|
+
}
|
|
983
|
+
if (description) {
|
|
984
|
+
logger.info(` Description: ${description}`);
|
|
985
|
+
}
|
|
986
|
+
logger.info(` Path: ${chalk__default.default.gray(toolPath)}`);
|
|
987
|
+
logger.newLine();
|
|
988
|
+
} else {
|
|
989
|
+
logger.info(` \u2022 ${chalk__default.default.cyan(toolName)}`);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
if (!options.verbose) {
|
|
993
|
+
logger.newLine();
|
|
994
|
+
logger.info(`Use ${chalk__default.default.cyan("--verbose")} for more details`);
|
|
995
|
+
}
|
|
996
|
+
} catch (error) {
|
|
997
|
+
logger.error(`Failed to list tools: ${error.message}`);
|
|
998
|
+
process.exit(1);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
function extractCategory(content) {
|
|
1002
|
+
const match = content.match(/Category:\s*(\w+)/);
|
|
1003
|
+
return match ? match[1] : null;
|
|
1004
|
+
}
|
|
1005
|
+
function extractDescription2(content) {
|
|
1006
|
+
const match = content.match(/\/\*\*\s*\n\s*\*\s*(.+?)\s*\n/);
|
|
1007
|
+
return match ? match[1] : null;
|
|
1008
|
+
}
|
|
1009
|
+
async function toolTestCommand(name, options) {
|
|
1010
|
+
try {
|
|
1011
|
+
logger.header("\u{1F9EA} Test Tool");
|
|
1012
|
+
const cwd = process.cwd();
|
|
1013
|
+
const testFile = path__default.default.join(cwd, "tests", "tools", `${name}.test.ts`);
|
|
1014
|
+
if (!await pathExists(testFile)) {
|
|
1015
|
+
logger.error(`Test file not found: ${testFile}`);
|
|
1016
|
+
logger.info(`Create tests with: ${chalk__default.default.cyan(`agentforge tool:create ${name} --test`)}`);
|
|
1017
|
+
process.exit(1);
|
|
1018
|
+
}
|
|
1019
|
+
logger.info(`Testing tool: ${chalk__default.default.cyan(name)}`);
|
|
1020
|
+
logger.info(`Watch mode: ${options.watch ? "Yes" : "No"}`);
|
|
1021
|
+
logger.newLine();
|
|
1022
|
+
const packageManager = await detectPackageManager(cwd);
|
|
1023
|
+
logger.startSpinner("Running tests...");
|
|
1024
|
+
const testCommand2 = options.watch ? "test:watch" : "test";
|
|
1025
|
+
process.env.TEST_FILE = testFile;
|
|
1026
|
+
await runScript(cwd, testCommand2, packageManager);
|
|
1027
|
+
logger.succeedSpinner("Tests completed");
|
|
1028
|
+
} catch (error) {
|
|
1029
|
+
logger.failSpinner("Tests failed");
|
|
1030
|
+
logger.error(error.message);
|
|
1031
|
+
process.exit(1);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
async function toolPublishCommand(name, options) {
|
|
1035
|
+
try {
|
|
1036
|
+
logger.header("\u{1F4E6} Publish Tool");
|
|
1037
|
+
logger.info(`Tool: ${chalk__default.default.cyan(name)}`);
|
|
1038
|
+
logger.info(`Tag: ${chalk__default.default.cyan(options.tag || "latest")}`);
|
|
1039
|
+
logger.info(`Dry run: ${options.dryRun ? "Yes" : "No"}`);
|
|
1040
|
+
logger.newLine();
|
|
1041
|
+
if (options.dryRun) {
|
|
1042
|
+
logger.warn("Dry run mode - no actual publishing will occur");
|
|
1043
|
+
logger.newLine();
|
|
1044
|
+
}
|
|
1045
|
+
const cwd = process.cwd();
|
|
1046
|
+
const packageManager = await detectPackageManager(cwd);
|
|
1047
|
+
logger.startSpinner("Running tests...");
|
|
1048
|
+
try {
|
|
1049
|
+
await runScript(cwd, "test", packageManager);
|
|
1050
|
+
logger.succeedSpinner("Tests passed");
|
|
1051
|
+
} catch (error) {
|
|
1052
|
+
logger.failSpinner("Tests failed");
|
|
1053
|
+
logger.error("Cannot publish tool with failing tests");
|
|
1054
|
+
process.exit(1);
|
|
1055
|
+
}
|
|
1056
|
+
logger.startSpinner("Building tool...");
|
|
1057
|
+
try {
|
|
1058
|
+
await runScript(cwd, "build", packageManager);
|
|
1059
|
+
logger.succeedSpinner("Build completed");
|
|
1060
|
+
} catch (error) {
|
|
1061
|
+
logger.failSpinner("Build failed");
|
|
1062
|
+
process.exit(1);
|
|
1063
|
+
}
|
|
1064
|
+
if (!options.dryRun) {
|
|
1065
|
+
logger.startSpinner("Publishing to npm...");
|
|
1066
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
1067
|
+
logger.succeedSpinner("Published to npm");
|
|
1068
|
+
}
|
|
1069
|
+
logger.newLine();
|
|
1070
|
+
logger.success(chalk__default.default.bold.green("\u2728 Tool published successfully!"));
|
|
1071
|
+
logger.newLine();
|
|
1072
|
+
logger.info("Note: Actual npm publishing implementation coming soon");
|
|
1073
|
+
logger.info("For now, please use npm publish manually");
|
|
1074
|
+
} catch (error) {
|
|
1075
|
+
logger.failSpinner("Publishing failed");
|
|
1076
|
+
logger.error(error.message);
|
|
1077
|
+
process.exit(1);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
// src/index.ts
|
|
1082
|
+
var program = new commander.Command();
|
|
1083
|
+
program.name("agentforge").description("CLI tool for AgentForge - scaffolding, development, and deployment").version("0.1.0");
|
|
1084
|
+
program.command("create <project-name>").description("Create a new AgentForge project").option("-t, --template <template>", "Project template (minimal, full, api, cli)", "minimal").option("-p, --package-manager <pm>", "Package manager (npm, pnpm, yarn)", "pnpm").option("--no-install", "Skip dependency installation").option("--no-git", "Skip git initialization").action(createCommand);
|
|
1085
|
+
program.command("dev").description("Start development server with hot reload").option("-p, --port <port>", "Port number", "3000").option("--no-open", "Do not open browser").action(devCommand);
|
|
1086
|
+
program.command("build").description("Build for production").option("--no-minify", "Skip minification").option("--no-sourcemap", "Skip sourcemap generation").action(buildCommand);
|
|
1087
|
+
program.command("test").description("Run tests with coverage").option("-w, --watch", "Watch mode").option("--ui", "Open test UI").option("--coverage", "Generate coverage report").action(testCommand);
|
|
1088
|
+
program.command("lint").description("Lint and format code").option("--fix", "Auto-fix issues").option("--no-format", "Skip formatting").action(lintCommand);
|
|
1089
|
+
var agent = program.command("agent").description("Manage agents");
|
|
1090
|
+
agent.command("create <name>").description("Create a new agent").option("-p, --pattern <pattern>", "Agent pattern (react, plan-execute, reflection, multi-agent)", "react").option("--no-test", "Skip test generation").action(agentCreateCommand);
|
|
1091
|
+
agent.command("list").description("List all agents").option("-v, --verbose", "Show detailed information").action(agentListCommand);
|
|
1092
|
+
agent.command("test <name>").description("Test a specific agent").option("-w, --watch", "Watch mode").action(agentTestCommand);
|
|
1093
|
+
agent.command("deploy <name>").description("Deploy an agent").option("-e, --environment <env>", "Deployment environment", "production").option("--dry-run", "Dry run without actual deployment").action(agentDeployCommand);
|
|
1094
|
+
var tool = program.command("tool").description("Manage tools");
|
|
1095
|
+
tool.command("create <name>").description("Create a new tool").option("-c, --category <category>", "Tool category (web, data, file, utility)", "utility").option("--no-test", "Skip test generation").action(toolCreateCommand);
|
|
1096
|
+
tool.command("list").description("List all tools").option("-c, --category <category>", "Filter by category").option("-v, --verbose", "Show detailed information").action(toolListCommand);
|
|
1097
|
+
tool.command("test <name>").description("Test a specific tool").option("-w, --watch", "Watch mode").action(toolTestCommand);
|
|
1098
|
+
tool.command("publish <name>").description("Publish a tool to npm").option("--tag <tag>", "npm tag", "latest").option("--dry-run", "Dry run without actual publishing").action(toolPublishCommand);
|
|
1099
|
+
program.exitOverride();
|
|
1100
|
+
async function run() {
|
|
1101
|
+
try {
|
|
1102
|
+
await program.parseAsync(process.argv);
|
|
1103
|
+
} catch (error) {
|
|
1104
|
+
if (error.code !== "commander.help" && error.code !== "commander.version") {
|
|
1105
|
+
console.error(chalk__default.default.red("Error:"), error.message);
|
|
1106
|
+
process.exit(1);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
exports.program = program;
|
|
1112
|
+
exports.run = run;
|
|
1113
|
+
//# sourceMappingURL=index.cjs.map
|
|
1114
|
+
//# sourceMappingURL=index.cjs.map
|