@tacuchi/agent-factory 0.3.0 → 0.4.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/bin/agent-factory.js +2 -0
- package/package.json +1 -45
- package/src/commands/create.js +21 -3
- package/src/core/stack-detector.js +34 -0
package/bin/agent-factory.js
CHANGED
|
@@ -38,6 +38,8 @@ program
|
|
|
38
38
|
.option('-s, --scope <path>', 'Repository path (for stack detection)')
|
|
39
39
|
.option('-o, --output <path>', 'Output directory (default: current dir)')
|
|
40
40
|
.option('-t, --target <target>', 'Target: claude, codex, all', 'all')
|
|
41
|
+
.option('--stack <csv>', 'Override detected stack (comma-separated)')
|
|
42
|
+
.option('--dry-run', 'Preview generated agent without writing files')
|
|
41
43
|
.option('--tools <tools>', 'Comma-separated tools: Read,Write,Edit,Bash')
|
|
42
44
|
.option('--specialists <list>', 'CSV list of specialist agent names (for coordinator role)')
|
|
43
45
|
.option('--repo-count <n>', 'Number of repos in workspace (for coordinator role)', parseInt)
|
package/package.json
CHANGED
|
@@ -1,45 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@tacuchi/agent-factory",
|
|
3
|
-
"version": "0.3.0",
|
|
4
|
-
"description": "CLI to create AI agents for Claude Code, Codex, Gemini CLI and more",
|
|
5
|
-
"bin": {
|
|
6
|
-
"agent-factory": "bin/agent-factory.js"
|
|
7
|
-
},
|
|
8
|
-
"files": [
|
|
9
|
-
"bin/",
|
|
10
|
-
"src/",
|
|
11
|
-
"templates/",
|
|
12
|
-
"README.md",
|
|
13
|
-
"LICENSE"
|
|
14
|
-
],
|
|
15
|
-
"engines": {
|
|
16
|
-
"node": ">=16"
|
|
17
|
-
},
|
|
18
|
-
"scripts": {
|
|
19
|
-
"test": "node --test tests/",
|
|
20
|
-
"start": "node bin/agent-factory.js"
|
|
21
|
-
},
|
|
22
|
-
"keywords": [
|
|
23
|
-
"claude-code",
|
|
24
|
-
"agents",
|
|
25
|
-
"codex",
|
|
26
|
-
"gemini",
|
|
27
|
-
"ai",
|
|
28
|
-
"cli",
|
|
29
|
-
"agent-factory"
|
|
30
|
-
],
|
|
31
|
-
"author": "tacuchi",
|
|
32
|
-
"license": "MIT",
|
|
33
|
-
"repository": {
|
|
34
|
-
"type": "git",
|
|
35
|
-
"url": "https://github.com/tacuchi/agent-factory"
|
|
36
|
-
},
|
|
37
|
-
"dependencies": {
|
|
38
|
-
"chalk": "^4.1.2",
|
|
39
|
-
"commander": "^11.1.0",
|
|
40
|
-
"fs-extra": "^11.2.0",
|
|
41
|
-
"inquirer": "^8.2.6",
|
|
42
|
-
"js-yaml": "^4.1.0",
|
|
43
|
-
"ora": "^5.4.1"
|
|
44
|
-
}
|
|
45
|
-
}
|
|
1
|
+
{"name":"@tacuchi/agent-factory","version":"0.4.0","description":"CLI to create AI agents for Claude Code, Codex, Gemini CLI and more","bin":{"agent-factory":"bin/agent-factory.js"},"files":["bin/","src/","templates/","README.md","LICENSE"],"engines":{"node":">=16"},"scripts":{"test":"node --test tests/*.test.js","start":"node bin/agent-factory.js"},"keywords":["claude-code","agents","codex","gemini","ai","cli","agent-factory"],"author":"tacuchi","license":"MIT","repository":{"type":"git","url":"https://github.com/tacuchi/agent-factory"},"dependencies":{"chalk":"^4.1.2","commander":"^11.1.0","fs-extra":"^11.2.0","inquirer":"^8.2.6","js-yaml":"^4.1.0","ora":"^5.4.1"}}
|
package/src/commands/create.js
CHANGED
|
@@ -10,7 +10,7 @@ async function runCreate(options = {}) {
|
|
|
10
10
|
const isInteractive = !options.name;
|
|
11
11
|
const config = isInteractive ? await askCreateOptions() : normalizeFlags(options);
|
|
12
12
|
|
|
13
|
-
const { name, role, model, scope, output, target, tools, specialists, repoCount, description, instructions } = config;
|
|
13
|
+
const { name, role, model, scope, output, target, tools, specialists, repoCount, description, instructions, stack, dryRun } = config;
|
|
14
14
|
|
|
15
15
|
const spin = spinner('Generating agent...').start();
|
|
16
16
|
|
|
@@ -21,7 +21,16 @@ async function runCreate(options = {}) {
|
|
|
21
21
|
spin.succeed('Custom agent generated');
|
|
22
22
|
} else {
|
|
23
23
|
let stackResult = { primaryTech: 'Generic', framework: '', verifyCommands: '', stackParts: [], stackCsv: 'Generic' };
|
|
24
|
-
if (
|
|
24
|
+
if (stack) {
|
|
25
|
+
const parts = stack.split(',').map(s => s.trim()).filter(Boolean);
|
|
26
|
+
stackResult = {
|
|
27
|
+
primaryTech: parts[0] || 'Generic',
|
|
28
|
+
framework: parts[1] || '',
|
|
29
|
+
verifyCommands: '',
|
|
30
|
+
stackParts: parts,
|
|
31
|
+
stackCsv: parts.join(', '),
|
|
32
|
+
};
|
|
33
|
+
} else if (scope) {
|
|
25
34
|
stackResult = await detect(scope);
|
|
26
35
|
}
|
|
27
36
|
|
|
@@ -61,6 +70,13 @@ async function runCreate(options = {}) {
|
|
|
61
70
|
if (target === 'claude' || target === 'all') targetDirs.push('.claude/agents/');
|
|
62
71
|
if (target === 'codex' || target === 'all') targetDirs.push('.agents/');
|
|
63
72
|
|
|
73
|
+
if (dryRun) {
|
|
74
|
+
log.info('--- DRY RUN: Agent preview ---');
|
|
75
|
+
console.log(body);
|
|
76
|
+
log.info('--- End preview ---');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
64
80
|
if (!options.yes && isInteractive) {
|
|
65
81
|
const confirmed = await confirmGeneration(name, targetDirs);
|
|
66
82
|
if (!confirmed) {
|
|
@@ -116,6 +132,8 @@ function normalizeFlags(options) {
|
|
|
116
132
|
repoCount: options.repoCount || 0,
|
|
117
133
|
description: options.description || '',
|
|
118
134
|
instructions: options.instructions || '',
|
|
135
|
+
stack: options.stack || '',
|
|
136
|
+
dryRun: options.dryRun || false,
|
|
119
137
|
};
|
|
120
138
|
}
|
|
121
139
|
|
|
@@ -141,4 +159,4 @@ async function resolveCustomBody(instructions, name, description) {
|
|
|
141
159
|
return `# ${name}\n\n${instructions}\n`;
|
|
142
160
|
}
|
|
143
161
|
|
|
144
|
-
module.exports = { runCreate };
|
|
162
|
+
module.exports = { runCreate, normalizeFlags, formatSpecialistList };
|
|
@@ -112,6 +112,20 @@ async function detect(repoPath) {
|
|
|
112
112
|
verifyCommands = 'npm run build, npm test';
|
|
113
113
|
stackParts.push('Node.js');
|
|
114
114
|
}
|
|
115
|
+
|
|
116
|
+
// Fallback: Node.js CLI (has bin field) or plain JS
|
|
117
|
+
if (!primaryTech && pkg) {
|
|
118
|
+
if (pkg.bin) {
|
|
119
|
+
primaryTech = 'Node.js';
|
|
120
|
+
framework = 'CLI';
|
|
121
|
+
verifyCommands = 'npm test';
|
|
122
|
+
stackParts.push('Node.js', 'CLI');
|
|
123
|
+
} else {
|
|
124
|
+
primaryTech = 'JavaScript';
|
|
125
|
+
verifyCommands = 'npm test';
|
|
126
|
+
stackParts.push('JavaScript');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
115
129
|
}
|
|
116
130
|
}
|
|
117
131
|
|
|
@@ -267,6 +281,26 @@ async function detect(repoPath) {
|
|
|
267
281
|
}
|
|
268
282
|
}
|
|
269
283
|
|
|
284
|
+
// --- Shell / Bash ---
|
|
285
|
+
if (!primaryTech) {
|
|
286
|
+
const shFiles = await findFiles(abs, ['.sh'], 1);
|
|
287
|
+
if (shFiles.length > 0) {
|
|
288
|
+
primaryTech = 'Bash';
|
|
289
|
+
framework = 'Shell';
|
|
290
|
+
verifyCommands = 'bash -n *.sh, shellcheck *.sh';
|
|
291
|
+
stackParts.push('Bash', 'Shell');
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// --- Makefile (standalone) ---
|
|
296
|
+
if (!primaryTech) {
|
|
297
|
+
if (await fs.pathExists(path.join(abs, 'Makefile'))) {
|
|
298
|
+
primaryTech = 'Make';
|
|
299
|
+
verifyCommands = 'make';
|
|
300
|
+
stackParts.push('Make');
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
270
304
|
// --- Supplementary ---
|
|
271
305
|
if (await fs.pathExists(path.join(abs, 'tsconfig.json'))) {
|
|
272
306
|
if (!stackParts.includes('TypeScript') && primaryTech !== 'TypeScript') {
|